feat: 增加ipynb渲染
This commit is contained in:
70
.vitepress/theme/css/jupyterlab/cells/inputarea.css
Normal file
70
.vitepress/theme/css/jupyterlab/cells/inputarea.css
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/* 源码地址:https://github.com/jupyterlab/jupyterlab/blob/master/packages/cells/style/inputarea.css */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Input
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* All input areas */
|
||||||
|
.jp-InputArea {
|
||||||
|
display: table;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-InputArea-editor {
|
||||||
|
display: table-cell;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
/* This is the non-active, default styling */
|
||||||
|
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
|
||||||
|
border-radius: 0;
|
||||||
|
background: var(--jp-cell-editor-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-InputPrompt {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: top;
|
||||||
|
width: var(--jp-cell-prompt-width);
|
||||||
|
color: var(--jp-cell-inprompt-font-color);
|
||||||
|
font-family: var(--jp-cell-prompt-font-family);
|
||||||
|
padding: var(--jp-code-padding);
|
||||||
|
letter-spacing: var(--jp-cell-prompt-letter-spacing);
|
||||||
|
opacity: var(--jp-cell-prompt-opacity);
|
||||||
|
line-height: var(--jp-code-line-height);
|
||||||
|
font-size: var(--jp-code-font-size);
|
||||||
|
border: var(--jp-border-width) solid transparent;
|
||||||
|
|
||||||
|
/* Right align prompt text, don't wrap to handle large prompt numbers */
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
/* Disable text selection */
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Mobile
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
@media only screen and (max-width: 760px) {
|
||||||
|
.jp-InputArea-editor {
|
||||||
|
display: table-row;
|
||||||
|
margin-left: var(--jp-notebook-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-InputPrompt {
|
||||||
|
display: table-row;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
237
.vitepress/theme/css/jupyterlab/cells/widget.css
Normal file
237
.vitepress/theme/css/jupyterlab/cells/widget.css
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
|
||||||
|
/* 源码地址:https://github.com/jupyterlab/jupyterlab/blob/master/packages/cells/style/widget.css */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Private CSS variables
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--jp-private-cell-scrolling-output-offset: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Cell
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-Cell {
|
||||||
|
padding: var(--jp-cell-padding);
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Common input/output
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-Cell-inputWrapper,
|
||||||
|
.jp-Cell-outputWrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
/* Added to reveal the box-shadow on the input and output collapsers. */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only input/output areas inside cells */
|
||||||
|
.jp-Cell-inputArea,
|
||||||
|
.jp-Cell-outputArea {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Collapser
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Make the output collapser disappear when there is not output, but do so
|
||||||
|
* in a manner that leaves it in the layout and preserves its width.
|
||||||
|
*/
|
||||||
|
.jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser {
|
||||||
|
border: none !important;
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser {
|
||||||
|
min-height: var(--jp-cell-collapser-min-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Output
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Put a space between input and output when there IS output */
|
||||||
|
.jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea {
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 24em;
|
||||||
|
margin-left: var(--jp-private-cell-scrolling-output-offset);
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea[style*='height'] {
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea::after {
|
||||||
|
content: ' ';
|
||||||
|
box-shadow: inset 0 0 6px 2px rgb(0 0 0 / 30%);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
margin-top: -50%;
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child {
|
||||||
|
padding-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt {
|
||||||
|
width:
|
||||||
|
calc(
|
||||||
|
var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| CodeCell
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| MarkdownCell
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-MarkdownOutput {
|
||||||
|
display: table-cell;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-left: var(--jp-code-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-MarkdownOutput.jp-RenderedHTMLCommon {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* collapseHeadingButton (show always if hiddenCellsButton is _not_ shown) */
|
||||||
|
.jp-collapseHeadingButton {
|
||||||
|
display: flex;
|
||||||
|
min-height: var(--jp-cell-collapser-min-height);
|
||||||
|
font-size: var(--jp-code-font-size);
|
||||||
|
position: absolute;
|
||||||
|
background-color: transparent;
|
||||||
|
background-size: 25px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position-x: center;
|
||||||
|
background-position-y: top;
|
||||||
|
background-image: var(--jp-icon-caret-down);
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-collapseHeadingButton.jp-mod-collapsed {
|
||||||
|
background-image: var(--jp-icon-caret-right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
set the container font size to match that of content
|
||||||
|
so that the nested collapse buttons have the right size
|
||||||
|
*/
|
||||||
|
.jp-MarkdownCell .jp-InputPrompt {
|
||||||
|
font-size: var(--jp-content-font-size1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Align collapseHeadingButton with cell top header
|
||||||
|
The font sizes are identical to the ones in packages/rendermime/style/base.css
|
||||||
|
*/
|
||||||
|
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='1'] {
|
||||||
|
font-size: var(--jp-content-font-size5);
|
||||||
|
background-position-y: calc(0.3 * var(--jp-content-font-size5));
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='2'] {
|
||||||
|
font-size: var(--jp-content-font-size4);
|
||||||
|
background-position-y: calc(0.3 * var(--jp-content-font-size4));
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='3'] {
|
||||||
|
font-size: var(--jp-content-font-size3);
|
||||||
|
background-position-y: calc(0.3 * var(--jp-content-font-size3));
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='4'] {
|
||||||
|
font-size: var(--jp-content-font-size2);
|
||||||
|
background-position-y: calc(0.3 * var(--jp-content-font-size2));
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='5'] {
|
||||||
|
font-size: var(--jp-content-font-size1);
|
||||||
|
background-position-y: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='6'] {
|
||||||
|
font-size: var(--jp-content-font-size0);
|
||||||
|
background-position-y: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* collapseHeadingButton (show only on (hover,active) if hiddenCellsButton is shown) */
|
||||||
|
.jp-Notebook.jp-mod-showHiddenCellsButton .jp-collapseHeadingButton {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook.jp-mod-showHiddenCellsButton :is(.jp-MarkdownCell:hover, .jp-mod-active) .jp-collapseHeadingButton {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* showHiddenCellsButton (only show if jp-mod-showHiddenCellsButton is set, which
|
||||||
|
is a consequence of the showHiddenCellsButton option in Notebook Settings) */
|
||||||
|
.jp-Notebook.jp-mod-showHiddenCellsButton .jp-showHiddenCellsButton {
|
||||||
|
margin-left: calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));
|
||||||
|
margin-top: var(--jp-code-padding);
|
||||||
|
border: 1px solid var(--jp-border-color2);
|
||||||
|
background-color: var(--jp-border-color3) !important;
|
||||||
|
color: var(--jp-content-font-color0) !important;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook.jp-mod-showHiddenCellsButton .jp-showHiddenCellsButton:hover {
|
||||||
|
background-color: var(--jp-border-color2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-showHiddenCellsButton {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Printing
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Using block instead of flex to allow the use of the break-inside CSS property for
|
||||||
|
cell outputs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.jp-Cell-inputWrapper,
|
||||||
|
.jp-Cell-outputWrapper {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
.vitepress/theme/css/jupyterlab/index.css
Normal file
7
.vitepress/theme/css/jupyterlab/index.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@import url('./lumino.widgets.widget.css');
|
||||||
|
@import url('./materialcolors.css');
|
||||||
|
@import url('./rendermine.base.css');
|
||||||
|
@import url('./output.area.base.css');
|
||||||
|
@import url('./cells/inputarea.css');
|
||||||
|
@import url('./cells/widget.css');
|
||||||
|
@import url('./notebook.base.css');
|
||||||
26
.vitepress/theme/css/jupyterlab/lumino.widgets.widget.css
Normal file
26
.vitepress/theme/css/jupyterlab/lumino.widgets.widget.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* 源码地址:https://github.com/jupyterlab/lumino/blob/main/packages/widgets/style/widget.css */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Jupyter Development Team.
|
||||||
|
* Distributed under the terms of the Modified BSD License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
||||||
|
|
|
||||||
|
| Distributed under the terms of the BSD 3-Clause License.
|
||||||
|
|
|
||||||
|
| The full license is in the file LICENSE, distributed with this software.
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.lm-Widget {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lm-Widget.lm-mod-hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
267
.vitepress/theme/css/jupyterlab/materialcolors.css
Normal file
267
.vitepress/theme/css/jupyterlab/materialcolors.css
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
/* 源码地址:https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/style/materialcolors.css */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Jupyter Development Team.
|
||||||
|
* Distributed under the terms of the Modified BSD License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* google-material-color v1.2.6
|
||||||
|
* https://github.com/danlevan/google-material-color
|
||||||
|
*/
|
||||||
|
:root {
|
||||||
|
--md-red-50: #ffebee;
|
||||||
|
--md-red-100: #ffcdd2;
|
||||||
|
--md-red-200: #ef9a9a;
|
||||||
|
--md-red-300: #e57373;
|
||||||
|
--md-red-400: #ef5350;
|
||||||
|
--md-red-500: #f44336;
|
||||||
|
--md-red-600: #e53935;
|
||||||
|
--md-red-700: #d32f2f;
|
||||||
|
--md-red-800: #c62828;
|
||||||
|
--md-red-900: #b71c1c;
|
||||||
|
--md-red-A100: #ff8a80;
|
||||||
|
--md-red-A200: #ff5252;
|
||||||
|
--md-red-A400: #ff1744;
|
||||||
|
--md-red-A700: #d50000;
|
||||||
|
--md-pink-50: #fce4ec;
|
||||||
|
--md-pink-100: #f8bbd0;
|
||||||
|
--md-pink-200: #f48fb1;
|
||||||
|
--md-pink-300: #f06292;
|
||||||
|
--md-pink-400: #ec407a;
|
||||||
|
--md-pink-500: #e91e63;
|
||||||
|
--md-pink-600: #d81b60;
|
||||||
|
--md-pink-700: #c2185b;
|
||||||
|
--md-pink-800: #ad1457;
|
||||||
|
--md-pink-900: #880e4f;
|
||||||
|
--md-pink-A100: #ff80ab;
|
||||||
|
--md-pink-A200: #ff4081;
|
||||||
|
--md-pink-A400: #f50057;
|
||||||
|
--md-pink-A700: #c51162;
|
||||||
|
--md-purple-50: #f3e5f5;
|
||||||
|
--md-purple-100: #e1bee7;
|
||||||
|
--md-purple-200: #ce93d8;
|
||||||
|
--md-purple-300: #ba68c8;
|
||||||
|
--md-purple-400: #ab47bc;
|
||||||
|
--md-purple-500: #9c27b0;
|
||||||
|
--md-purple-600: #8e24aa;
|
||||||
|
--md-purple-700: #7b1fa2;
|
||||||
|
--md-purple-800: #6a1b9a;
|
||||||
|
--md-purple-900: #4a148c;
|
||||||
|
--md-purple-A100: #ea80fc;
|
||||||
|
--md-purple-A200: #e040fb;
|
||||||
|
--md-purple-A400: #d500f9;
|
||||||
|
--md-purple-A700: #a0f;
|
||||||
|
--md-deep-purple-50: #ede7f6;
|
||||||
|
--md-deep-purple-100: #d1c4e9;
|
||||||
|
--md-deep-purple-200: #b39ddb;
|
||||||
|
--md-deep-purple-300: #9575cd;
|
||||||
|
--md-deep-purple-400: #7e57c2;
|
||||||
|
--md-deep-purple-500: #673ab7;
|
||||||
|
--md-deep-purple-600: #5e35b1;
|
||||||
|
--md-deep-purple-700: #512da8;
|
||||||
|
--md-deep-purple-800: #4527a0;
|
||||||
|
--md-deep-purple-900: #311b92;
|
||||||
|
--md-deep-purple-A100: #b388ff;
|
||||||
|
--md-deep-purple-A200: #7c4dff;
|
||||||
|
--md-deep-purple-A400: #651fff;
|
||||||
|
--md-deep-purple-A700: #6200ea;
|
||||||
|
--md-indigo-50: #e8eaf6;
|
||||||
|
--md-indigo-100: #c5cae9;
|
||||||
|
--md-indigo-200: #9fa8da;
|
||||||
|
--md-indigo-300: #7986cb;
|
||||||
|
--md-indigo-400: #5c6bc0;
|
||||||
|
--md-indigo-500: #3f51b5;
|
||||||
|
--md-indigo-600: #3949ab;
|
||||||
|
--md-indigo-700: #303f9f;
|
||||||
|
--md-indigo-800: #283593;
|
||||||
|
--md-indigo-900: #1a237e;
|
||||||
|
--md-indigo-A100: #8c9eff;
|
||||||
|
--md-indigo-A200: #536dfe;
|
||||||
|
--md-indigo-A400: #3d5afe;
|
||||||
|
--md-indigo-A700: #304ffe;
|
||||||
|
--md-blue-50: #e3f2fd;
|
||||||
|
--md-blue-100: #bbdefb;
|
||||||
|
--md-blue-200: #90caf9;
|
||||||
|
--md-blue-300: #64b5f6;
|
||||||
|
--md-blue-400: #42a5f5;
|
||||||
|
--md-blue-500: #2196f3;
|
||||||
|
--md-blue-600: #1e88e5;
|
||||||
|
--md-blue-700: #1976d2;
|
||||||
|
--md-blue-800: #1565c0;
|
||||||
|
--md-blue-900: #0d47a1;
|
||||||
|
--md-blue-A100: #82b1ff;
|
||||||
|
--md-blue-A200: #448aff;
|
||||||
|
--md-blue-A400: #2979ff;
|
||||||
|
--md-blue-A700: #2962ff;
|
||||||
|
--md-light-blue-50: #e1f5fe;
|
||||||
|
--md-light-blue-100: #b3e5fc;
|
||||||
|
--md-light-blue-200: #81d4fa;
|
||||||
|
--md-light-blue-300: #4fc3f7;
|
||||||
|
--md-light-blue-400: #29b6f6;
|
||||||
|
--md-light-blue-500: #03a9f4;
|
||||||
|
--md-light-blue-600: #039be5;
|
||||||
|
--md-light-blue-700: #0288d1;
|
||||||
|
--md-light-blue-800: #0277bd;
|
||||||
|
--md-light-blue-900: #01579b;
|
||||||
|
--md-light-blue-A100: #80d8ff;
|
||||||
|
--md-light-blue-A200: #40c4ff;
|
||||||
|
--md-light-blue-A400: #00b0ff;
|
||||||
|
--md-light-blue-A700: #0091ea;
|
||||||
|
--md-cyan-50: #e0f7fa;
|
||||||
|
--md-cyan-100: #b2ebf2;
|
||||||
|
--md-cyan-200: #80deea;
|
||||||
|
--md-cyan-300: #4dd0e1;
|
||||||
|
--md-cyan-400: #26c6da;
|
||||||
|
--md-cyan-500: #00bcd4;
|
||||||
|
--md-cyan-600: #00acc1;
|
||||||
|
--md-cyan-700: #0097a7;
|
||||||
|
--md-cyan-800: #00838f;
|
||||||
|
--md-cyan-900: #006064;
|
||||||
|
--md-cyan-A100: #84ffff;
|
||||||
|
--md-cyan-A200: #18ffff;
|
||||||
|
--md-cyan-A400: #00e5ff;
|
||||||
|
--md-cyan-A700: #00b8d4;
|
||||||
|
--md-teal-50: #e0f2f1;
|
||||||
|
--md-teal-100: #b2dfdb;
|
||||||
|
--md-teal-200: #80cbc4;
|
||||||
|
--md-teal-300: #4db6ac;
|
||||||
|
--md-teal-400: #26a69a;
|
||||||
|
--md-teal-500: #009688;
|
||||||
|
--md-teal-600: #00897b;
|
||||||
|
--md-teal-700: #00796b;
|
||||||
|
--md-teal-800: #00695c;
|
||||||
|
--md-teal-900: #004d40;
|
||||||
|
--md-teal-A100: #a7ffeb;
|
||||||
|
--md-teal-A200: #64ffda;
|
||||||
|
--md-teal-A400: #1de9b6;
|
||||||
|
--md-teal-A700: #00bfa5;
|
||||||
|
--md-green-50: #e8f5e9;
|
||||||
|
--md-green-100: #c8e6c9;
|
||||||
|
--md-green-200: #a5d6a7;
|
||||||
|
--md-green-300: #81c784;
|
||||||
|
--md-green-400: #66bb6a;
|
||||||
|
--md-green-500: #4caf50;
|
||||||
|
--md-green-600: #43a047;
|
||||||
|
--md-green-700: #388e3c;
|
||||||
|
--md-green-800: #2e7d32;
|
||||||
|
--md-green-900: #1b5e20;
|
||||||
|
--md-green-A100: #b9f6ca;
|
||||||
|
--md-green-A200: #69f0ae;
|
||||||
|
--md-green-A400: #00e676;
|
||||||
|
--md-green-A700: #00c853;
|
||||||
|
--md-light-green-50: #f1f8e9;
|
||||||
|
--md-light-green-100: #dcedc8;
|
||||||
|
--md-light-green-200: #c5e1a5;
|
||||||
|
--md-light-green-300: #aed581;
|
||||||
|
--md-light-green-400: #9ccc65;
|
||||||
|
--md-light-green-500: #8bc34a;
|
||||||
|
--md-light-green-600: #7cb342;
|
||||||
|
--md-light-green-700: #689f38;
|
||||||
|
--md-light-green-800: #558b2f;
|
||||||
|
--md-light-green-900: #33691e;
|
||||||
|
--md-light-green-A100: #ccff90;
|
||||||
|
--md-light-green-A200: #b2ff59;
|
||||||
|
--md-light-green-A400: #76ff03;
|
||||||
|
--md-light-green-A700: #64dd17;
|
||||||
|
--md-lime-50: #f9fbe7;
|
||||||
|
--md-lime-100: #f0f4c3;
|
||||||
|
--md-lime-200: #e6ee9c;
|
||||||
|
--md-lime-300: #dce775;
|
||||||
|
--md-lime-400: #d4e157;
|
||||||
|
--md-lime-500: #cddc39;
|
||||||
|
--md-lime-600: #c0ca33;
|
||||||
|
--md-lime-700: #afb42b;
|
||||||
|
--md-lime-800: #9e9d24;
|
||||||
|
--md-lime-900: #827717;
|
||||||
|
--md-lime-A100: #f4ff81;
|
||||||
|
--md-lime-A200: #eeff41;
|
||||||
|
--md-lime-A400: #c6ff00;
|
||||||
|
--md-lime-A700: #aeea00;
|
||||||
|
--md-yellow-50: #fffde7;
|
||||||
|
--md-yellow-100: #fff9c4;
|
||||||
|
--md-yellow-200: #fff59d;
|
||||||
|
--md-yellow-300: #fff176;
|
||||||
|
--md-yellow-400: #ffee58;
|
||||||
|
--md-yellow-500: #ffeb3b;
|
||||||
|
--md-yellow-600: #fdd835;
|
||||||
|
--md-yellow-700: #fbc02d;
|
||||||
|
--md-yellow-800: #f9a825;
|
||||||
|
--md-yellow-900: #f57f17;
|
||||||
|
--md-yellow-A100: #ffff8d;
|
||||||
|
--md-yellow-A200: #ff0;
|
||||||
|
--md-yellow-A400: #ffea00;
|
||||||
|
--md-yellow-A700: #ffd600;
|
||||||
|
--md-amber-50: #fff8e1;
|
||||||
|
--md-amber-100: #ffecb3;
|
||||||
|
--md-amber-200: #ffe082;
|
||||||
|
--md-amber-300: #ffd54f;
|
||||||
|
--md-amber-400: #ffca28;
|
||||||
|
--md-amber-500: #ffc107;
|
||||||
|
--md-amber-600: #ffb300;
|
||||||
|
--md-amber-700: #ffa000;
|
||||||
|
--md-amber-800: #ff8f00;
|
||||||
|
--md-amber-900: #ff6f00;
|
||||||
|
--md-amber-A100: #ffe57f;
|
||||||
|
--md-amber-A200: #ffd740;
|
||||||
|
--md-amber-A400: #ffc400;
|
||||||
|
--md-amber-A700: #ffab00;
|
||||||
|
--md-orange-50: #fff3e0;
|
||||||
|
--md-orange-100: #ffe0b2;
|
||||||
|
--md-orange-200: #ffcc80;
|
||||||
|
--md-orange-300: #ffb74d;
|
||||||
|
--md-orange-400: #ffa726;
|
||||||
|
--md-orange-500: #ff9800;
|
||||||
|
--md-orange-600: #fb8c00;
|
||||||
|
--md-orange-700: #f57c00;
|
||||||
|
--md-orange-800: #ef6c00;
|
||||||
|
--md-orange-900: #e65100;
|
||||||
|
--md-orange-A100: #ffd180;
|
||||||
|
--md-orange-A200: #ffab40;
|
||||||
|
--md-orange-A400: #ff9100;
|
||||||
|
--md-orange-A700: #ff6d00;
|
||||||
|
--md-deep-orange-50: #fbe9e7;
|
||||||
|
--md-deep-orange-100: #ffccbc;
|
||||||
|
--md-deep-orange-200: #ffab91;
|
||||||
|
--md-deep-orange-300: #ff8a65;
|
||||||
|
--md-deep-orange-400: #ff7043;
|
||||||
|
--md-deep-orange-500: #ff5722;
|
||||||
|
--md-deep-orange-600: #f4511e;
|
||||||
|
--md-deep-orange-700: #e64a19;
|
||||||
|
--md-deep-orange-800: #d84315;
|
||||||
|
--md-deep-orange-900: #bf360c;
|
||||||
|
--md-deep-orange-A100: #ff9e80;
|
||||||
|
--md-deep-orange-A200: #ff6e40;
|
||||||
|
--md-deep-orange-A400: #ff3d00;
|
||||||
|
--md-deep-orange-A700: #dd2c00;
|
||||||
|
--md-brown-50: #efebe9;
|
||||||
|
--md-brown-100: #d7ccc8;
|
||||||
|
--md-brown-200: #bcaaa4;
|
||||||
|
--md-brown-300: #a1887f;
|
||||||
|
--md-brown-400: #8d6e63;
|
||||||
|
--md-brown-500: #795548;
|
||||||
|
--md-brown-600: #6d4c41;
|
||||||
|
--md-brown-700: #5d4037;
|
||||||
|
--md-brown-800: #4e342e;
|
||||||
|
--md-brown-900: #3e2723;
|
||||||
|
--md-grey-50: #fafafa;
|
||||||
|
--md-grey-100: #f5f5f5;
|
||||||
|
--md-grey-200: #eee;
|
||||||
|
--md-grey-300: #e0e0e0;
|
||||||
|
--md-grey-400: #bdbdbd;
|
||||||
|
--md-grey-500: #9e9e9e;
|
||||||
|
--md-grey-600: #757575;
|
||||||
|
--md-grey-700: #616161;
|
||||||
|
--md-grey-800: #424242;
|
||||||
|
--md-grey-900: #212121;
|
||||||
|
--md-blue-grey-50: #eceff1;
|
||||||
|
--md-blue-grey-100: #cfd8dc;
|
||||||
|
--md-blue-grey-200: #b0bec5;
|
||||||
|
--md-blue-grey-300: #90a4ae;
|
||||||
|
--md-blue-grey-400: #78909c;
|
||||||
|
--md-blue-grey-500: #607d8b;
|
||||||
|
--md-blue-grey-600: #546e7a;
|
||||||
|
--md-blue-grey-700: #455a64;
|
||||||
|
--md-blue-grey-800: #37474f;
|
||||||
|
--md-blue-grey-900: #263238;
|
||||||
|
}
|
||||||
460
.vitepress/theme/css/jupyterlab/notebook.base.css
Normal file
460
.vitepress/theme/css/jupyterlab/notebook.base.css
Normal file
@@ -0,0 +1,460 @@
|
|||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
|
||||||
|
/* 源码地址:https://github.com/jupyterlab/jupyterlab/blob/master/packages/notebook/style/base.css */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| CSS variables
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--jp-side-by-side-output-size: 1fr;
|
||||||
|
--jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size);
|
||||||
|
--jp-private-notebook-dragImage-width: 304px;
|
||||||
|
--jp-private-notebook-dragImage-height: 36px;
|
||||||
|
--jp-private-notebook-selected-color: var(--md-blue-400);
|
||||||
|
--jp-private-notebook-active-color: var(--md-green-400);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Notebook
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-NotebookPanel {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-NotebookPanel.jp-Document {
|
||||||
|
min-width: 240px;
|
||||||
|
min-height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook {
|
||||||
|
padding: var(--jp-notebook-padding);
|
||||||
|
outline: none;
|
||||||
|
overflow: auto;
|
||||||
|
background: var(--jp-layout-color0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook.jp-mod-scrollPastEnd::after {
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
min-height: var(--jp-notebook-scroll-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-MainAreaWidget-ContainStrict .jp-Notebook * {
|
||||||
|
contain: strict;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook-render * {
|
||||||
|
contain: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook .jp-Cell {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook .jp-Cell .jp-InputPrompt {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Notebook state related styling
|
||||||
|
|
|
||||||
|
| The notebook and cells each have states, here are the possibilities:
|
||||||
|
|
|
||||||
|
| - Notebook
|
||||||
|
| - Command
|
||||||
|
| - Edit
|
||||||
|
| - Cell
|
||||||
|
| - None
|
||||||
|
| - Active (only one can be active)
|
||||||
|
| - Selected (the cells actions are applied to)
|
||||||
|
| - Multiselected (when multiple selected, the cursor)
|
||||||
|
| - No outputs
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Command or edit modes */
|
||||||
|
|
||||||
|
.jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt {
|
||||||
|
opacity: var(--jp-cell-prompt-not-active-opacity);
|
||||||
|
color: var(--jp-cell-prompt-not-active-font-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt {
|
||||||
|
opacity: var(--jp-cell-prompt-not-active-opacity);
|
||||||
|
color: var(--jp-cell-prompt-not-active-font-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cell is active */
|
||||||
|
.jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser {
|
||||||
|
background: var(--jp-brand-color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cell is dirty */
|
||||||
|
.jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt {
|
||||||
|
color: var(--jp-warn-color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt::before {
|
||||||
|
color: var(--jp-warn-color1);
|
||||||
|
content: '•';
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser {
|
||||||
|
background: var(--jp-warn-color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* collapser is hovered */
|
||||||
|
.jp-Notebook .jp-Cell .jp-Collapser:hover {
|
||||||
|
box-shadow: var(--jp-elevation-z2);
|
||||||
|
background: var(--jp-brand-color1);
|
||||||
|
opacity: var(--jp-cell-collapser-not-active-hover-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cell is active and collapser is hovered */
|
||||||
|
.jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover {
|
||||||
|
background: var(--jp-brand-color0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Command mode */
|
||||||
|
|
||||||
|
.jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected {
|
||||||
|
background: var(--jp-notebook-multiselected-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected) {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Edit mode */
|
||||||
|
|
||||||
|
.jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor {
|
||||||
|
border: var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);
|
||||||
|
box-shadow: var(--jp-input-box-shadow);
|
||||||
|
background-color: var(--jp-cell-editor-active-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Notebook drag and drop
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-Notebook-cell.jp-mod-dropSource {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Notebook-cell.jp-mod-dropTarget,
|
||||||
|
.jp-Notebook.jp-mod-commandMode .jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget {
|
||||||
|
border-top-color: var(--jp-private-notebook-selected-color);
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-dragImage {
|
||||||
|
display: block;
|
||||||
|
flex-direction: row;
|
||||||
|
width: var(--jp-private-notebook-dragImage-width);
|
||||||
|
height: var(--jp-private-notebook-dragImage-height);
|
||||||
|
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
|
||||||
|
background: var(--jp-cell-editor-background);
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-dragImage-singlePrompt {
|
||||||
|
box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-dragImage .jp-dragImage-content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
z-index: 2;
|
||||||
|
font-size: var(--jp-code-font-size);
|
||||||
|
font-family: var(--jp-code-font-family);
|
||||||
|
line-height: var(--jp-code-line-height);
|
||||||
|
padding: var(--jp-code-padding);
|
||||||
|
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
|
||||||
|
background: var(--jp-cell-editor-background-color);
|
||||||
|
color: var(--jp-content-font-color3);
|
||||||
|
text-align: left;
|
||||||
|
margin: 4px 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-dragImage .jp-dragImage-prompt {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 36px;
|
||||||
|
color: var(--jp-cell-inprompt-font-color);
|
||||||
|
padding: var(--jp-code-padding);
|
||||||
|
padding-left: 12px;
|
||||||
|
font-family: var(--jp-cell-prompt-font-family);
|
||||||
|
letter-spacing: var(--jp-cell-prompt-letter-spacing);
|
||||||
|
line-height: 1.9;
|
||||||
|
font-size: var(--jp-code-font-size);
|
||||||
|
border: var(--jp-border-width) solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-dragImage-multipleBack {
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
height: 32px;
|
||||||
|
width: 300px;
|
||||||
|
top: 8px;
|
||||||
|
left: 8px;
|
||||||
|
background: var(--jp-layout-color2);
|
||||||
|
border: var(--jp-border-width) solid var(--jp-input-border-color);
|
||||||
|
box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Cell toolbar
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-NotebookTools {
|
||||||
|
display: block;
|
||||||
|
min-width: var(--jp-sidebar-min-width);
|
||||||
|
color: var(--jp-ui-font-color1);
|
||||||
|
background: var(--jp-layout-color1);
|
||||||
|
|
||||||
|
/* This is needed so that all font sizing of children done in ems is
|
||||||
|
* relative to this base size */
|
||||||
|
font-size: var(--jp-ui-font-size1);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-NotebookTools-tool {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-ActiveCellTool {
|
||||||
|
padding: 12px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-ActiveCell-Content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-ActiveCellTool .jp-Cell-Content {
|
||||||
|
background: var(--jp-cell-editor-background);
|
||||||
|
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
|
||||||
|
border-radius: 0;
|
||||||
|
min-height: 29px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-ActiveCellTool .jp-InputPrompt {
|
||||||
|
min-width: calc(var(--jp-cell-prompt-width) * 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Cell-Content > pre {
|
||||||
|
padding: 5px 4px;
|
||||||
|
margin: 0;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-MetadataEditorTool {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RankedPanel > :not(:first-child) {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-KeySelector select.jp-mod-styled {
|
||||||
|
font-size: var(--jp-ui-font-size1);
|
||||||
|
color: var(--jp-ui-font-color0);
|
||||||
|
border: var(--jp-border-width) solid var(--jp-border-color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-KeySelector label,
|
||||||
|
.jp-MetadataEditorTool label,
|
||||||
|
.jp-NumberSetter label {
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-NotebookTools .jp-select-wrapper {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-NumberSetter input {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-NotebookTools .jp-Collapse {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Presentation Mode (.jp-mod-presentationMode)
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-mod-presentationMode .jp-Notebook {
|
||||||
|
--jp-content-font-size1: var(--jp-content-presentation-font-size1);
|
||||||
|
--jp-code-font-size: var(--jp-code-presentation-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,
|
||||||
|
.jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt {
|
||||||
|
flex: 0 0 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Side-by-side Mode (.jp-mod-sideBySide)
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell {
|
||||||
|
margin-top: 3em;
|
||||||
|
margin-bottom: 3em;
|
||||||
|
margin-left: 5%;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns:
|
||||||
|
minmax(0, 1fr) min-content minmax(
|
||||||
|
0,
|
||||||
|
var(--jp-side-by-side-output-size)
|
||||||
|
);
|
||||||
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
||||||
|
grid-template-areas:
|
||||||
|
'header header header'
|
||||||
|
'input handle output'
|
||||||
|
'footer footer footer';
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell {
|
||||||
|
grid-template-columns:
|
||||||
|
minmax(0, 1fr) min-content minmax(
|
||||||
|
0,
|
||||||
|
var(--jp-side-by-side-resized-cell)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader {
|
||||||
|
grid-area: header;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper {
|
||||||
|
grid-area: input;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper {
|
||||||
|
/* overwrite the default margin (no vertical separation needed in side by side move */
|
||||||
|
margin-top: 0;
|
||||||
|
grid-area: output;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter {
|
||||||
|
grid-area: footer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle {
|
||||||
|
grid-area: handle;
|
||||||
|
user-select: none;
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
cursor: ew-resize;
|
||||||
|
padding: 0 var(--jp-cell-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
background: var(--jp-border-color2);
|
||||||
|
height: 100%;
|
||||||
|
width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell .jp-CellResizeHandle::after {
|
||||||
|
background: var(--jp-border-color0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-CellResizeHandle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Placeholder
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-Cell-Placeholder {
|
||||||
|
padding-left: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Cell-Placeholder-wrapper {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: #e5e6e9 #dfe0e4 #d0d1d5;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
margin: 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Cell-Placeholder-wrapper-inner {
|
||||||
|
padding: 15px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Cell-Placeholder-wrapper-body {
|
||||||
|
background-repeat: repeat;
|
||||||
|
background-size: 50% auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Cell-Placeholder-wrapper-body div {
|
||||||
|
background: #f6f7f8;
|
||||||
|
background-image:
|
||||||
|
-webkit-linear-gradient(
|
||||||
|
left,
|
||||||
|
#f6f7f8 0%,
|
||||||
|
#edeef1 20%,
|
||||||
|
#f6f7f8 40%,
|
||||||
|
#f6f7f8 100%
|
||||||
|
);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 800px 104px;
|
||||||
|
height: 104px;
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
left: 15px;
|
||||||
|
top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-Cell-Placeholder-h1 {
|
||||||
|
top: 20px;
|
||||||
|
height: 20px;
|
||||||
|
left: 15px;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-Cell-Placeholder-h2 {
|
||||||
|
left: 15px;
|
||||||
|
top: 50px;
|
||||||
|
height: 10px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-Cell-Placeholder-content-1,
|
||||||
|
div.jp-Cell-Placeholder-content-2,
|
||||||
|
div.jp-Cell-Placeholder-content-3 {
|
||||||
|
left: 15px;
|
||||||
|
right: 15px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-Cell-Placeholder-content-1 {
|
||||||
|
top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-Cell-Placeholder-content-2 {
|
||||||
|
top: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-Cell-Placeholder-content-3 {
|
||||||
|
top: 140px;
|
||||||
|
}
|
||||||
276
.vitepress/theme/css/jupyterlab/output.area.base.css
Normal file
276
.vitepress/theme/css/jupyterlab/output.area.base.css
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
|
||||||
|
/* 源码地址:https://github.com/jupyterlab/jupyterlab/blob/master/packages/outputarea/style/base.css */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Main OutputArea
|
||||||
|
| OutputArea has a list of Outputs
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-OutputArea {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-child {
|
||||||
|
display: table;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputPrompt {
|
||||||
|
width: var(--jp-cell-prompt-width);
|
||||||
|
color: var(--jp-cell-outprompt-font-color);
|
||||||
|
font-family: var(--jp-cell-prompt-font-family);
|
||||||
|
padding: var(--jp-code-padding);
|
||||||
|
letter-spacing: var(--jp-cell-prompt-letter-spacing);
|
||||||
|
line-height: var(--jp-code-line-height);
|
||||||
|
font-size: var(--jp-code-font-size);
|
||||||
|
border: var(--jp-border-width) solid transparent;
|
||||||
|
opacity: var(--jp-cell-prompt-opacity);
|
||||||
|
|
||||||
|
/* Right align prompt text, don't wrap to handle large prompt numbers */
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
/* Disable text selection */
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-prompt {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-output {
|
||||||
|
display: table-cell;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
overflow: auto;
|
||||||
|
user-select: text;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Isolated output.
|
||||||
|
*/
|
||||||
|
.jp-OutputArea-output.jp-mod-isolated {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
When drag events occur, `lm-mod-override-cursor` is added to the body.
|
||||||
|
Because iframes steal all cursor events, the following two rules are necessary
|
||||||
|
to suppress pointer events while resize drags are occurring. There may be a
|
||||||
|
better solution to this problem.
|
||||||
|
*/
|
||||||
|
body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pre */
|
||||||
|
|
||||||
|
.jp-OutputArea-output pre {
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
word-break: break-all;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tables */
|
||||||
|
|
||||||
|
.jp-OutputArea-output.jp-RenderedHTMLCommon table {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* description lists */
|
||||||
|
|
||||||
|
.jp-OutputArea-output dl,
|
||||||
|
.jp-OutputArea-output dt,
|
||||||
|
.jp-OutputArea-output dd {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-output dl {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-output dt {
|
||||||
|
font-weight: bold;
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-output dd {
|
||||||
|
float: left;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-TrimmedOutputs pre {
|
||||||
|
background: var(--jp-layout-color3);
|
||||||
|
font-size: calc(var(--jp-code-font-size) * 1.4);
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the gutter in case of
|
||||||
|
* - nested output areas (e.g. in the case of output widgets)
|
||||||
|
* - mirrored output areas
|
||||||
|
*/
|
||||||
|
.jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide empty lines in the output area, for instance due to cleared widgets */
|
||||||
|
.jp-OutputArea-prompt:empty {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| executeResult is added to any Output-result for the display of the object
|
||||||
|
| returned by a cell
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-OutputArea-output.jp-OutputArea-executeResult {
|
||||||
|
margin-left: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text output with the Out[] prompt needs a top padding to match the
|
||||||
|
* alignment of the Out[] prompt itself.
|
||||||
|
*/
|
||||||
|
.jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output {
|
||||||
|
padding-top: var(--jp-code-padding);
|
||||||
|
border-top: var(--jp-border-width) solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| The Stdin output
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-OutputArea-stdin {
|
||||||
|
line-height: var(--jp-code-line-height);
|
||||||
|
padding-top: var(--jp-code-padding);
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Stdin-prompt {
|
||||||
|
color: var(--jp-content-font-color0);
|
||||||
|
padding-right: var(--jp-code-padding);
|
||||||
|
vertical-align: baseline;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Stdin-input {
|
||||||
|
font-family: var(--jp-code-font-family);
|
||||||
|
font-size: inherit;
|
||||||
|
color: inherit;
|
||||||
|
background-color: inherit;
|
||||||
|
width: 42%;
|
||||||
|
min-width: 200px;
|
||||||
|
|
||||||
|
/* make sure input baseline aligns with prompt */
|
||||||
|
vertical-align: baseline;
|
||||||
|
|
||||||
|
/* padding + margin = 0.5em between prompt and cursor */
|
||||||
|
padding: 0 0.25em;
|
||||||
|
margin: 0 0.25em;
|
||||||
|
flex: 0 0 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Stdin-input::placeholder {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Stdin-input:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-Stdin-input:focus::placeholder {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Output Area View
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-LinkedOutputView .jp-OutputArea {
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-LinkedOutputView .jp-OutputArea-output:only-child {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Printing
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.jp-OutputArea-child {
|
||||||
|
break-inside: avoid-page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Mobile
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
@media only screen and (max-width: 760px) {
|
||||||
|
.jp-OutputPrompt {
|
||||||
|
display: table-row;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-OutputArea-child .jp-OutputArea-output {
|
||||||
|
display: table-row;
|
||||||
|
margin-left: var(--jp-notebook-padding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trimmed outputs warning */
|
||||||
|
.jp-TrimmedOutputs > a {
|
||||||
|
margin: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-TrimmedOutputs > a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
634
.vitepress/theme/css/jupyterlab/rendermine.base.css
Normal file
634
.vitepress/theme/css/jupyterlab/rendermine.base.css
Normal file
@@ -0,0 +1,634 @@
|
|||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
|
||||||
|
/* 源码地址:https://github.com/jupyterlab/jupyterlab/blob/master/packages/rendermime/style/base.css */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| RenderedText
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
/* This is the padding value to fill the gaps between lines containing spans with background color. */
|
||||||
|
--jp-private-code-span-padding:
|
||||||
|
calc(
|
||||||
|
(var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: var(--jp-code-padding);
|
||||||
|
line-height: var(--jp-code-line-height);
|
||||||
|
font-family: var(--jp-code-font-family);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre,
|
||||||
|
.jp-RenderedJavaScript pre,
|
||||||
|
.jp-RenderedHTMLCommon pre {
|
||||||
|
color: var(--jp-content-font-color1);
|
||||||
|
font-size: var(--jp-code-font-size);
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre a:link {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--jp-content-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--jp-content-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre a:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--jp-content-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* console foregrounds and backgrounds */
|
||||||
|
.jp-RenderedText pre .ansi-black-fg {
|
||||||
|
color: #3e424d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-red-fg {
|
||||||
|
color: #e75c58;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-green-fg {
|
||||||
|
color: #00a250;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-yellow-fg {
|
||||||
|
color: #ddb62b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-blue-fg {
|
||||||
|
color: #208ffb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-magenta-fg {
|
||||||
|
color: #d160c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-cyan-fg {
|
||||||
|
color: #60c6c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-white-fg {
|
||||||
|
color: #c5c1b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-black-bg {
|
||||||
|
background-color: #3e424d;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-red-bg {
|
||||||
|
background-color: #e75c58;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-green-bg {
|
||||||
|
background-color: #00a250;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-yellow-bg {
|
||||||
|
background-color: #ddb62b;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-blue-bg {
|
||||||
|
background-color: #208ffb;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-magenta-bg {
|
||||||
|
background-color: #d160c4;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-cyan-bg {
|
||||||
|
background-color: #60c6c8;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-white-bg {
|
||||||
|
background-color: #c5c1b4;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-black-intense-fg {
|
||||||
|
color: #282c36;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-red-intense-fg {
|
||||||
|
color: #b22b31;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-green-intense-fg {
|
||||||
|
color: #007427;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-yellow-intense-fg {
|
||||||
|
color: #b27d12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-blue-intense-fg {
|
||||||
|
color: #0065ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-magenta-intense-fg {
|
||||||
|
color: #a03196;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-cyan-intense-fg {
|
||||||
|
color: #258f8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-white-intense-fg {
|
||||||
|
color: #a1a6b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-black-intense-bg {
|
||||||
|
background-color: #282c36;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-red-intense-bg {
|
||||||
|
background-color: #b22b31;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-green-intense-bg {
|
||||||
|
background-color: #007427;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-yellow-intense-bg {
|
||||||
|
background-color: #b27d12;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-blue-intense-bg {
|
||||||
|
background-color: #0065ca;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-magenta-intense-bg {
|
||||||
|
background-color: #a03196;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-cyan-intense-bg {
|
||||||
|
background-color: #258f8f;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-white-intense-bg {
|
||||||
|
background-color: #a1a6b2;
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-default-inverse-fg {
|
||||||
|
color: var(--jp-ui-inverse-font-color0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-default-inverse-bg {
|
||||||
|
background-color: var(--jp-inverse-layout-color0);
|
||||||
|
padding: var(--jp-private-code-span-padding) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText pre .ansi-underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedText[data-mime-type='application/vnd.jupyter.stderr'] {
|
||||||
|
background: var(--jp-rendermime-error-background);
|
||||||
|
padding-top: var(--jp-code-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| RenderedLatex
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-RenderedLatex {
|
||||||
|
color: var(--jp-content-font-color1);
|
||||||
|
font-size: var(--jp-content-font-size1);
|
||||||
|
line-height: var(--jp-content-line-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left-justify outputs. */
|
||||||
|
.jp-OutputArea-output.jp-RenderedLatex {
|
||||||
|
padding: var(--jp-code-padding);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| RenderedHTML
|
||||||
|
|---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon {
|
||||||
|
color: var(--jp-content-font-color1);
|
||||||
|
font-family: var(--jp-content-font-family);
|
||||||
|
font-size: var(--jp-content-font-size1);
|
||||||
|
line-height: var(--jp-content-line-height);
|
||||||
|
|
||||||
|
/* Give a bit more R padding on Markdown text to keep line lengths reasonable */
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon u {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon a:link {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--jp-content-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--jp-content-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon a:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--jp-content-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings */
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h1,
|
||||||
|
.jp-RenderedHTMLCommon h2,
|
||||||
|
.jp-RenderedHTMLCommon h3,
|
||||||
|
.jp-RenderedHTMLCommon h4,
|
||||||
|
.jp-RenderedHTMLCommon h5,
|
||||||
|
.jp-RenderedHTMLCommon h6 {
|
||||||
|
line-height: var(--jp-content-heading-line-height);
|
||||||
|
font-weight: var(--jp-content-heading-font-weight);
|
||||||
|
font-style: normal;
|
||||||
|
margin:
|
||||||
|
var(--jp-content-heading-margin-top) 0
|
||||||
|
var(--jp-content-heading-margin-bottom) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h1:first-child,
|
||||||
|
.jp-RenderedHTMLCommon h2:first-child,
|
||||||
|
.jp-RenderedHTMLCommon h3:first-child,
|
||||||
|
.jp-RenderedHTMLCommon h4:first-child,
|
||||||
|
.jp-RenderedHTMLCommon h5:first-child,
|
||||||
|
.jp-RenderedHTMLCommon h6:first-child {
|
||||||
|
margin-top: calc(0.5 * var(--jp-content-heading-margin-top));
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h1:last-child,
|
||||||
|
.jp-RenderedHTMLCommon h2:last-child,
|
||||||
|
.jp-RenderedHTMLCommon h3:last-child,
|
||||||
|
.jp-RenderedHTMLCommon h4:last-child,
|
||||||
|
.jp-RenderedHTMLCommon h5:last-child,
|
||||||
|
.jp-RenderedHTMLCommon h6:last-child {
|
||||||
|
margin-bottom: calc(0.5 * var(--jp-content-heading-margin-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h1 {
|
||||||
|
font-size: var(--jp-content-font-size5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h2 {
|
||||||
|
font-size: var(--jp-content-font-size4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h3 {
|
||||||
|
font-size: var(--jp-content-font-size3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h4 {
|
||||||
|
font-size: var(--jp-content-font-size2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h5 {
|
||||||
|
font-size: var(--jp-content-font-size1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon h6 {
|
||||||
|
font-size: var(--jp-content-font-size0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lists */
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ul:not(.list-inline),
|
||||||
|
.jp-RenderedHTMLCommon ol:not(.list-inline) {
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ul {
|
||||||
|
list-style: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ul ul {
|
||||||
|
list-style: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ul ul ul {
|
||||||
|
list-style: circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ol {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ol ol {
|
||||||
|
list-style: upper-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ol ol ol {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ol ol ol ol {
|
||||||
|
list-style: lower-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ol ol ol ol ol {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ol,
|
||||||
|
.jp-RenderedHTMLCommon ul {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon ul ul,
|
||||||
|
.jp-RenderedHTMLCommon ul ol,
|
||||||
|
.jp-RenderedHTMLCommon ol ul,
|
||||||
|
.jp-RenderedHTMLCommon ol ol {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon hr {
|
||||||
|
color: var(--jp-border-color2);
|
||||||
|
background-color: var(--jp-border-color1);
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon > pre {
|
||||||
|
margin: 1.5em 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon pre,
|
||||||
|
.jp-RenderedHTMLCommon code {
|
||||||
|
border: 0;
|
||||||
|
background-color: var(--jp-layout-color0);
|
||||||
|
color: var(--jp-content-font-color1);
|
||||||
|
font-family: var(--jp-code-font-family);
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: var(--jp-code-line-height);
|
||||||
|
padding: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon :not(pre) > code {
|
||||||
|
background-color: var(--jp-layout-color2);
|
||||||
|
padding: 1px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
border: none;
|
||||||
|
color: var(--jp-ui-font-color1);
|
||||||
|
font-size: var(--jp-ui-font-size1);
|
||||||
|
table-layout: fixed;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon thead {
|
||||||
|
border-bottom: var(--jp-border-width) solid var(--jp-border-color1);
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon td,
|
||||||
|
.jp-RenderedHTMLCommon th,
|
||||||
|
.jp-RenderedHTMLCommon tr {
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 0.5em;
|
||||||
|
line-height: normal;
|
||||||
|
white-space: normal;
|
||||||
|
max-width: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedMarkdown.jp-RenderedHTMLCommon td,
|
||||||
|
.jp-RenderedMarkdown.jp-RenderedHTMLCommon th {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon td,
|
||||||
|
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon th,
|
||||||
|
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon tr {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon tbody tr:nth-child(odd) {
|
||||||
|
background: var(--jp-layout-color0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon tbody tr:nth-child(even) {
|
||||||
|
background: var(--jp-rendermime-table-row-background) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon tbody tr:hover {
|
||||||
|
background: var(--jp-rendermime-table-row-hover-background) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon p {
|
||||||
|
text-align: left;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon img {
|
||||||
|
-moz-force-broken-image-icon: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restrict to direct children as other images could be nested in other content. */
|
||||||
|
.jp-RenderedHTMLCommon > img {
|
||||||
|
display: block;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change color behind transparent images if they need it... */
|
||||||
|
[data-jp-theme-light='false'] .jp-RenderedImage img.jp-needs-light-background {
|
||||||
|
background-color: var(--jp-inverse-layout-color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-jp-theme-light='true'] .jp-RenderedImage img.jp-needs-dark-background {
|
||||||
|
background-color: var(--jp-inverse-layout-color1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon img,
|
||||||
|
.jp-RenderedImage img,
|
||||||
|
.jp-RenderedHTMLCommon svg,
|
||||||
|
.jp-RenderedSVG svg {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon img.jp-mod-unconfined,
|
||||||
|
.jp-RenderedImage img.jp-mod-unconfined,
|
||||||
|
.jp-RenderedHTMLCommon svg.jp-mod-unconfined,
|
||||||
|
.jp-RenderedSVG svg.jp-mod-unconfined {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert {
|
||||||
|
padding: var(--jp-notebook-padding);
|
||||||
|
border: var(--jp-border-width) solid transparent;
|
||||||
|
border-radius: var(--jp-border-radius);
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-info {
|
||||||
|
color: var(--jp-info-color0);
|
||||||
|
background-color: var(--jp-info-color3);
|
||||||
|
border-color: var(--jp-info-color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-info hr {
|
||||||
|
border-color: var(--jp-info-color3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-info > p:last-child,
|
||||||
|
.jp-RenderedHTMLCommon .alert-info > ul:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-warning {
|
||||||
|
color: var(--jp-warn-color0);
|
||||||
|
background-color: var(--jp-warn-color3);
|
||||||
|
border-color: var(--jp-warn-color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-warning hr {
|
||||||
|
border-color: var(--jp-warn-color3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-warning > p:last-child,
|
||||||
|
.jp-RenderedHTMLCommon .alert-warning > ul:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-success {
|
||||||
|
color: var(--jp-success-color0);
|
||||||
|
background-color: var(--jp-success-color3);
|
||||||
|
border-color: var(--jp-success-color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-success hr {
|
||||||
|
border-color: var(--jp-success-color3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-success > p:last-child,
|
||||||
|
.jp-RenderedHTMLCommon .alert-success > ul:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-danger {
|
||||||
|
color: var(--jp-error-color0);
|
||||||
|
background-color: var(--jp-error-color3);
|
||||||
|
border-color: var(--jp-error-color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-danger hr {
|
||||||
|
border-color: var(--jp-error-color3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon .alert-danger > p:last-child,
|
||||||
|
.jp-RenderedHTMLCommon .alert-danger > ul:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon blockquote {
|
||||||
|
margin: 1em 2em;
|
||||||
|
padding: 0 1em;
|
||||||
|
border-left: 5px solid var(--jp-border-color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
a.jp-InternalAnchorLink {
|
||||||
|
visibility: hidden;
|
||||||
|
margin-left: 8px;
|
||||||
|
color: var(--md-blue-800);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover .jp-InternalAnchorLink,
|
||||||
|
h2:hover .jp-InternalAnchorLink,
|
||||||
|
h3:hover .jp-InternalAnchorLink,
|
||||||
|
h4:hover .jp-InternalAnchorLink,
|
||||||
|
h5:hover .jp-InternalAnchorLink,
|
||||||
|
h6:hover .jp-InternalAnchorLink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-RenderedHTMLCommon kbd {
|
||||||
|
background-color: var(--jp-rendermime-table-row-background);
|
||||||
|
border: 1px solid var(--jp-border-color0);
|
||||||
|
border-bottom-color: var(--jp-border-color2);
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
display: inline-block;
|
||||||
|
font-size: var(--jp-ui-font-size0);
|
||||||
|
line-height: 1em;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Most direct children of .jp-RenderedHTMLCommon have a margin-bottom of 1.0.
|
||||||
|
* At the bottom of cells this is a bit too much as there is also spacing
|
||||||
|
* between cells. Going all the way to 0 gets too tight between markdown and
|
||||||
|
* code cells.
|
||||||
|
*/
|
||||||
|
.jp-RenderedHTMLCommon > *:last-child {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mimeType-highlight {
|
||||||
|
background-color:
|
||||||
|
var(
|
||||||
|
--jp-search-unselected-match-background-color
|
||||||
|
) !important;
|
||||||
|
color: var(--jp-search-unselected-match-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-mod-selected.jp-mimeType-highlight {
|
||||||
|
background-color: var(--jp-search-selected-match-background-color) !important;
|
||||||
|
color: var(--jp-search-selected-match-color) !important;
|
||||||
|
}
|
||||||
@@ -151,3 +151,28 @@ mjx-container {
|
|||||||
--vp-home-hero-image-background-image: transparent;
|
--vp-home-hero-image-background-image: transparent;
|
||||||
--vp-home-hero-image-filter: '';
|
--vp-home-hero-image-filter: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jp-MarkdownOutput{
|
||||||
|
color: #3c3c43 !important;
|
||||||
|
font-weight: 400 !important;
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .jp-MarkdownOutput{
|
||||||
|
color: #dfdfd7 !important;
|
||||||
|
font-family: 'Noto Sans SC', 'Noto Color Emoji', sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jp-InputArea-editor{
|
||||||
|
border-radius: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-content{
|
||||||
|
font-family: 'Noto Sans Mono', sans-serif, monospace, consolas !important;
|
||||||
|
background-color: #f6f6f7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .cm-content{
|
||||||
|
font-family: 'Noto Sans Mono', sans-serif, monospace, consolas !important;
|
||||||
|
/* background-color: #161618 !important; */
|
||||||
|
}
|
||||||
19
components/RenderJupyterNotebook.vue
Normal file
19
components/RenderJupyterNotebook.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="NotebookFragment" class="notebook-fragment" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Notebook } from "../utils/index";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "RenderJupyterNotebook",
|
||||||
|
props: {
|
||||||
|
notebook: { required: true, type: Object },
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
const notebook = new Notebook(this.notebook, false);
|
||||||
|
const fragment = await notebook.render();
|
||||||
|
this.$refs.NotebookFragment.appendChild(fragment);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
18
notebook.md
Normal file
18
notebook.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<div class="home">
|
||||||
|
<RenderJupyterNotebook :notebook="notebook" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import RenderJupyterNotebook from "./components/RenderJupyterNotebook.vue";
|
||||||
|
import example from "./特征工程.json";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "HomeView",
|
||||||
|
components: { RenderJupyterNotebook },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
notebook: example,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
3513
package-lock.json
generated
3513
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,13 @@
|
|||||||
"docs:build": "vitepress build",
|
"docs:build": "vitepress build",
|
||||||
"docs:preview": "vitepress preview"
|
"docs:preview": "vitepress preview"
|
||||||
},
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/lang-python": "^6.1.2",
|
||||||
|
"@codemirror/lang-sql": "^6.4.1",
|
||||||
|
"@jupyterlab/mathjax2": "^3.6.3",
|
||||||
|
"@jupyterlab/theme-light-extension": "^3.6.3",
|
||||||
|
"markdown-it": "^13.0.1"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"markdown-it-mathjax3": "^4.3.2",
|
"markdown-it-mathjax3": "^4.3.2",
|
||||||
"vitepress": "^1.0.0-alpha.73"
|
"vitepress": "^1.0.0-alpha.73"
|
||||||
|
|||||||
1
utils/index.js
Normal file
1
utils/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from "./notebook";
|
||||||
50
utils/notebook/codemirror.js
Normal file
50
utils/notebook/codemirror.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* 调用 codemirror 插件渲染code,并调用 jupyterlab 的 codemirror 主题样式做渲染
|
||||||
|
* codemirror 插件: https://codemirror.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { EditorState } from "@codemirror/state";
|
||||||
|
import { EditorView } from "@codemirror/view";
|
||||||
|
import { python } from "@codemirror/lang-python";
|
||||||
|
import { sql } from "@codemirror/lang-sql";
|
||||||
|
import { Theme } from "./codemirror.theme";
|
||||||
|
|
||||||
|
// Codemirror 扩展配置
|
||||||
|
const extensionsConfig = [
|
||||||
|
EditorState.readOnly.of(true),
|
||||||
|
EditorView.editable.of(false),
|
||||||
|
Theme.getTheme("jupyter"), // 主题引入
|
||||||
|
|
||||||
|
/* 引入所需的编程语言 START */
|
||||||
|
python(),
|
||||||
|
sql(),
|
||||||
|
/* 引入所需的编程语言 END */
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用codemirror插件渲染code
|
||||||
|
*
|
||||||
|
* @param {string} codeString 需要渲染的code字符串
|
||||||
|
* @param {Element} parent 父元素,渲染成功后得元素将作为其的子元素
|
||||||
|
* @returns {Element} 渲染完成后的父元素
|
||||||
|
*/
|
||||||
|
export function createCodemirror(codeString, parent) {
|
||||||
|
if (codeString instanceof Array) codeString = codeString.join("");
|
||||||
|
if (typeof codeString !== "string")
|
||||||
|
throw "Function createCodemirror: 参数 codeString 必须是字符串!";
|
||||||
|
if (!parent) console.warn("Function createCodemirror: 参数 parent 不能为空");
|
||||||
|
if (!("appendChild" in document.body)) {
|
||||||
|
console.warn(
|
||||||
|
"Function createCodemirror: 参数 parent 类型错误,需为HTML元素"
|
||||||
|
);
|
||||||
|
codeString = document.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EditorView({
|
||||||
|
state: EditorState.create({
|
||||||
|
doc: codeString || "",
|
||||||
|
extensions: extensionsConfig,
|
||||||
|
}),
|
||||||
|
parent: parent || document.body,
|
||||||
|
});
|
||||||
|
}
|
||||||
180
utils/notebook/codemirror.theme.js
Normal file
180
utils/notebook/codemirror.theme.js
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
// Copyright (c) Jupyter Development Team.
|
||||||
|
// Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本文件为 Jupyter lab 源码。
|
||||||
|
* 用于设置 codemirror 相关的主题,提供了 codemirror 以及 jupyter 两种主题。其中 jupyter 为默认主题
|
||||||
|
*
|
||||||
|
* 源码TS版:https://github.com/jupyterlab/jupyterlab/blob/master/packages/codemirror/src/editortheme.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
defaultHighlightStyle,
|
||||||
|
HighlightStyle,
|
||||||
|
syntaxHighlighting,
|
||||||
|
} from "@codemirror/language";
|
||||||
|
import { EditorView } from "@codemirror/view";
|
||||||
|
import { tags as t } from "@lezer/highlight";
|
||||||
|
export const jupyterEditorTheme = EditorView.theme({
|
||||||
|
/**
|
||||||
|
* CodeMirror themes are handling the background/color in this way. This works
|
||||||
|
* fine for CodeMirror editors outside the notebook, but the notebook styles
|
||||||
|
* these things differently.
|
||||||
|
*/
|
||||||
|
"&": {
|
||||||
|
background: "var(--jp-layout-color0)",
|
||||||
|
color: "var(--jp-content-font-color1)",
|
||||||
|
},
|
||||||
|
/* In the notebook, we want this styling to be handled by its container */
|
||||||
|
".jp-CodeConsole &, .jp-Notebook &": {
|
||||||
|
background: "transparent",
|
||||||
|
},
|
||||||
|
".cm-content": {
|
||||||
|
caretColor: "var(--jp-editor-cursor-color)",
|
||||||
|
},
|
||||||
|
".cm-cursor, .cm-dropCursor": {
|
||||||
|
borderLeft:
|
||||||
|
"var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)",
|
||||||
|
},
|
||||||
|
".cm-selectionBackground, .cm-content ::selection": {
|
||||||
|
backgroundColor: "var(--jp-editor-selected-background)",
|
||||||
|
},
|
||||||
|
"&.cm-focused .cm-selectionBackground": {
|
||||||
|
backgroundColor: "var(--jp-editor-selected-focused-background)",
|
||||||
|
},
|
||||||
|
".cm-gutters": {
|
||||||
|
borderRight: "1px solid var(--jp-border-color2)",
|
||||||
|
backgroundColor: "var(--jp-layout-color2)",
|
||||||
|
},
|
||||||
|
".cm-gutter, .cm-activeLine": {
|
||||||
|
backgroundColor: "var(--jp-layout-color2)",
|
||||||
|
},
|
||||||
|
".cm-searchMatch": {
|
||||||
|
backgroundColor: "var(--jp-search-unselected-match-background-color)",
|
||||||
|
color: "var(--jp-search-unselected-match-color)",
|
||||||
|
},
|
||||||
|
".cm-searchMatch.cm-searchMatch-selected": {
|
||||||
|
backgroundColor:
|
||||||
|
"var(--jp-search-selected-match-background-color) !important",
|
||||||
|
color: "var(--jp-search-selected-match-color) !important",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// The list of available tags for syntax highlighting is available at
|
||||||
|
// https://lezer.codemirror.net/docs/ref/#highlight.tags
|
||||||
|
export const jupyterHighlightStyle = HighlightStyle.define([
|
||||||
|
// Order matters - a rule will override the previous ones; important for example for in headings styles.
|
||||||
|
{ tag: t.meta, color: "var(--jp-mirror-editor-meta-color)" },
|
||||||
|
{ tag: t.heading, color: "var(--jp-mirror-editor-header-color)" },
|
||||||
|
{
|
||||||
|
tag: [t.heading1, t.heading2, t.heading3, t.heading4],
|
||||||
|
color: "var(--jp-mirror-editor-header-color)",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: t.keyword,
|
||||||
|
color: "var(--jp-mirror-editor-keyword-color)",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
{ tag: t.atom, color: "var(--jp-mirror-editor-atom-color)" },
|
||||||
|
{ tag: t.number, color: "var(--jp-mirror-editor-number-color)" },
|
||||||
|
{
|
||||||
|
tag: [t.definition(t.name), t.function(t.definition(t.variableName))],
|
||||||
|
color: "var(--jp-mirror-editor-def-color)",
|
||||||
|
},
|
||||||
|
{ tag: t.variableName, color: "var(--jp-mirror-editor-variable-color)" },
|
||||||
|
{
|
||||||
|
tag: [t.special(t.variableName), t.self],
|
||||||
|
color: "var(--jp-mirror-editor-variable-2-color)",
|
||||||
|
},
|
||||||
|
{ tag: t.punctuation, color: "var(--jp-mirror-editor-punctuation-color)" },
|
||||||
|
{ tag: t.propertyName, color: "var(--jp-mirror-editor-property-color)" },
|
||||||
|
{
|
||||||
|
tag: t.operator,
|
||||||
|
color: "var(--jp-mirror-editor-operator-color)",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag: t.comment,
|
||||||
|
color: "var(--jp-mirror-editor-comment-color)",
|
||||||
|
fontStyle: "italic",
|
||||||
|
},
|
||||||
|
{ tag: t.string, color: "var(--jp-mirror-editor-string-color)" },
|
||||||
|
{
|
||||||
|
tag: [t.labelName, t.monospace, t.special(t.string)],
|
||||||
|
color: "var(--jp-mirror-editor-string-2-color)",
|
||||||
|
},
|
||||||
|
{ tag: t.bracket, color: "var(--jp-mirror-editor-bracket-color)" },
|
||||||
|
{ tag: t.tagName, color: "var(--jp-mirror-editor-tag-color)" },
|
||||||
|
{ tag: t.attributeName, color: "var(--jp-mirror-editor-attribute-color)" },
|
||||||
|
{ tag: t.quote, color: "var(--jp-mirror-editor-quote-color)" },
|
||||||
|
{
|
||||||
|
tag: t.link,
|
||||||
|
color: "var(--jp-mirror-editor-link-color)",
|
||||||
|
textDecoration: "underline",
|
||||||
|
},
|
||||||
|
{ tag: [t.separator, t.derefOperator, t.paren], color: "" },
|
||||||
|
{ tag: t.strong, fontWeight: "bold" },
|
||||||
|
{ tag: t.emphasis, fontStyle: "italic" },
|
||||||
|
{ tag: t.strikethrough, textDecoration: "line-through" },
|
||||||
|
]);
|
||||||
|
/**
|
||||||
|
* JupyterLab CodeMirror 6 theme
|
||||||
|
*/
|
||||||
|
export const jupyterTheme = [
|
||||||
|
jupyterEditorTheme,
|
||||||
|
syntaxHighlighting(jupyterHighlightStyle),
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* A namespace to handle CodeMirror 6 theme
|
||||||
|
*
|
||||||
|
* @alpha
|
||||||
|
*/
|
||||||
|
export var Theme;
|
||||||
|
(function (Theme) {
|
||||||
|
/**
|
||||||
|
* CodeMirror 6 themes
|
||||||
|
*/
|
||||||
|
const themeMap = new Map([
|
||||||
|
[
|
||||||
|
"codemirror",
|
||||||
|
[EditorView.baseTheme({}), syntaxHighlighting(defaultHighlightStyle)],
|
||||||
|
],
|
||||||
|
["jupyter", jupyterTheme],
|
||||||
|
]);
|
||||||
|
/**
|
||||||
|
* Get the default CodeMirror 6 theme for JupyterLab
|
||||||
|
*
|
||||||
|
* @alpha
|
||||||
|
* @returns Default theme
|
||||||
|
*/
|
||||||
|
function defaultTheme() {
|
||||||
|
return themeMap.get("jupyter");
|
||||||
|
}
|
||||||
|
Theme.defaultTheme = defaultTheme;
|
||||||
|
/**
|
||||||
|
* Register a new theme.
|
||||||
|
*
|
||||||
|
* @alpha
|
||||||
|
* @param name Theme name
|
||||||
|
* @param theme Codemirror 6 theme extension
|
||||||
|
*/
|
||||||
|
function registerTheme(name, theme) {
|
||||||
|
themeMap.set(name, theme);
|
||||||
|
}
|
||||||
|
Theme.registerTheme = registerTheme;
|
||||||
|
/**
|
||||||
|
* Get a theme.
|
||||||
|
*
|
||||||
|
* #### Notes
|
||||||
|
* It falls back to the default theme
|
||||||
|
*
|
||||||
|
* @alpha
|
||||||
|
* @param name Theme name
|
||||||
|
* @returns Theme extension
|
||||||
|
*/
|
||||||
|
function getTheme(name) {
|
||||||
|
let ext = themeMap.get(name);
|
||||||
|
return ext !== null && ext !== void 0 ? ext : this.defaultTheme();
|
||||||
|
}
|
||||||
|
Theme.getTheme = getTheme;
|
||||||
|
})(Theme || (Theme = {}));
|
||||||
348
utils/notebook/index.js
Normal file
348
utils/notebook/index.js
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
import "@jupyterlab/theme-light-extension/style/theme.css";
|
||||||
|
import "../../.vitepress/theme/css/jupyterlab/index.css";
|
||||||
|
import { createCodemirror } from "./codemirror";
|
||||||
|
import { defaultSanitizer } from "./sanitizer";
|
||||||
|
import { MathJaxTypesetter } from "./lib/index.js";
|
||||||
|
import {
|
||||||
|
renderHTML,
|
||||||
|
renderImage,
|
||||||
|
renderLatex,
|
||||||
|
renderMarkdown,
|
||||||
|
renderSVG,
|
||||||
|
renderText,
|
||||||
|
} from "./renderers";
|
||||||
|
import defaultMarkdownParser from "./markdown.js"; // 引入cngbdb-ui的markdown渲染逻辑
|
||||||
|
|
||||||
|
export class Notebook {
|
||||||
|
#source; // notebook源数据
|
||||||
|
#cells; // notebook cell列表;cell表示一个最基础的渲染单元,例如inputCell,outputCell,outputResultCell
|
||||||
|
#fragment; // notebook 渲染结果片段,是个div元素
|
||||||
|
#trusted; // 当前渲染字符是安全或者但求运行环境是否可信,涉及Script,SVG渲染
|
||||||
|
#sanitizer; // 字符串无害化处理
|
||||||
|
#shouldTypeset; // 是否对数学公式字符进行latex排版,这里默认为true
|
||||||
|
#latexTypesetter; // latex 插件实例
|
||||||
|
#markdownParser; // markdown 渲染工具
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param {Object} sourceOfJson Notebook 源数据,JSON 对象
|
||||||
|
* @param {Boolean} trusted 当前渲染字符是安全或者当前运行环境是否可信,涉及Script,SVG渲染,默认为False
|
||||||
|
* @param {Boolean} shouldTypeset 是否对数学公式字符进行latex排版,默认为true
|
||||||
|
* @param {*} markdownParser markdown 渲染工具
|
||||||
|
*/
|
||||||
|
constructor(source, trusted, shouldTypeset, markdownParser) {
|
||||||
|
if (!source.cells || !(source.cells instanceof Array))
|
||||||
|
throw "The Notebook is Error! Cells attribute is required and is Array!";
|
||||||
|
this.#source = JSON.parse(JSON.stringify(source));
|
||||||
|
const { cells } = this.#source;
|
||||||
|
this.#cells = cells;
|
||||||
|
this.#fragment = document.createElement("div"); // 创建一个新的空白的div片段,notebook渲染的结果都暂时存储在其中
|
||||||
|
|
||||||
|
/*---------- 默认配置项 START ----------*/
|
||||||
|
this.#trusted = trusted || false; // 当前运行环境是否安全可信,涉及Script,SVG渲染
|
||||||
|
this.#sanitizer = defaultSanitizer; // 字符串无害化处理
|
||||||
|
this.#shouldTypeset = shouldTypeset || true; // 是否对数学公式字符进行latex排版,这里默认为true
|
||||||
|
this.#latexTypesetter = new MathJaxTypesetter({
|
||||||
|
url: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js",
|
||||||
|
config: "TeX-AMS_HTML-full,Safe",
|
||||||
|
}); // latex 插件实例化
|
||||||
|
this.#markdownParser = markdownParser || defaultMarkdownParser; // markdown 渲染工具
|
||||||
|
/*---------- 默认配置项 END ----------*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// notebook渲染成HTML的结果
|
||||||
|
get notebookHTML() {
|
||||||
|
return this.#fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cells 渲染
|
||||||
|
* 此处是 notebook 渲染的总入口
|
||||||
|
*
|
||||||
|
* 每个 cell 由input和output两个模块组成;
|
||||||
|
* input 分为三类数据,即cell_type = markdown/code/raw。其中只有code会有output;
|
||||||
|
* output 处理详见 renderCommonCell 方法;
|
||||||
|
*
|
||||||
|
* @author 王志杰
|
||||||
|
* @returns {DocumentFragment} 返回一个 DocumentFragment 对象
|
||||||
|
*/
|
||||||
|
async render() {
|
||||||
|
try {
|
||||||
|
for (let cell of this.#cells) {
|
||||||
|
let node = null;
|
||||||
|
let { cell_type, source } = cell;
|
||||||
|
cell.source = typeof source === "string" ? source : source.join("");
|
||||||
|
switch (cell_type) {
|
||||||
|
case "markdown":
|
||||||
|
node = await this.#renderMarkdownCell(cell);
|
||||||
|
break;
|
||||||
|
case "code":
|
||||||
|
node = await this.#renderCodeCell(cell);
|
||||||
|
break;
|
||||||
|
case "raw":
|
||||||
|
node = await this.#renderRawCell(cell);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.#fragment.appendChild(node);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
return this.#fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据渲染总模块,input和output的数据渲染都经由这里分发到具体的渲染模块
|
||||||
|
*
|
||||||
|
* @param {string} param0 type-数据模块类型,所支持的类型为output_type全部类型‘
|
||||||
|
* @param {object} param1 options-渲染模块所需的参数
|
||||||
|
*/
|
||||||
|
async #renderCommonCell({ type, options }) {
|
||||||
|
// 对未设置的配置项,设置为全局默认配置对应的属性值
|
||||||
|
options.trusted = options.trusted || this.#trusted;
|
||||||
|
options.sanitizer = options.sanitizer || this.#sanitizer;
|
||||||
|
options.shouldTypeset = options.shouldTypeset || this.#shouldTypeset;
|
||||||
|
options.latexTypesetter = options.latexTypesetter || this.#latexTypesetter;
|
||||||
|
options.markdownParser = options.markdownParser || this.#markdownParser;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "text/html":
|
||||||
|
await renderHTML(options);
|
||||||
|
break;
|
||||||
|
case "markdown":
|
||||||
|
case "text/markdown":
|
||||||
|
await renderMarkdown(options);
|
||||||
|
break;
|
||||||
|
case "text/plain":
|
||||||
|
case "application/vnd.jupyter.stdout":
|
||||||
|
case "application/vnd.jupyter.stderr":
|
||||||
|
await renderText(options);
|
||||||
|
break;
|
||||||
|
case "text/latex":
|
||||||
|
await renderLatex(options);
|
||||||
|
break;
|
||||||
|
case "image/bmp":
|
||||||
|
case "image/png":
|
||||||
|
case "image/jpeg":
|
||||||
|
case "image/gif":
|
||||||
|
case "image/webp":
|
||||||
|
await renderImage(options);
|
||||||
|
break;
|
||||||
|
case "image/svg+xml":
|
||||||
|
await renderSVG(options);
|
||||||
|
break;
|
||||||
|
case "text/javascript":
|
||||||
|
case "application/javascript":
|
||||||
|
// 禁止输出 JavaScript
|
||||||
|
options.source = "JavaScript output is disabled in JupyterLab";
|
||||||
|
await renderText(options);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染markdown DOM
|
||||||
|
* @param {Object} cell
|
||||||
|
*/
|
||||||
|
async #renderMarkdownCell(cell) {
|
||||||
|
let { source, execution_count: executionCount } = cell;
|
||||||
|
let contentNode = document.createElement("div");
|
||||||
|
await this.#renderCommonCell({
|
||||||
|
type: "text/markdown",
|
||||||
|
options: { host: contentNode, source: source },
|
||||||
|
});
|
||||||
|
return this.#createContainerNode(
|
||||||
|
"inputMarkdown",
|
||||||
|
contentNode,
|
||||||
|
executionCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染Code DOM
|
||||||
|
* @param {Object} cell
|
||||||
|
*/
|
||||||
|
async #renderCodeCell(cell) {
|
||||||
|
let node = null;
|
||||||
|
let { source, outputs, execution_count: executionCount } = cell;
|
||||||
|
let contentNode = document.createElement("div");
|
||||||
|
contentNode.className =
|
||||||
|
"lm-Widget p-Widget jp-Cell jp-CodeCell jp-Notebook-cell ";
|
||||||
|
createCodemirror(source, contentNode); // input代码块渲染
|
||||||
|
node = this.#createContainerNode("inputCode", contentNode, executionCount);
|
||||||
|
await this.#renderOutputCell(outputs, contentNode.parentNode.parentNode);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
async #renderRawCell(cell) {
|
||||||
|
let { source } = cell;
|
||||||
|
let node = document.createElement("div");
|
||||||
|
await this.#renderCommonCell({
|
||||||
|
type: "text/plain",
|
||||||
|
options: { host: node, source: source },
|
||||||
|
});
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染 outputs
|
||||||
|
* @param {Array} outputs
|
||||||
|
*/
|
||||||
|
async #renderOutputCell(outputs, parentNode) {
|
||||||
|
if (!outputs || !outputs.length) return;
|
||||||
|
const OutputAreaNode = document.createElement("div");
|
||||||
|
OutputAreaNode.className =
|
||||||
|
"lm-Widget jp-OutputArea jp-Cell-outputArea q-mt-sm";
|
||||||
|
parentNode.appendChild(OutputAreaNode);
|
||||||
|
for (let output of outputs) {
|
||||||
|
let sources = [];
|
||||||
|
switch (output.output_type) {
|
||||||
|
case "stream": // 文本流输出
|
||||||
|
sources = output.text;
|
||||||
|
for (const source of sources) {
|
||||||
|
let node = document.createElement("div");
|
||||||
|
await this.#renderCommonCell({
|
||||||
|
type: "application/vnd.jupyter." + output.name,
|
||||||
|
options: { host: node, source: source },
|
||||||
|
});
|
||||||
|
|
||||||
|
OutputAreaNode.appendChild(
|
||||||
|
this.#createContainerNode(
|
||||||
|
"application/vnd.jupyter." + output.name,
|
||||||
|
node,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "display_data":
|
||||||
|
case "execute_result": {
|
||||||
|
// 富文本输出
|
||||||
|
const { data: outputData, execution_count: executionCount } = output;
|
||||||
|
const keys = Object.keys(outputData);
|
||||||
|
const key = keys[0];
|
||||||
|
let source = outputData[key];
|
||||||
|
if (!source) return;
|
||||||
|
let node = document.createElement("div");
|
||||||
|
source = typeof source === "string" ? source : source.join("\n");
|
||||||
|
await this.#renderCommonCell({
|
||||||
|
type: key,
|
||||||
|
options: { host: node, source: source },
|
||||||
|
});
|
||||||
|
|
||||||
|
OutputAreaNode.appendChild(
|
||||||
|
this.#createContainerNode(key, node, executionCount)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "error": // 错误信息输出
|
||||||
|
sources = output.traceback;
|
||||||
|
for (const source of sources) {
|
||||||
|
let node = document.createElement("div");
|
||||||
|
await this.#renderCommonCell({
|
||||||
|
type: "application/vnd.jupyter.stderr",
|
||||||
|
options: { host: node, source: source },
|
||||||
|
});
|
||||||
|
OutputAreaNode.appendChild(
|
||||||
|
this.#createContainerNode(
|
||||||
|
"application/vnd.jupyter.stderr",
|
||||||
|
node,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#createContainerNode(type, contentNode, executionCount) {
|
||||||
|
let node = document.createElement("div");
|
||||||
|
let areaNode = document.createElement("div");
|
||||||
|
let promptNode = document.createElement("div");
|
||||||
|
if (executionCount || executionCount === null) {
|
||||||
|
promptNode.innerText = `[${executionCount === null ? " " : executionCount
|
||||||
|
}]`;
|
||||||
|
}
|
||||||
|
// prompt class设置。prompt 样式分为input和output两种
|
||||||
|
["inputMarkdown", "inputCode"].includes(type)
|
||||||
|
? (promptNode.className =
|
||||||
|
"lm-Widget p-Widget jp-InputPrompt jp-InputArea-prompt")
|
||||||
|
: (promptNode.className =
|
||||||
|
"lm-Widget p-Widget jp-OutputPrompt jp-OutputArea-prompt");
|
||||||
|
switch (type) {
|
||||||
|
case "inputMarkdown": {
|
||||||
|
node.className =
|
||||||
|
"lm-Widget p-Widget jp-Cell jp-MarkdownCell jp-mod-rendered jp-Notebook-cell";
|
||||||
|
areaNode.className =
|
||||||
|
"lm-Widget p-Widget jp-InputArea jp-Cell-inputArea";
|
||||||
|
contentNode.className =
|
||||||
|
"lm-Widget p-Widget jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput";
|
||||||
|
contentNode.setAttribute("data-mime-type", "text/markdown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "inputCode": {
|
||||||
|
node.className =
|
||||||
|
"lm-Widget p-Widget jp-Cell jp-CodeCell jp-mod-noOutputs jp-Notebook-cell";
|
||||||
|
areaNode.className =
|
||||||
|
"lm-Widget p-Widget jp-InputArea jp-Cell-inputArea";
|
||||||
|
contentNode.className =
|
||||||
|
"lm-Widget p-Widget jp-CodeMirrorEditor jp-Editor jp-InputArea-editor";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "application/vnd.jupyter.stdout": {
|
||||||
|
node.className = "lm-Widget lm-Panel jp-OutputArea-child";
|
||||||
|
areaNode.className =
|
||||||
|
"lm-Widget p-Widget lm-Panel p-Panel jp-OutputArea-child";
|
||||||
|
contentNode.className =
|
||||||
|
"lm-Widget p-Widget jp-RenderedText jp-OutputArea-output";
|
||||||
|
contentNode.setAttribute(
|
||||||
|
"data-mime-type",
|
||||||
|
"application/vnd.jupyter.stdout"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "application/vnd.jupyter.stderr": {
|
||||||
|
node.className = "lm-Widget lm-Panel jp-OutputArea-child";
|
||||||
|
areaNode.className =
|
||||||
|
"lm-Widget p-Widget lm-Panel p-Panel jp-OutputArea-child";
|
||||||
|
contentNode.className =
|
||||||
|
"lm-Widget p-Widget jp-RenderedText jp-OutputArea-output";
|
||||||
|
contentNode.setAttribute(
|
||||||
|
"data-mime-type",
|
||||||
|
"application/vnd.jupyter.stderr"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const typeClassMap = new Map([
|
||||||
|
["image/bmp", "jp-RenderedImage"],
|
||||||
|
["image/png", "jp-RenderedImage"],
|
||||||
|
["image/jpeg", "jp-RenderedImage"],
|
||||||
|
["image/gif", "jp-RenderedImage"],
|
||||||
|
["image/webp", "jp-RenderedImage"],
|
||||||
|
["text/latex", "jp-RenderedLatex"],
|
||||||
|
["image/svg+xml", "jp-RenderedSVG"],
|
||||||
|
["text/markdown", "jp-RenderedHTMLCommon jp-RenderedHTML"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
node.className =
|
||||||
|
"lm-Widget p-Widget lm-Panel p-Panel jp-OutputArea-child jp-OutputArea-executeResult";
|
||||||
|
areaNode.className =
|
||||||
|
"lm-Widget p-Widget lm-Panel p-Panel jp-OutputArea-child";
|
||||||
|
contentNode.className = `lm-Widget p-Widget ${typeClassMap.get(type) || "jp-RenderedHTMLCommon"
|
||||||
|
} jp-OutputArea-output`;
|
||||||
|
contentNode.setAttribute("data-mime-type", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
areaNode.appendChild(promptNode);
|
||||||
|
areaNode.appendChild(contentNode);
|
||||||
|
node.appendChild(areaNode);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
194
utils/notebook/latex.js
Normal file
194
utils/notebook/latex.js
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|----------------------------------------------------------------------------*/
|
||||||
|
// Some magic for deferring mathematical expressions to MathJax
|
||||||
|
// by hiding them from the Markdown parser.
|
||||||
|
// Some of the code here is adapted with permission from Davide Cervone
|
||||||
|
// under the terms of the Apache2 license governing the MathJax project.
|
||||||
|
// Other minor modifications are also due to StackExchange and are used with
|
||||||
|
// permission.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本文件为 Jupyter lab 源码。
|
||||||
|
* 用于 latex 字符渲染
|
||||||
|
*
|
||||||
|
* 源码TS版:https://github.com/jupyterlab/jupyterlab/blob/master/packages/rendermime/src/latex.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
const inline = "$"; // the inline math delimiter
|
||||||
|
// MATHSPLIT contains the pattern for math delimiters and special symbols
|
||||||
|
// needed for searching for math in the text input.
|
||||||
|
const MATHSPLIT =
|
||||||
|
/(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[{}$]|[{}]|(?:\n\s*)+|@@\d+@@|\\\\(?:\(|\)|\[|\]))/i;
|
||||||
|
/**
|
||||||
|
* Break up the text into its component parts and search
|
||||||
|
* through them for math delimiters, braces, linebreaks, etc.
|
||||||
|
* Math delimiters must match and braces must balance.
|
||||||
|
* Don't allow math to pass through a double linebreak
|
||||||
|
* (which will be a paragraph).
|
||||||
|
*/
|
||||||
|
export function removeMath(text) {
|
||||||
|
const math = []; // stores math strings for later
|
||||||
|
let start = null;
|
||||||
|
let end = null;
|
||||||
|
let last = null;
|
||||||
|
let braces = 0;
|
||||||
|
let deTilde;
|
||||||
|
// Except for extreme edge cases, this should catch precisely those pieces of the markdown
|
||||||
|
// source that will later be turned into code spans. While MathJax will not TeXify code spans,
|
||||||
|
// we still have to consider them at this point; the following issue has happened several times:
|
||||||
|
//
|
||||||
|
// `$foo` and `$bar` are variables. --> <code>$foo ` and `$bar</code> are variables.
|
||||||
|
const hasCodeSpans = text.includes("`") || text.includes("~~~");
|
||||||
|
if (hasCodeSpans) {
|
||||||
|
text = text
|
||||||
|
.replace(/~/g, "~T")
|
||||||
|
// note: the `fence` (three or more consecutive tildes or backticks)
|
||||||
|
// can be followed by an `info string` but this cannot include backticks,
|
||||||
|
// see specification: https://spec.commonmark.org/0.30/#info-string
|
||||||
|
.replace(
|
||||||
|
/^(?<fence>`{3,}|(~T){3,})[^`\n]*\n([\s\S]*?)^\k<fence>`*$/gm,
|
||||||
|
(wholematch) => wholematch.replace(/\$/g, "~D")
|
||||||
|
)
|
||||||
|
.replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, (wholematch) =>
|
||||||
|
wholematch.replace(/\$/g, "~D")
|
||||||
|
);
|
||||||
|
deTilde = (text) => {
|
||||||
|
return text.replace(/~([TD])/g, (wholematch, character) =>
|
||||||
|
character === "T" ? "~" : inline
|
||||||
|
);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
deTilde = (text) => {
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let blocks = text.replace(/\r\n?/g, "\n").split(MATHSPLIT);
|
||||||
|
for (let i = 1, m = blocks.length; i < m; i += 2) {
|
||||||
|
const block = blocks[i];
|
||||||
|
if (block.charAt(0) === "@") {
|
||||||
|
//
|
||||||
|
// Things that look like our math markers will get
|
||||||
|
// stored and then retrieved along with the math.
|
||||||
|
//
|
||||||
|
blocks[i] = "@@" + math.length + "@@";
|
||||||
|
math.push(block);
|
||||||
|
} else if (start !== null) {
|
||||||
|
//
|
||||||
|
// If we are in math, look for the end delimiter,
|
||||||
|
// but don't go past double line breaks, and
|
||||||
|
// and balance braces within the math.
|
||||||
|
//
|
||||||
|
if (block === end) {
|
||||||
|
if (braces) {
|
||||||
|
last = i;
|
||||||
|
} else {
|
||||||
|
blocks = processMath(start, i, deTilde, math, blocks);
|
||||||
|
start = null;
|
||||||
|
end = null;
|
||||||
|
last = null;
|
||||||
|
}
|
||||||
|
} else if (block.match(/\n.*\n/)) {
|
||||||
|
if (last !== null) {
|
||||||
|
i = last;
|
||||||
|
blocks = processMath(start, i, deTilde, math, blocks);
|
||||||
|
}
|
||||||
|
start = null;
|
||||||
|
end = null;
|
||||||
|
last = null;
|
||||||
|
braces = 0;
|
||||||
|
} else if (block === "{") {
|
||||||
|
braces++;
|
||||||
|
} else if (block === "}" && braces) {
|
||||||
|
braces--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Look for math start delimiters and when
|
||||||
|
// found, set up the end delimiter.
|
||||||
|
//
|
||||||
|
if (block === inline || block === "$$") {
|
||||||
|
start = i;
|
||||||
|
end = block;
|
||||||
|
braces = 0;
|
||||||
|
} else if (block === "\\\\(" || block === "\\\\[") {
|
||||||
|
start = i;
|
||||||
|
end = block.slice(-1) === "(" ? "\\\\)" : "\\\\]";
|
||||||
|
braces = 0;
|
||||||
|
} else if (block.substr(1, 5) === "begin") {
|
||||||
|
start = i;
|
||||||
|
end = "\\end" + block.substr(6);
|
||||||
|
braces = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (start !== null && last !== null) {
|
||||||
|
blocks = processMath(start, last, deTilde, math, blocks);
|
||||||
|
start = null;
|
||||||
|
end = null;
|
||||||
|
last = null;
|
||||||
|
}
|
||||||
|
return { text: deTilde(blocks.join("")), math };
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Put back the math strings that were saved,
|
||||||
|
* and clear the math array (no need to keep it around).
|
||||||
|
*/
|
||||||
|
export function replaceMath(text, math) {
|
||||||
|
/**
|
||||||
|
* Replace a math placeholder with its corresponding group.
|
||||||
|
* The math delimiters "\\(", "\\[", "\\)" and "\\]" are replaced
|
||||||
|
* removing one backslash in order to be interpreted correctly by MathJax.
|
||||||
|
*/
|
||||||
|
const process = (match, n) => {
|
||||||
|
let group = math[n];
|
||||||
|
if (
|
||||||
|
group.substr(0, 3) === "\\\\(" &&
|
||||||
|
group.substr(group.length - 3) === "\\\\)"
|
||||||
|
) {
|
||||||
|
group = "\\(" + group.substring(3, group.length - 3) + "\\)";
|
||||||
|
} else if (
|
||||||
|
group.substr(0, 3) === "\\\\[" &&
|
||||||
|
group.substr(group.length - 3) === "\\\\]"
|
||||||
|
) {
|
||||||
|
group = "\\[" + group.substring(3, group.length - 3) + "\\]";
|
||||||
|
}
|
||||||
|
return group;
|
||||||
|
};
|
||||||
|
// Replace all the math group placeholders in the text
|
||||||
|
// with the saved strings.
|
||||||
|
return text.replace(/@@(\d+)@@/g, process);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Process math blocks.
|
||||||
|
*
|
||||||
|
* The math is in blocks i through j, so
|
||||||
|
* collect it into one block and clear the others.
|
||||||
|
* Replace &, <, and > by named entities.
|
||||||
|
* For IE, put <br> at the ends of comments since IE removes \n.
|
||||||
|
* Clear the current math positions and store the index of the
|
||||||
|
* math, then push the math string onto the storage array.
|
||||||
|
* The preProcess function is called on all blocks if it has been passed in
|
||||||
|
*/
|
||||||
|
function processMath(i, j, preProcess, math, blocks) {
|
||||||
|
let block = blocks
|
||||||
|
.slice(i, j + 1)
|
||||||
|
.join("")
|
||||||
|
.replace(/&/g, "&") // use HTML entity for &
|
||||||
|
.replace(/</g, "<") // use HTML entity for <
|
||||||
|
.replace(/>/g, ">"); // use HTML entity for >
|
||||||
|
if (navigator && navigator.appName === "Microsoft Internet Explorer") {
|
||||||
|
block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n");
|
||||||
|
}
|
||||||
|
while (j > i) {
|
||||||
|
blocks[j] = "";
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
blocks[i] = "@@" + math.length + "@@"; // replace the current block text with a unique tag to find later
|
||||||
|
if (preProcess) {
|
||||||
|
block = preProcess(block);
|
||||||
|
}
|
||||||
|
math.push(block);
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
108
utils/notebook/lib/index.js
Normal file
108
utils/notebook/lib/index.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|----------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @packageDocumentation
|
||||||
|
* @module mathjax2
|
||||||
|
*/
|
||||||
|
import { PromiseDelegate } from '@lumino/coreutils';
|
||||||
|
/**
|
||||||
|
* The MathJax Typesetter.
|
||||||
|
*/
|
||||||
|
export class MathJaxTypesetter {
|
||||||
|
/**
|
||||||
|
* Create a new MathJax typesetter.
|
||||||
|
*/
|
||||||
|
constructor(options) {
|
||||||
|
this._initPromise = new PromiseDelegate();
|
||||||
|
this._initialized = false;
|
||||||
|
this._url = options.url;
|
||||||
|
this._config = options.config;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Typeset the math in a node.
|
||||||
|
*
|
||||||
|
* #### Notes
|
||||||
|
* MathJax schedules the typesetting asynchronously,
|
||||||
|
* but there are not currently any callbacks or Promises
|
||||||
|
* firing when it is done.
|
||||||
|
*/
|
||||||
|
typeset(node) {
|
||||||
|
if (!this._initialized) {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
void this._initPromise.promise.then(() => {
|
||||||
|
MathJax.Hub.Queue(['Typeset', MathJax.Hub, node]);
|
||||||
|
try {
|
||||||
|
MathJax.Hub.Queue(['Require', MathJax.Ajax, '[MathJax]/extensions/TeX/AMSmath.js'], () => {
|
||||||
|
MathJax.InputJax.TeX.resetEquationNumbers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('Error queueing resetEquationNumbers:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialize MathJax.
|
||||||
|
*/
|
||||||
|
_init() {
|
||||||
|
const head = document.getElementsByTagName('head')[0];
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.src = `${this._url}?config=${this._config}&delayStartupUntil=configured`;
|
||||||
|
script.charset = 'utf-8';
|
||||||
|
head.appendChild(script);
|
||||||
|
script.addEventListener('load', () => {
|
||||||
|
this._onLoad();
|
||||||
|
});
|
||||||
|
this._initialized = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handle MathJax loading.
|
||||||
|
*/
|
||||||
|
_onLoad() {
|
||||||
|
MathJax.Hub.Config({
|
||||||
|
tex2jax: {
|
||||||
|
inlineMath: [
|
||||||
|
['$', '$'],
|
||||||
|
['\\(', '\\)']
|
||||||
|
],
|
||||||
|
displayMath: [
|
||||||
|
['$$', '$$'],
|
||||||
|
['\\[', '\\]']
|
||||||
|
],
|
||||||
|
processEscapes: true,
|
||||||
|
processEnvironments: true
|
||||||
|
},
|
||||||
|
// Center justify equations in code and markdown cells. Elsewhere
|
||||||
|
// we use CSS to left justify single line equations in code cells.
|
||||||
|
displayAlign: 'center',
|
||||||
|
CommonHTML: {
|
||||||
|
linebreaks: { automatic: true }
|
||||||
|
},
|
||||||
|
'HTML-CSS': {
|
||||||
|
availableFonts: [],
|
||||||
|
imageFont: null,
|
||||||
|
preferredFont: null,
|
||||||
|
webFont: 'STIX-Web',
|
||||||
|
styles: { '.MathJax_Display': { margin: 0 } },
|
||||||
|
linebreaks: { automatic: true }
|
||||||
|
},
|
||||||
|
skipStartupTypeset: true,
|
||||||
|
messageStyle: 'none'
|
||||||
|
});
|
||||||
|
MathJax.Hub.Register.StartupHook('End Config', () => {
|
||||||
|
var _a, _b, _c, _d, _e, _f;
|
||||||
|
// Disable `:hover span` styles which cause performance issues in Chromium browsers
|
||||||
|
// c-f https://github.com/jupyterlab/jupyterlab/issues/9757
|
||||||
|
// Note that we cannot overwrite them in config earlier due to how `CombineConfig`
|
||||||
|
// is implemented in MathJax 2 (it does not allow removing styles, just expanding).
|
||||||
|
(_c = (_b = (_a = MathJax.Hub) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.MathEvents) === null || _c === void 0 ? true : delete _c.styles['.MathJax_Hover_Arrow:hover span'];
|
||||||
|
(_f = (_e = (_d = MathJax.Hub) === null || _d === void 0 ? void 0 : _d.config) === null || _e === void 0 ? void 0 : _e.MathMenu) === null || _f === void 0 ? true : delete _f.styles['.MathJax_MenuClose:hover span'];
|
||||||
|
});
|
||||||
|
MathJax.Hub.Configured();
|
||||||
|
this._initPromise.resolve(void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
utils/notebook/markdown.js
Normal file
10
utils/notebook/markdown.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import markdown from "markdown-it";
|
||||||
|
|
||||||
|
const MD = markdown({
|
||||||
|
html: true,
|
||||||
|
xhtmlOut: true,
|
||||||
|
breaks: true,
|
||||||
|
linkify: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default MD;
|
||||||
701
utils/notebook/renderers.js
Normal file
701
utils/notebook/renderers.js
Normal file
@@ -0,0 +1,701 @@
|
|||||||
|
/* eslint-disable no-func-assign */
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jupyter lab notebook output 渲染模块
|
||||||
|
* 本模块基于 @jupyterlab\rendermime\lib\renderers.js 二次开发
|
||||||
|
* 移除了部分功能,如:a 标签url处理,markdown 标题的自动生成对应链接等。
|
||||||
|
* 此外还去除了所需传参:resolver、linkHandler、translator
|
||||||
|
*
|
||||||
|
* 源码TS版:https://github.com/jupyterlab/jupyterlab/blob/master/packages/rendermime/src/renderers.ts
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { removeMath, replaceMath } from "./latex";
|
||||||
|
import { URLExt } from "@jupyterlab/coreutils";
|
||||||
|
import escape from "lodash.escape";
|
||||||
|
/**
|
||||||
|
* Render HTML into a host node.
|
||||||
|
*
|
||||||
|
* @param options - The options for rendering.
|
||||||
|
*
|
||||||
|
* @returns A promise which resolves when rendering is complete.
|
||||||
|
*/
|
||||||
|
export function renderHTML(options) {
|
||||||
|
// Unpack the options.
|
||||||
|
let { host, source, trusted, sanitizer, shouldTypeset, latexTypesetter } =
|
||||||
|
options;
|
||||||
|
let originalSource = source;
|
||||||
|
// Bail early if the source is empty.
|
||||||
|
if (!source) {
|
||||||
|
host.textContent = "";
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
// Sanitize the source if it is not trusted. This removes all
|
||||||
|
// `<script>` tags as well as other potentially harmful HTML.
|
||||||
|
if (!trusted) {
|
||||||
|
originalSource = `${source}`;
|
||||||
|
source = sanitizer.sanitize(source);
|
||||||
|
}
|
||||||
|
// Set the inner HTML of the host.
|
||||||
|
host.innerHTML = source;
|
||||||
|
if (host.getElementsByTagName("script").length > 0) {
|
||||||
|
// If output it trusted, eval any script tags contained in the HTML.
|
||||||
|
// This is not done automatically by the browser when script tags are
|
||||||
|
// created by setting `innerHTML`.
|
||||||
|
if (trusted) {
|
||||||
|
Private.evalInnerHTMLScriptTags(host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle default behavior of nodes.
|
||||||
|
Private.handleDefaults(host);
|
||||||
|
// Patch the urls if a resolver is available.
|
||||||
|
let promise;
|
||||||
|
promise = Promise.resolve(undefined);
|
||||||
|
// Return the final rendered promise.
|
||||||
|
return promise.then(() => {
|
||||||
|
if (shouldTypeset && latexTypesetter) {
|
||||||
|
latexTypesetter.typeset(host);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Render an image into a host node.
|
||||||
|
*
|
||||||
|
* @param options - The options for rendering.
|
||||||
|
*
|
||||||
|
* @returns A promise which resolves when rendering is complete.
|
||||||
|
*/
|
||||||
|
export function renderImage(options) {
|
||||||
|
// Unpack the options.
|
||||||
|
const { host, mimeType, source, width, height, needsBackground, unconfined } =
|
||||||
|
options;
|
||||||
|
// Clear the content in the host.
|
||||||
|
host.textContent = "";
|
||||||
|
// Create the image element.
|
||||||
|
const img = document.createElement("img");
|
||||||
|
// Set the source of the image.
|
||||||
|
img.src = `data:${mimeType};base64,${source}`;
|
||||||
|
// Set the size of the image if provided.
|
||||||
|
if (typeof height === "number") {
|
||||||
|
img.height = height;
|
||||||
|
}
|
||||||
|
if (typeof width === "number") {
|
||||||
|
img.width = width;
|
||||||
|
}
|
||||||
|
if (needsBackground === "light") {
|
||||||
|
img.classList.add("jp-needs-light-background");
|
||||||
|
} else if (needsBackground === "dark") {
|
||||||
|
img.classList.add("jp-needs-dark-background");
|
||||||
|
}
|
||||||
|
if (unconfined === true) {
|
||||||
|
img.classList.add("jp-mod-unconfined");
|
||||||
|
}
|
||||||
|
// Add the image to the host.
|
||||||
|
host.appendChild(img);
|
||||||
|
// Return the rendered promise.
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Render LaTeX into a host node.
|
||||||
|
*
|
||||||
|
* @param options - The options for rendering.
|
||||||
|
*
|
||||||
|
* @returns A promise which resolves when rendering is complete.
|
||||||
|
*/
|
||||||
|
export function renderLatex(options) {
|
||||||
|
// Unpack the options.
|
||||||
|
const { host, source, shouldTypeset, latexTypesetter } = options;
|
||||||
|
// Set the source on the node.
|
||||||
|
host.textContent = source;
|
||||||
|
// Typeset the node if needed.
|
||||||
|
if (shouldTypeset && latexTypesetter) {
|
||||||
|
latexTypesetter.typeset(host);
|
||||||
|
}
|
||||||
|
// Return the rendered promise.
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Render Markdown into a host node.
|
||||||
|
*
|
||||||
|
* @param options - The options for rendering.
|
||||||
|
*
|
||||||
|
* @returns A promise which resolves when rendering is complete.
|
||||||
|
*/
|
||||||
|
export async function renderMarkdown(options) {
|
||||||
|
// Unpack the options.
|
||||||
|
const { host, source, markdownParser, ...others } = options;
|
||||||
|
// Clear the content if there is no source.
|
||||||
|
if (!source) {
|
||||||
|
host.textContent = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let html = "";
|
||||||
|
|
||||||
|
if (markdownParser) {
|
||||||
|
// Separate math from normal markdown text.
|
||||||
|
const parts = removeMath(source);
|
||||||
|
// Convert the markdown to HTML.
|
||||||
|
html = await markdownParser.render(parts["text"]);
|
||||||
|
// Replace math.
|
||||||
|
html = replaceMath(html, parts["math"]);
|
||||||
|
} else {
|
||||||
|
// Fallback if the application does not have any markdown parser.
|
||||||
|
html = `<pre>${source}</pre>`;
|
||||||
|
}
|
||||||
|
// Render HTML.
|
||||||
|
await renderHTML({
|
||||||
|
host,
|
||||||
|
source: html,
|
||||||
|
...others,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The namespace for the `renderMarkdown` function statics.
|
||||||
|
*/
|
||||||
|
(function (renderMarkdown) {
|
||||||
|
/**
|
||||||
|
* Create a normalized id for a header element.
|
||||||
|
*
|
||||||
|
* @param header Header element
|
||||||
|
* @returns Normalized id
|
||||||
|
*/
|
||||||
|
function createHeaderId(header) {
|
||||||
|
var _a;
|
||||||
|
return (
|
||||||
|
(_a = header.textContent) !== null && _a !== void 0 ? _a : ""
|
||||||
|
).replace(/ /g, "-");
|
||||||
|
}
|
||||||
|
renderMarkdown.createHeaderId = createHeaderId;
|
||||||
|
})(renderMarkdown || (renderMarkdown = {}));
|
||||||
|
/**
|
||||||
|
* Render SVG into a host node.
|
||||||
|
*
|
||||||
|
* @param options - The options for rendering.
|
||||||
|
*
|
||||||
|
* @returns A promise which resolves when rendering is complete.
|
||||||
|
*/
|
||||||
|
export function renderSVG(options) {
|
||||||
|
// Unpack the options.
|
||||||
|
let { host, source, trusted, unconfined } = options;
|
||||||
|
// Clear the content if there is no source.
|
||||||
|
if (!source) {
|
||||||
|
host.textContent = "";
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
// Display a message if the source is not trusted.
|
||||||
|
if (!trusted) {
|
||||||
|
host.textContent =
|
||||||
|
"Cannot display an untrusted SVG. Maybe you need to run the cell?";
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
// Add missing SVG namespace (if actually missing)
|
||||||
|
const patt = "<svg[^>]+xmlns=[^>]+svg";
|
||||||
|
if (source.search(patt) < 0) {
|
||||||
|
source = source.replace("<svg", '<svg xmlns="http://www.w3.org/2000/svg"');
|
||||||
|
}
|
||||||
|
// Render in img so that user can save it easily
|
||||||
|
const img = new Image();
|
||||||
|
img.src = `data:image/svg+xml,${encodeURIComponent(source)}`;
|
||||||
|
host.appendChild(img);
|
||||||
|
if (unconfined === true) {
|
||||||
|
host.classList.add("jp-mod-unconfined");
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Replace URLs with links.
|
||||||
|
*
|
||||||
|
* @param content - The text content of a node.
|
||||||
|
*
|
||||||
|
* @returns A list of text nodes and anchor elements.
|
||||||
|
*/
|
||||||
|
function autolink(content) {
|
||||||
|
// Taken from Visual Studio Code:
|
||||||
|
// https://github.com/microsoft/vscode/blob/9f709d170b06e991502153f281ec3c012add2e42/src/vs/workbench/contrib/debug/browser/linkDetector.ts#L17-L18
|
||||||
|
const controlCodes = "\\u0000-\\u0020\\u007f-\\u009f";
|
||||||
|
const webLinkRegex = new RegExp(
|
||||||
|
"(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s" +
|
||||||
|
controlCodes +
|
||||||
|
'"]{2,}[^\\s' +
|
||||||
|
controlCodes +
|
||||||
|
"\"'(){}\\[\\],:;.!?]",
|
||||||
|
"ug"
|
||||||
|
);
|
||||||
|
const nodes = [];
|
||||||
|
let lastIndex = 0;
|
||||||
|
let match;
|
||||||
|
while (null != (match = webLinkRegex.exec(content))) {
|
||||||
|
if (match.index !== lastIndex) {
|
||||||
|
nodes.push(
|
||||||
|
document.createTextNode(content.slice(lastIndex, match.index))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let url = match[0];
|
||||||
|
// Special case when the URL ends with ">" or "<"
|
||||||
|
const lastChars = url.slice(-1);
|
||||||
|
const endsWithGtLt = [">", "<"].indexOf(lastChars) !== -1;
|
||||||
|
const len = endsWithGtLt ? url.length - 1 : url.length;
|
||||||
|
const anchor = document.createElement("a");
|
||||||
|
url = url.slice(0, len);
|
||||||
|
anchor.href = url.startsWith("www.") ? "https://" + url : url;
|
||||||
|
anchor.rel = "noopener";
|
||||||
|
anchor.target = "_blank";
|
||||||
|
anchor.appendChild(document.createTextNode(url.slice(0, len)));
|
||||||
|
nodes.push(anchor);
|
||||||
|
lastIndex = match.index + len;
|
||||||
|
}
|
||||||
|
if (lastIndex !== content.length) {
|
||||||
|
nodes.push(
|
||||||
|
document.createTextNode(content.slice(lastIndex, content.length))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Split a shallow node (node without nested nodes inside) at a given text content position.
|
||||||
|
*
|
||||||
|
* @param node the shallow node to be split
|
||||||
|
* @param at the position in textContent at which the split should occur
|
||||||
|
*/
|
||||||
|
function splitShallowNode(node, at) {
|
||||||
|
var _a, _b;
|
||||||
|
const pre = node.cloneNode();
|
||||||
|
pre.textContent =
|
||||||
|
(_a = node.textContent) === null || _a === void 0
|
||||||
|
? void 0
|
||||||
|
: _a.substr(0, at);
|
||||||
|
const post = node.cloneNode();
|
||||||
|
post.textContent =
|
||||||
|
(_b = node.textContent) === null || _b === void 0 ? void 0 : _b.substr(at);
|
||||||
|
return {
|
||||||
|
pre: pre,
|
||||||
|
post: post,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Render text into a host node.
|
||||||
|
*
|
||||||
|
* @param options - The options for rendering.
|
||||||
|
*
|
||||||
|
* @returns A promise which resolves when rendering is complete.
|
||||||
|
*/
|
||||||
|
export function renderText(options) {
|
||||||
|
var _a, _b;
|
||||||
|
// Unpack the options.
|
||||||
|
const { host, sanitizer, source } = options;
|
||||||
|
// Create the HTML content.
|
||||||
|
const content = sanitizer.sanitize(Private.ansiSpan(source), {
|
||||||
|
allowedTags: ["span"],
|
||||||
|
});
|
||||||
|
// Set the sanitized content for the host node.
|
||||||
|
const pre = document.createElement("pre");
|
||||||
|
pre.innerHTML = content;
|
||||||
|
const preTextContent = pre.textContent;
|
||||||
|
if (preTextContent) {
|
||||||
|
// Note: only text nodes and span elements should be present after sanitization in the `<pre>` element.
|
||||||
|
const linkedNodes = autolink(preTextContent);
|
||||||
|
let inAnchorElement = false;
|
||||||
|
const combinedNodes = [];
|
||||||
|
const preNodes = Array.from(pre.childNodes);
|
||||||
|
while (preNodes.length && linkedNodes.length) {
|
||||||
|
// Use non-null assertions to workaround TypeScript context awareness limitation
|
||||||
|
// (if any of the arrays were empty, we would not enter the body of the loop).
|
||||||
|
let preNode = preNodes.shift();
|
||||||
|
let linkNode = linkedNodes.shift();
|
||||||
|
// This should never happen because we modify the arrays in flight so they should end simultaneously,
|
||||||
|
// but this makes the coding assistance happy and might make it easier to conceptualize.
|
||||||
|
if (typeof preNode === "undefined") {
|
||||||
|
combinedNodes.push(linkNode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (typeof linkNode === "undefined") {
|
||||||
|
combinedNodes.push(preNode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let preLen =
|
||||||
|
(_a = preNode.textContent) === null || _a === void 0
|
||||||
|
? void 0
|
||||||
|
: _a.length;
|
||||||
|
let linkLen =
|
||||||
|
(_b = linkNode.textContent) === null || _b === void 0
|
||||||
|
? void 0
|
||||||
|
: _b.length;
|
||||||
|
if (preLen && linkLen) {
|
||||||
|
if (preLen > linkLen) {
|
||||||
|
// Split pre node and only keep the shorter part
|
||||||
|
let { pre: keep, post: postpone } = splitShallowNode(
|
||||||
|
preNode,
|
||||||
|
linkLen
|
||||||
|
);
|
||||||
|
preNodes.unshift(postpone);
|
||||||
|
preNode = keep;
|
||||||
|
} else if (linkLen > preLen) {
|
||||||
|
let { pre: keep, post: postpone } = splitShallowNode(
|
||||||
|
linkNode,
|
||||||
|
preLen
|
||||||
|
);
|
||||||
|
linkedNodes.unshift(postpone);
|
||||||
|
linkNode = keep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const lastCombined = combinedNodes[combinedNodes.length - 1];
|
||||||
|
// If we are already in an anchor element and the anchor element did not change,
|
||||||
|
// we should insert the node from <pre> which is either Text node or coloured span Element
|
||||||
|
// into the anchor content as a child
|
||||||
|
if (inAnchorElement && linkNode.href === lastCombined.href) {
|
||||||
|
lastCombined.appendChild(preNode);
|
||||||
|
} else {
|
||||||
|
// the `linkNode` is either Text or AnchorElement;
|
||||||
|
const isAnchor = linkNode.nodeType !== Node.TEXT_NODE;
|
||||||
|
// if we are NOT about to start an anchor element, just add the pre Node
|
||||||
|
if (!isAnchor) {
|
||||||
|
combinedNodes.push(preNode);
|
||||||
|
inAnchorElement = false;
|
||||||
|
} else {
|
||||||
|
// otherwise start a new anchor; the contents of the `linkNode` and `preNode` should be the same,
|
||||||
|
// so we just put the neatly formatted `preNode` inside the anchor node (`linkNode`)
|
||||||
|
// and append that to combined nodes.
|
||||||
|
linkNode.textContent = "";
|
||||||
|
linkNode.appendChild(preNode);
|
||||||
|
combinedNodes.push(linkNode);
|
||||||
|
inAnchorElement = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: replace with `.replaceChildren()` once the target ES version allows it
|
||||||
|
pre.innerHTML = "";
|
||||||
|
for (const child of combinedNodes) {
|
||||||
|
pre.appendChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
host.appendChild(pre);
|
||||||
|
// Return the rendered promise.
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The namespace for module implementation details.
|
||||||
|
*/
|
||||||
|
var Private;
|
||||||
|
(function (Private) {
|
||||||
|
/**
|
||||||
|
* Eval the script tags contained in a host populated by `innerHTML`.
|
||||||
|
*
|
||||||
|
* When script tags are created via `innerHTML`, the browser does not
|
||||||
|
* evaluate them when they are added to the page. This function works
|
||||||
|
* around that by creating new equivalent script nodes manually, and
|
||||||
|
* replacing the originals.
|
||||||
|
*/
|
||||||
|
function evalInnerHTMLScriptTags(host) {
|
||||||
|
// Create a snapshot of the current script nodes.
|
||||||
|
const scripts = Array.from(host.getElementsByTagName("script"));
|
||||||
|
// Loop over each script node.
|
||||||
|
for (const script of scripts) {
|
||||||
|
// Skip any scripts which no longer have a parent.
|
||||||
|
if (!script.parentNode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Create a new script node which will be clone.
|
||||||
|
const clone = document.createElement("script");
|
||||||
|
// Copy the attributes into the clone.
|
||||||
|
const attrs = script.attributes;
|
||||||
|
for (let i = 0, n = attrs.length; i < n; ++i) {
|
||||||
|
const { name, value } = attrs[i];
|
||||||
|
clone.setAttribute(name, value);
|
||||||
|
}
|
||||||
|
// Copy the text content into the clone.
|
||||||
|
clone.textContent = script.textContent;
|
||||||
|
// Replace the old script in the parent.
|
||||||
|
script.parentNode.replaceChild(clone, script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Private.evalInnerHTMLScriptTags = evalInnerHTMLScriptTags;
|
||||||
|
/**
|
||||||
|
* Handle the default behavior of nodes.
|
||||||
|
*/
|
||||||
|
function handleDefaults(node) {
|
||||||
|
// Handle anchor elements.
|
||||||
|
const anchors = node.getElementsByTagName("a");
|
||||||
|
for (let i = 0; i < anchors.length; i++) {
|
||||||
|
const el = anchors[i];
|
||||||
|
// skip when processing a elements inside svg
|
||||||
|
// which are of type SVGAnimatedString
|
||||||
|
if (!(el instanceof HTMLAnchorElement)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const path = el.href;
|
||||||
|
const isLocal = URLExt.isLocal(path);
|
||||||
|
// set target attribute if not already present
|
||||||
|
if (!el.target) {
|
||||||
|
el.target = isLocal ? "_self" : "_blank";
|
||||||
|
}
|
||||||
|
// set rel as 'noopener' for non-local anchors
|
||||||
|
if (!isLocal) {
|
||||||
|
el.rel = "noopener";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle image elements.
|
||||||
|
const imgs = node.getElementsByTagName("img");
|
||||||
|
for (let i = 0; i < imgs.length; i++) {
|
||||||
|
if (!imgs[i].alt) {
|
||||||
|
imgs[i].alt = "Image";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Private.handleDefaults = handleDefaults;
|
||||||
|
|
||||||
|
const ANSI_COLORS = [
|
||||||
|
"ansi-black",
|
||||||
|
"ansi-red",
|
||||||
|
"ansi-green",
|
||||||
|
"ansi-yellow",
|
||||||
|
"ansi-blue",
|
||||||
|
"ansi-magenta",
|
||||||
|
"ansi-cyan",
|
||||||
|
"ansi-white",
|
||||||
|
"ansi-black-intense",
|
||||||
|
"ansi-red-intense",
|
||||||
|
"ansi-green-intense",
|
||||||
|
"ansi-yellow-intense",
|
||||||
|
"ansi-blue-intense",
|
||||||
|
"ansi-magenta-intense",
|
||||||
|
"ansi-cyan-intense",
|
||||||
|
"ansi-white-intense",
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* Create HTML tags for a string with given foreground, background etc. and
|
||||||
|
* add them to the `out` array.
|
||||||
|
*/
|
||||||
|
function pushColoredChunk(chunk, fg, bg, bold, underline, inverse, out) {
|
||||||
|
if (chunk) {
|
||||||
|
const classes = [];
|
||||||
|
const styles = [];
|
||||||
|
if (bold && typeof fg === "number" && 0 <= fg && fg < 8) {
|
||||||
|
fg += 8; // Bold text uses "intense" colors
|
||||||
|
}
|
||||||
|
if (inverse) {
|
||||||
|
[fg, bg] = [bg, fg];
|
||||||
|
}
|
||||||
|
if (typeof fg === "number") {
|
||||||
|
classes.push(ANSI_COLORS[fg] + "-fg");
|
||||||
|
} else if (fg.length) {
|
||||||
|
styles.push(`color: rgb(${fg})`);
|
||||||
|
} else if (inverse) {
|
||||||
|
classes.push("ansi-default-inverse-fg");
|
||||||
|
}
|
||||||
|
if (typeof bg === "number") {
|
||||||
|
classes.push(ANSI_COLORS[bg] + "-bg");
|
||||||
|
} else if (bg.length) {
|
||||||
|
styles.push(`background-color: rgb(${bg})`);
|
||||||
|
} else if (inverse) {
|
||||||
|
classes.push("ansi-default-inverse-bg");
|
||||||
|
}
|
||||||
|
if (bold) {
|
||||||
|
classes.push("ansi-bold");
|
||||||
|
}
|
||||||
|
if (underline) {
|
||||||
|
classes.push("ansi-underline");
|
||||||
|
}
|
||||||
|
if (classes.length || styles.length) {
|
||||||
|
out.push("<span");
|
||||||
|
if (classes.length) {
|
||||||
|
out.push(` class="${classes.join(" ")}"`);
|
||||||
|
}
|
||||||
|
if (styles.length) {
|
||||||
|
out.push(` style="${styles.join("; ")}"`);
|
||||||
|
}
|
||||||
|
out.push(">");
|
||||||
|
out.push(chunk);
|
||||||
|
out.push("</span>");
|
||||||
|
} else {
|
||||||
|
out.push(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convert ANSI extended colors to R/G/B triple.
|
||||||
|
*/
|
||||||
|
function getExtendedColors(numbers) {
|
||||||
|
let r;
|
||||||
|
let g;
|
||||||
|
let b;
|
||||||
|
const n = numbers.shift();
|
||||||
|
if (n === 2 && numbers.length >= 3) {
|
||||||
|
// 24-bit RGB
|
||||||
|
r = numbers.shift();
|
||||||
|
g = numbers.shift();
|
||||||
|
b = numbers.shift();
|
||||||
|
if ([r, g, b].some((c) => c < 0 || 255 < c)) {
|
||||||
|
throw new RangeError("Invalid range for RGB colors");
|
||||||
|
}
|
||||||
|
} else if (n === 5 && numbers.length >= 1) {
|
||||||
|
// 256 colors
|
||||||
|
const idx = numbers.shift();
|
||||||
|
if (idx < 0) {
|
||||||
|
throw new RangeError("Color index must be >= 0");
|
||||||
|
} else if (idx < 16) {
|
||||||
|
// 16 default terminal colors
|
||||||
|
return idx;
|
||||||
|
} else if (idx < 232) {
|
||||||
|
// 6x6x6 color cube, see https://stackoverflow.com/a/27165165/500098
|
||||||
|
r = Math.floor((idx - 16) / 36);
|
||||||
|
r = r > 0 ? 55 + r * 40 : 0;
|
||||||
|
g = Math.floor(((idx - 16) % 36) / 6);
|
||||||
|
g = g > 0 ? 55 + g * 40 : 0;
|
||||||
|
b = (idx - 16) % 6;
|
||||||
|
b = b > 0 ? 55 + b * 40 : 0;
|
||||||
|
} else if (idx < 256) {
|
||||||
|
// grayscale, see https://stackoverflow.com/a/27165165/500098
|
||||||
|
r = g = b = (idx - 232) * 10 + 8;
|
||||||
|
} else {
|
||||||
|
throw new RangeError("Color index must be < 256");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RangeError("Invalid extended color specification");
|
||||||
|
}
|
||||||
|
return [r, g, b];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transform ANSI color escape codes into HTML <span> tags with CSS
|
||||||
|
* classes such as "ansi-green-intense-fg".
|
||||||
|
* The actual colors used are set in the CSS file.
|
||||||
|
* This also removes non-color escape sequences.
|
||||||
|
* This is supposed to have the same behavior as nbconvert.filters.ansi2html()
|
||||||
|
*/
|
||||||
|
function ansiSpan(str) {
|
||||||
|
const ansiRe = /\x1b\[(.*?)([@-~])/g; // eslint-disable-line no-control-regex
|
||||||
|
let fg = [];
|
||||||
|
let bg = [];
|
||||||
|
let bold = false;
|
||||||
|
let underline = false;
|
||||||
|
let inverse = false;
|
||||||
|
let match;
|
||||||
|
const out = [];
|
||||||
|
const numbers = [];
|
||||||
|
let start = 0;
|
||||||
|
str = escape(str);
|
||||||
|
str += "\x1b[m"; // Ensure markup for trailing text
|
||||||
|
// tslint:disable-next-line
|
||||||
|
while ((match = ansiRe.exec(str))) {
|
||||||
|
if (match[2] === "m") {
|
||||||
|
const items = match[1].split(";");
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
if (item === "") {
|
||||||
|
numbers.push(0);
|
||||||
|
} else if (item.search(/^\d+$/) !== -1) {
|
||||||
|
numbers.push(parseInt(item, 10));
|
||||||
|
} else {
|
||||||
|
// Ignored: Invalid color specification
|
||||||
|
numbers.length = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Ignored: Not a color code
|
||||||
|
}
|
||||||
|
const chunk = str.substring(start, match.index);
|
||||||
|
pushColoredChunk(chunk, fg, bg, bold, underline, inverse, out);
|
||||||
|
start = ansiRe.lastIndex;
|
||||||
|
while (numbers.length) {
|
||||||
|
const n = numbers.shift();
|
||||||
|
switch (n) {
|
||||||
|
case 0:
|
||||||
|
fg = bg = [];
|
||||||
|
bold = false;
|
||||||
|
underline = false;
|
||||||
|
inverse = false;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 5:
|
||||||
|
bold = true;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
underline = true;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
inverse = true;
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
case 22:
|
||||||
|
bold = false;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
underline = false;
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
inverse = false;
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
case 31:
|
||||||
|
case 32:
|
||||||
|
case 33:
|
||||||
|
case 34:
|
||||||
|
case 35:
|
||||||
|
case 36:
|
||||||
|
case 37:
|
||||||
|
fg = n - 30;
|
||||||
|
break;
|
||||||
|
case 38:
|
||||||
|
try {
|
||||||
|
fg = getExtendedColors(numbers);
|
||||||
|
} catch (e) {
|
||||||
|
numbers.length = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
fg = [];
|
||||||
|
break;
|
||||||
|
case 40:
|
||||||
|
case 41:
|
||||||
|
case 42:
|
||||||
|
case 43:
|
||||||
|
case 44:
|
||||||
|
case 45:
|
||||||
|
case 46:
|
||||||
|
case 47:
|
||||||
|
bg = n - 40;
|
||||||
|
break;
|
||||||
|
case 48:
|
||||||
|
try {
|
||||||
|
bg = getExtendedColors(numbers);
|
||||||
|
} catch (e) {
|
||||||
|
numbers.length = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 49:
|
||||||
|
bg = [];
|
||||||
|
break;
|
||||||
|
case 90:
|
||||||
|
case 91:
|
||||||
|
case 92:
|
||||||
|
case 93:
|
||||||
|
case 94:
|
||||||
|
case 95:
|
||||||
|
case 96:
|
||||||
|
case 97:
|
||||||
|
fg = n - 90 + 8;
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
case 101:
|
||||||
|
case 102:
|
||||||
|
case 103:
|
||||||
|
case 104:
|
||||||
|
case 105:
|
||||||
|
case 106:
|
||||||
|
case 107:
|
||||||
|
bg = n - 100 + 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown codes are ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.join("");
|
||||||
|
}
|
||||||
|
Private.ansiSpan = ansiSpan;
|
||||||
|
})(Private || (Private = {}));
|
||||||
948
utils/notebook/sanitizer.js
Normal file
948
utils/notebook/sanitizer.js
Normal file
@@ -0,0 +1,948 @@
|
|||||||
|
/* eslint-disable no-useless-escape */
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
// Copyright (c) Jupyter Development Team.
|
||||||
|
// Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本文件为 Jupyter lab 源码。
|
||||||
|
* 用于字符串无害化处理
|
||||||
|
*
|
||||||
|
* 源码TS版:https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/src/sanitizer.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
import sanitize from "sanitize-html";
|
||||||
|
/**
|
||||||
|
* Helper class that contains regular expressions for inline CSS style validation.
|
||||||
|
*
|
||||||
|
* Which properties (and values) to allow is largely based on the Google Caja project:
|
||||||
|
* https://github.com/google/caja
|
||||||
|
*
|
||||||
|
* The regular expressions are largly based on the syntax definition found at
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/CSS.
|
||||||
|
*/
|
||||||
|
class CssProp {
|
||||||
|
static reg(r) {
|
||||||
|
return new RegExp("^" + r + "$", "i");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Numeric base expressions used to help build more complex regular expressions
|
||||||
|
*/
|
||||||
|
CssProp.N = {
|
||||||
|
integer: `[+-]?[0-9]+`,
|
||||||
|
integer_pos: `[+]?[0-9]+`,
|
||||||
|
integer_zero_ff: `([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])`,
|
||||||
|
number: `[+-]?([0-9]*[.])?[0-9]+(e-?[0-9]*)?`,
|
||||||
|
number_pos: `[+]?([0-9]*[.])?[0-9]+(e-?[0-9]*)?`,
|
||||||
|
number_zero_hundred: `[+]?(([0-9]|[1-9][0-9])([.][0-9]+)?|100)`,
|
||||||
|
number_zero_one: `[+]?(1([.][0]+)?|0?([.][0-9]+)?)`,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Base expressions of common CSS syntax elements
|
||||||
|
*/
|
||||||
|
CssProp.B = {
|
||||||
|
angle: `(${CssProp.N.number}(deg|rad|grad|turn)|0)`,
|
||||||
|
frequency: `${CssProp.N.number}(Hz|kHz)`,
|
||||||
|
ident: String.raw`-?([_a-z]|[\xA0-\xFF]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])([_a-z0-9-]|[\xA0-\xFF]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*`,
|
||||||
|
len_or_perc: `(0|${CssProp.N.number}(px|em|rem|ex|in|cm|mm|pt|pc|%))`,
|
||||||
|
length: `(${CssProp.N.number}(px|em|rem|ex|in|cm|mm|pt|pc)|0)`,
|
||||||
|
length_pos: `(${CssProp.N.number_pos}(px|em|rem|ex|in|cm|mm|pt|pc)|0)`,
|
||||||
|
percentage: `${CssProp.N.number}%`,
|
||||||
|
percentage_pos: `${CssProp.N.number_pos}%`,
|
||||||
|
percentage_zero_hundred: `${CssProp.N.number_zero_hundred}%`,
|
||||||
|
string: String.raw`(\"([^\n\r\f\\"]|\\\n|\r\n|\r|\f|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*\")|(\'([^\n\r\f\\']|\\\n|\r\n|\r|\f|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*\')`,
|
||||||
|
time: `${CssProp.N.number}(s|ms)`,
|
||||||
|
url: `url\\(.*?\\)`,
|
||||||
|
z_index: `[+-]?[0-9]{1,7}`,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Atomic (i.e. not dependant on other regular expressions) sub RegEx segments
|
||||||
|
*/
|
||||||
|
CssProp.A = {
|
||||||
|
absolute_size: `xx-small|x-small|small|medium|large|x-large|xx-large`,
|
||||||
|
attachment: `scroll|fixed|local`,
|
||||||
|
bg_origin: `border-box|padding-box|content-box`,
|
||||||
|
border_style: `none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset`,
|
||||||
|
box: `border-box|padding-box|content-box`,
|
||||||
|
display_inside: `auto|block|table|flex|grid`,
|
||||||
|
display_outside: `block-level|inline-level|none|table-row-group|table-header-group|table-footer-group|table-row|table-cell|table-column-group|table-column|table-caption`,
|
||||||
|
ending_shape: `circle|ellipse`,
|
||||||
|
generic_family: `serif|sans-serif|cursive|fantasy|monospace`,
|
||||||
|
generic_voice: `male|female|child`,
|
||||||
|
relative_size: `smaller|larger`,
|
||||||
|
repeat_style: `repeat-x|repeat-y|((?:repeat|space|round|no-repeat)(?:\\s*(?:repeat|space|round|no-repeat))?)`,
|
||||||
|
side_or_corner: `(left|right)?\\s*(top|bottom)?`,
|
||||||
|
single_animation_direction: `normal|reverse|alternate|alternate-reverse`,
|
||||||
|
single_animation_fill_mode: `none|forwards|backwards|both`,
|
||||||
|
single_animation_play_state: `running|paused`,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Color definition sub expressions
|
||||||
|
*/
|
||||||
|
CssProp._COLOR = {
|
||||||
|
hex: `\\#(0x)?[0-9a-f]+`,
|
||||||
|
name: `aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|transparent|violet|wheat|white|whitesmoke|yellow|yellowgreen`,
|
||||||
|
rgb: String.raw`rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)`,
|
||||||
|
rgba: String.raw`rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(${CssProp.N.integer_zero_ff}|${CssProp.N.number_zero_one}|${CssProp.B.percentage_zero_hundred})\s*\)`,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Compound (i.e. dependant on other (sub) regular expressions) sub RegEx segments
|
||||||
|
*/
|
||||||
|
CssProp._C = {
|
||||||
|
alpha: `${CssProp.N.integer_zero_ff}|${CssProp.N.number_zero_one}|${CssProp.B.percentage_zero_hundred}`,
|
||||||
|
alphavalue: CssProp.N.number_zero_one,
|
||||||
|
bg_position: `((${CssProp.B.len_or_perc}|left|center|right|top|bottom)\\s*){1,4}`,
|
||||||
|
bg_size: `(${CssProp.B.length_pos}|${CssProp.B.percentage}|auto){1,2}|cover|contain`,
|
||||||
|
border_width: `thin|medium|thick|${CssProp.B.length}`,
|
||||||
|
bottom: `${CssProp.B.length}|auto`,
|
||||||
|
color: `${CssProp._COLOR.hex}|${CssProp._COLOR.rgb}|${CssProp._COLOR.rgba}|${CssProp._COLOR.name}`,
|
||||||
|
color_stop_length: `(${CssProp.B.len_or_perc}\\s*){1,2}`,
|
||||||
|
linear_color_hint: `${CssProp.B.len_or_perc}`,
|
||||||
|
family_name: `${CssProp.B.string}|(${CssProp.B.ident}\\s*)+`,
|
||||||
|
image_decl: CssProp.B.url,
|
||||||
|
left: `${CssProp.B.length}|auto`,
|
||||||
|
loose_quotable_words: `(${CssProp.B.ident})+`,
|
||||||
|
margin_width: `${CssProp.B.len_or_perc}|auto`,
|
||||||
|
padding_width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}`,
|
||||||
|
page_url: CssProp.B.url,
|
||||||
|
position: `((${CssProp.B.len_or_perc}|left|center|right|top|bottom)\\s*){1,4}`,
|
||||||
|
right: `${CssProp.B.length}|auto`,
|
||||||
|
shadow: "",
|
||||||
|
size: `closest-side|farthest-side|closest-corner|farthest-corner|${CssProp.B.length}|(${CssProp.B.len_or_perc})\\s+(${CssProp.B.len_or_perc})`,
|
||||||
|
top: `${CssProp.B.length}|auto`,
|
||||||
|
};
|
||||||
|
CssProp._C1 = {
|
||||||
|
image_list: `image\\(\\s*(${CssProp.B.url})*\\s*(${CssProp.B.url}|${CssProp._C.color})\\s*\\)`,
|
||||||
|
linear_color_stop: `(${CssProp._C.color})(\\s*${CssProp._C.color_stop_length})?`,
|
||||||
|
shadow: `((${CssProp._C.color})\\s+((${CssProp.B.length})\\s*){2,4}(\s+inset)?)|((inset\\s+)?((${CssProp.B.length})\\s*){2,4}\\s*(${CssProp._C.color})?)`,
|
||||||
|
};
|
||||||
|
CssProp._C2 = {
|
||||||
|
color_stop_list: `((${CssProp._C1.linear_color_stop})(\\s*(${CssProp._C.linear_color_hint}))?\\s*,\\s*)+(${CssProp._C1.linear_color_stop})`,
|
||||||
|
shape: `rect\\(\\s*(${CssProp._C.top})\\s*,\\s*(${CssProp._C.right})\\s*,\\s*(${CssProp._C.bottom})\\s*,\\s*(${CssProp._C.left})\\s*\\)`,
|
||||||
|
};
|
||||||
|
CssProp._C3 = {
|
||||||
|
linear_gradient: `linear-gradient\\((((${CssProp.B.angle})|to\\s+(${CssProp.A.side_or_corner}))\\s*,\\s*)?\\s*(${CssProp._C2.color_stop_list})\\s*\\)`,
|
||||||
|
radial_gradient: `radial-gradient\\(((((${CssProp.A.ending_shape})|(${CssProp._C.size}))\\s*)*\\s*(at\\s+${CssProp._C.position})?\\s*,\\s*)?\\s*(${CssProp._C2.color_stop_list})\\s*\\)`,
|
||||||
|
};
|
||||||
|
CssProp._C4 = {
|
||||||
|
image: `${CssProp.B.url}|${CssProp._C3.linear_gradient}|${CssProp._C3.radial_gradient}|${CssProp._C1.image_list}`,
|
||||||
|
bg_image: `(${CssProp.B.url}|${CssProp._C3.linear_gradient}|${CssProp._C3.radial_gradient}|${CssProp._C1.image_list})|none`,
|
||||||
|
};
|
||||||
|
CssProp.C = {
|
||||||
|
...CssProp._C,
|
||||||
|
...CssProp._C1,
|
||||||
|
...CssProp._C2,
|
||||||
|
...CssProp._C3,
|
||||||
|
...CssProp._C4,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Property value regular expressions not dependant on other sub expressions
|
||||||
|
*/
|
||||||
|
CssProp.AP = {
|
||||||
|
border_collapse: `collapse|separate`,
|
||||||
|
box: `normal|none|contents`,
|
||||||
|
box_sizing: `content-box|padding-box|border-box`,
|
||||||
|
caption_side: `top|bottom`,
|
||||||
|
clear: `none|left|right|both`,
|
||||||
|
direction: `ltr|rtl`,
|
||||||
|
empty_cells: `show|hide`,
|
||||||
|
float: `left|right|none`,
|
||||||
|
font_stretch: `normal|wider|narrower|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded`,
|
||||||
|
font_style: `normal|italic|oblique`,
|
||||||
|
font_variant: `normal|small-caps`,
|
||||||
|
font_weight: `normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900`,
|
||||||
|
list_style_position: `inside|outside`,
|
||||||
|
list_style_type: `disc|circle|square|decimal|decimal-leading-zero|lower-roman|upper-roman|lower-greek|lower-latin|upper-latin|armenian|georgian|lower-alpha|upper-alpha|none`,
|
||||||
|
overflow: `visible|hidden|scroll|auto`,
|
||||||
|
overflow_wrap: `normal|break-word`,
|
||||||
|
overflow_x: `visible|hidden|scroll|auto|no-display|no-content`,
|
||||||
|
page_break_after: `auto|always|avoid|left|right`,
|
||||||
|
page_break_before: `auto|always|avoid|left|right`,
|
||||||
|
page_break_inside: `avoid|auto`,
|
||||||
|
position: `static|relative|absolute`,
|
||||||
|
resize: `none|both|horizontal|vertical`,
|
||||||
|
speak: `normal|none|spell-out`,
|
||||||
|
speak_header: `once|always`,
|
||||||
|
speak_numeral: `digits|continuous`,
|
||||||
|
speak_punctuation: `code|none`,
|
||||||
|
table_layout: `auto|fixed`,
|
||||||
|
text_align: `left|right|center|justify`,
|
||||||
|
text_decoration: `none|((underline|overline|line-through|blink)\\s*)+`,
|
||||||
|
text_transform: `capitalize|uppercase|lowercase|none`,
|
||||||
|
text_wrap: `normal|unrestricted|none|suppress`,
|
||||||
|
unicode_bidi: `normal|embed|bidi-override`,
|
||||||
|
visibility: `visible|hidden|collapse`,
|
||||||
|
white_space: `normal|pre|nowrap|pre-wrap|pre-line`,
|
||||||
|
word_break: `normal|keep-all|break-all`,
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Compound propertiy value regular expressions (i.e. dependant on other sub expressions)
|
||||||
|
*/
|
||||||
|
CssProp._CP = {
|
||||||
|
background_attachment: `${CssProp.A.attachment}(,\\s*${CssProp.A.attachment})*`,
|
||||||
|
background_color: CssProp.C.color,
|
||||||
|
background_origin: `${CssProp.A.box}(,\\s*${CssProp.A.box})*`,
|
||||||
|
background_repeat: `${CssProp.A.repeat_style}(,\\s*${CssProp.A.repeat_style})*`,
|
||||||
|
border: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
|
||||||
|
border_radius: `((${CssProp.B.len_or_perc})\\s*){1,4}(\\/\\s*((${CssProp.B.len_or_perc})\\s*){1,4})?`,
|
||||||
|
border_spacing: `${CssProp.B.length}\\s*(${CssProp.B.length})?`,
|
||||||
|
border_top_color: CssProp.C.color,
|
||||||
|
border_top_style: CssProp.A.border_style,
|
||||||
|
border_width: `((${CssProp.C.border_width})\\s*){1,4}`,
|
||||||
|
color: CssProp.C.color,
|
||||||
|
cursor: `(${CssProp.B.url}(\\s*,\\s*)?)*(auto|crosshair|default|pointer|move|e-resize|ne-resize|nw-resize|n-resize|se-resize|sw-resize|s-resize|w-resize|text|wait|help|progress|all-scroll|col-resize|hand|no-drop|not-allowed|row-resize|vertical-text)`,
|
||||||
|
display: `inline|block|list-item|run-in|inline-list-item|inline-block|table|inline-table|table-cell|table-caption|flex|inline-flex|grid|inline-grid|${CssProp.A.display_inside}|${CssProp.A.display_outside}|inherit|inline-box|inline-stack`,
|
||||||
|
display_outside: CssProp.A.display_outside,
|
||||||
|
elevation: `${CssProp.B.angle}|below|level|above|higher|lower`,
|
||||||
|
font_family: `(${CssProp.C.family_name}|${CssProp.A.generic_family})(,\\s*(${CssProp.C.family_name}|${CssProp.A.generic_family}))*`,
|
||||||
|
height: `${CssProp.B.length}|${CssProp.B.percentage}|auto`,
|
||||||
|
letter_spacing: `normal|${CssProp.B.length}`,
|
||||||
|
list_style_image: `${CssProp.C.image}|none`,
|
||||||
|
margin_right: CssProp.C.margin_width,
|
||||||
|
max_height: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|none|auto`,
|
||||||
|
min_height: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|auto`,
|
||||||
|
opacity: CssProp.C.alphavalue,
|
||||||
|
outline_color: `${CssProp.C.color}|invert`,
|
||||||
|
outline_width: CssProp.C.border_width,
|
||||||
|
padding: `((${CssProp.C.padding_width})\\s*){1,4}`,
|
||||||
|
padding_top: CssProp.C.padding_width,
|
||||||
|
pitch_range: CssProp.N.number,
|
||||||
|
right: `${CssProp.B.length}|${CssProp.B.percentage}|auto`,
|
||||||
|
stress: CssProp.N.number,
|
||||||
|
text_indent: `${CssProp.B.length}|${CssProp.B.percentage}`,
|
||||||
|
text_shadow: `none|${CssProp.C.shadow}(,\\s*(${CssProp.C.shadow}))*`,
|
||||||
|
volume: `${CssProp.N.number_pos}|${CssProp.B.percentage_pos}|silent|x-soft|soft|medium|loud|x-loud`,
|
||||||
|
word_wrap: CssProp.AP.overflow_wrap,
|
||||||
|
zoom: `normal|${CssProp.N.number_pos}|${CssProp.B.percentage_pos}`,
|
||||||
|
backface_visibility: CssProp.AP.visibility,
|
||||||
|
background_clip: `${CssProp.A.box}(,\\s*(${CssProp.A.box}))*`,
|
||||||
|
background_position: `${CssProp.C.bg_position}(,\\s*(${CssProp.C.bg_position}))*`,
|
||||||
|
border_bottom_color: CssProp.C.color,
|
||||||
|
border_bottom_style: CssProp.A.border_style,
|
||||||
|
border_color: `((${CssProp.C.color})\\s*){1,4}`,
|
||||||
|
border_left_color: CssProp.C.color,
|
||||||
|
border_right_color: CssProp.C.color,
|
||||||
|
border_style: `((${CssProp.A.border_style})\\s*){1,4}`,
|
||||||
|
border_top_left_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
|
||||||
|
border_top_width: CssProp.C.border_width,
|
||||||
|
box_shadow: `none|${CssProp.C.shadow}(,\\s*(${CssProp.C.shadow}))*`,
|
||||||
|
clip: `${CssProp.C.shape}|auto`,
|
||||||
|
display_inside: CssProp.A.display_inside,
|
||||||
|
font_size: `${CssProp.A.absolute_size}|${CssProp.A.relative_size}|${CssProp.B.length_pos}|${CssProp.B.percentage_pos}`,
|
||||||
|
line_height: `normal|${CssProp.N.number_pos}|${CssProp.B.length_pos}|${CssProp.B.percentage_pos}`,
|
||||||
|
margin_left: CssProp.C.margin_width,
|
||||||
|
max_width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|none|auto`,
|
||||||
|
outline_style: CssProp.A.border_style,
|
||||||
|
padding_bottom: CssProp.C.padding_width,
|
||||||
|
padding_right: CssProp.C.padding_width,
|
||||||
|
perspective: `none|${CssProp.B.length}`,
|
||||||
|
richness: CssProp.N.number,
|
||||||
|
text_overflow: `((clip|ellipsis|${CssProp.B.string})\\s*){1,2}`,
|
||||||
|
top: `${CssProp.B.length}|${CssProp.B.percentage}|auto`,
|
||||||
|
width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|auto`,
|
||||||
|
z_index: `auto|${CssProp.B.z_index}`,
|
||||||
|
// Simplified background
|
||||||
|
background: `(((${CssProp.C.bg_position}\\s*(\\/\\s*${CssProp.C.bg_size})?)|(${CssProp.A.repeat_style})|(${CssProp.A.attachment})|(${CssProp.A.bg_origin})|(${CssProp.C.bg_image})|(${CssProp.C.color}))\\s*)+`,
|
||||||
|
background_size: `${CssProp.C.bg_size}(,\\s*${CssProp.C.bg_size})*`,
|
||||||
|
border_bottom_left_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
|
||||||
|
border_bottom_width: CssProp.C.border_width,
|
||||||
|
border_left_style: CssProp.A.border_style,
|
||||||
|
border_right_style: CssProp.A.border_style,
|
||||||
|
border_top: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
|
||||||
|
bottom: `${CssProp.B.len_or_perc}|auto`,
|
||||||
|
list_style: `((${CssProp.AP.list_style_type}|${CssProp.AP.list_style_position}|${CssProp.C.image}|none})\\s*){1,3}`,
|
||||||
|
margin_top: CssProp.C.margin_width,
|
||||||
|
outline: `((${CssProp.C.color}|invert|${CssProp.A.border_style}|${CssProp.C.border_width})\\s*){1,3}`,
|
||||||
|
overflow_y: CssProp.AP.overflow_x,
|
||||||
|
pitch: `${CssProp.B.frequency}|x-low|low|medium|high|x-high`,
|
||||||
|
vertical_align: `baseline|sub|super|top|text-top|middle|bottom|text-bottom|${CssProp.B.len_or_perc}`,
|
||||||
|
word_spacing: `normal|${CssProp.B.length}`,
|
||||||
|
background_image: `${CssProp.C.bg_image}(,\\s*${CssProp.C.bg_image})*`,
|
||||||
|
border_bottom_right_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
|
||||||
|
border_left_width: CssProp.C.border_width,
|
||||||
|
border_right_width: CssProp.C.border_width,
|
||||||
|
left: `${CssProp.B.len_or_perc}|auto`,
|
||||||
|
margin_bottom: CssProp.C.margin_width,
|
||||||
|
pause_after: `${CssProp.B.time}|${CssProp.B.percentage}`,
|
||||||
|
speech_rate: `${CssProp.N.number}|x-slow|slow|medium|fast|x-fast|faster|slower`,
|
||||||
|
transition_duration: `${CssProp.B.time}(,\\s*${CssProp.B.time})*`,
|
||||||
|
border_bottom: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
|
||||||
|
border_right: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
|
||||||
|
margin: `((${CssProp.C.margin_width})\\s*){1,4}`,
|
||||||
|
padding_left: CssProp.C.padding_width,
|
||||||
|
border_left: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
|
||||||
|
quotes: `(${CssProp.B.string}\\s*${CssProp.B.string})+|none`,
|
||||||
|
border_top_right_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
|
||||||
|
min_width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|auto`,
|
||||||
|
};
|
||||||
|
CssProp._CP1 = {
|
||||||
|
font: `(((((${CssProp.AP.font_style}|${CssProp.AP.font_variant}|${CssProp.AP.font_weight})\\s*){1,3})?\\s*(${CssProp._CP.font_size})\\s*(\\/\\s*(${CssProp._CP.line_height}))?\\s+(${CssProp._CP.font_family}))|caption|icon|menu|message-box|small-caption|status-bar)`,
|
||||||
|
};
|
||||||
|
CssProp.CP = { ...CssProp._CP, ...CssProp._CP1 };
|
||||||
|
// CSS Property value validation regular expressions for use with sanitize-html
|
||||||
|
CssProp.BORDER_COLLAPSE = CssProp.reg(CssProp.AP.border_collapse);
|
||||||
|
CssProp.BOX = CssProp.reg(CssProp.AP.box);
|
||||||
|
CssProp.BOX_SIZING = CssProp.reg(CssProp.AP.box_sizing);
|
||||||
|
CssProp.CAPTION_SIDE = CssProp.reg(CssProp.AP.caption_side);
|
||||||
|
CssProp.CLEAR = CssProp.reg(CssProp.AP.clear);
|
||||||
|
CssProp.DIRECTION = CssProp.reg(CssProp.AP.direction);
|
||||||
|
CssProp.EMPTY_CELLS = CssProp.reg(CssProp.AP.empty_cells);
|
||||||
|
CssProp.FLOAT = CssProp.reg(CssProp.AP.float);
|
||||||
|
CssProp.FONT_STRETCH = CssProp.reg(CssProp.AP.font_stretch);
|
||||||
|
CssProp.FONT_STYLE = CssProp.reg(CssProp.AP.font_style);
|
||||||
|
CssProp.FONT_VARIANT = CssProp.reg(CssProp.AP.font_variant);
|
||||||
|
CssProp.FONT_WEIGHT = CssProp.reg(CssProp.AP.font_weight);
|
||||||
|
CssProp.LIST_STYLE_POSITION = CssProp.reg(CssProp.AP.list_style_position);
|
||||||
|
CssProp.LIST_STYLE_TYPE = CssProp.reg(CssProp.AP.list_style_type);
|
||||||
|
CssProp.OVERFLOW = CssProp.reg(CssProp.AP.overflow);
|
||||||
|
CssProp.OVERFLOW_WRAP = CssProp.reg(CssProp.AP.overflow_wrap);
|
||||||
|
CssProp.OVERFLOW_X = CssProp.reg(CssProp.AP.overflow_x);
|
||||||
|
CssProp.PAGE_BREAK_AFTER = CssProp.reg(CssProp.AP.page_break_after);
|
||||||
|
CssProp.PAGE_BREAK_BEFORE = CssProp.reg(CssProp.AP.page_break_before);
|
||||||
|
CssProp.PAGE_BREAK_INSIDE = CssProp.reg(CssProp.AP.page_break_inside);
|
||||||
|
CssProp.POSITION = CssProp.reg(CssProp.AP.position);
|
||||||
|
CssProp.RESIZE = CssProp.reg(CssProp.AP.resize);
|
||||||
|
CssProp.SPEAK = CssProp.reg(CssProp.AP.speak);
|
||||||
|
CssProp.SPEAK_HEADER = CssProp.reg(CssProp.AP.speak_header);
|
||||||
|
CssProp.SPEAK_NUMERAL = CssProp.reg(CssProp.AP.speak_numeral);
|
||||||
|
CssProp.SPEAK_PUNCTUATION = CssProp.reg(CssProp.AP.speak_punctuation);
|
||||||
|
CssProp.TABLE_LAYOUT = CssProp.reg(CssProp.AP.table_layout);
|
||||||
|
CssProp.TEXT_ALIGN = CssProp.reg(CssProp.AP.text_align);
|
||||||
|
CssProp.TEXT_DECORATION = CssProp.reg(CssProp.AP.text_decoration);
|
||||||
|
CssProp.TEXT_TRANSFORM = CssProp.reg(CssProp.AP.text_transform);
|
||||||
|
CssProp.TEXT_WRAP = CssProp.reg(CssProp.AP.text_wrap);
|
||||||
|
CssProp.UNICODE_BIDI = CssProp.reg(CssProp.AP.unicode_bidi);
|
||||||
|
CssProp.VISIBILITY = CssProp.reg(CssProp.AP.visibility);
|
||||||
|
CssProp.WHITE_SPACE = CssProp.reg(CssProp.AP.white_space);
|
||||||
|
CssProp.WORD_BREAK = CssProp.reg(CssProp.AP.word_break);
|
||||||
|
CssProp.BACKGROUND_ATTACHMENT = CssProp.reg(CssProp.CP.background_attachment);
|
||||||
|
CssProp.BACKGROUND_COLOR = CssProp.reg(CssProp.CP.background_color);
|
||||||
|
CssProp.BACKGROUND_ORIGIN = CssProp.reg(CssProp.CP.background_origin);
|
||||||
|
CssProp.BACKGROUND_REPEAT = CssProp.reg(CssProp.CP.background_repeat);
|
||||||
|
CssProp.BORDER = CssProp.reg(CssProp.CP.border);
|
||||||
|
CssProp.BORDER_RADIUS = CssProp.reg(CssProp.CP.border_radius);
|
||||||
|
CssProp.BORDER_SPACING = CssProp.reg(CssProp.CP.border_spacing);
|
||||||
|
CssProp.BORDER_TOP_COLOR = CssProp.reg(CssProp.CP.border_top_color);
|
||||||
|
CssProp.BORDER_TOP_STYLE = CssProp.reg(CssProp.CP.border_top_style);
|
||||||
|
CssProp.BORDER_WIDTH = CssProp.reg(CssProp.CP.border_width);
|
||||||
|
CssProp.COLOR = CssProp.reg(CssProp.CP.color);
|
||||||
|
CssProp.CURSOR = CssProp.reg(CssProp.CP.cursor);
|
||||||
|
CssProp.DISPLAY = CssProp.reg(CssProp.CP.display);
|
||||||
|
CssProp.DISPLAY_OUTSIDE = CssProp.reg(CssProp.CP.display_outside);
|
||||||
|
CssProp.ELEVATION = CssProp.reg(CssProp.CP.elevation);
|
||||||
|
CssProp.FONT_FAMILY = CssProp.reg(CssProp.CP.font_family);
|
||||||
|
CssProp.HEIGHT = CssProp.reg(CssProp.CP.height);
|
||||||
|
CssProp.LETTER_SPACING = CssProp.reg(CssProp.CP.letter_spacing);
|
||||||
|
CssProp.LIST_STYLE_IMAGE = CssProp.reg(CssProp.CP.list_style_image);
|
||||||
|
CssProp.MARGIN_RIGHT = CssProp.reg(CssProp.CP.margin_right);
|
||||||
|
CssProp.MAX_HEIGHT = CssProp.reg(CssProp.CP.max_height);
|
||||||
|
CssProp.MIN_HEIGHT = CssProp.reg(CssProp.CP.min_height);
|
||||||
|
CssProp.OPACITY = CssProp.reg(CssProp.CP.opacity);
|
||||||
|
CssProp.OUTLINE_COLOR = CssProp.reg(CssProp.CP.outline_color);
|
||||||
|
CssProp.OUTLINE_WIDTH = CssProp.reg(CssProp.CP.outline_width);
|
||||||
|
CssProp.PADDING = CssProp.reg(CssProp.CP.padding);
|
||||||
|
CssProp.PADDING_TOP = CssProp.reg(CssProp.CP.padding_top);
|
||||||
|
CssProp.PITCH_RANGE = CssProp.reg(CssProp.CP.pitch_range);
|
||||||
|
CssProp.RIGHT = CssProp.reg(CssProp.CP.right);
|
||||||
|
CssProp.STRESS = CssProp.reg(CssProp.CP.stress);
|
||||||
|
CssProp.TEXT_INDENT = CssProp.reg(CssProp.CP.text_indent);
|
||||||
|
CssProp.TEXT_SHADOW = CssProp.reg(CssProp.CP.text_shadow);
|
||||||
|
CssProp.VOLUME = CssProp.reg(CssProp.CP.volume);
|
||||||
|
CssProp.WORD_WRAP = CssProp.reg(CssProp.CP.word_wrap);
|
||||||
|
CssProp.ZOOM = CssProp.reg(CssProp.CP.zoom);
|
||||||
|
CssProp.BACKFACE_VISIBILITY = CssProp.reg(CssProp.CP.backface_visibility);
|
||||||
|
CssProp.BACKGROUND_CLIP = CssProp.reg(CssProp.CP.background_clip);
|
||||||
|
CssProp.BACKGROUND_POSITION = CssProp.reg(CssProp.CP.background_position);
|
||||||
|
CssProp.BORDER_BOTTOM_COLOR = CssProp.reg(CssProp.CP.border_bottom_color);
|
||||||
|
CssProp.BORDER_BOTTOM_STYLE = CssProp.reg(CssProp.CP.border_bottom_style);
|
||||||
|
CssProp.BORDER_COLOR = CssProp.reg(CssProp.CP.border_color);
|
||||||
|
CssProp.BORDER_LEFT_COLOR = CssProp.reg(CssProp.CP.border_left_color);
|
||||||
|
CssProp.BORDER_RIGHT_COLOR = CssProp.reg(CssProp.CP.border_right_color);
|
||||||
|
CssProp.BORDER_STYLE = CssProp.reg(CssProp.CP.border_style);
|
||||||
|
CssProp.BORDER_TOP_LEFT_RADIUS = CssProp.reg(CssProp.CP.border_top_left_radius);
|
||||||
|
CssProp.BORDER_TOP_WIDTH = CssProp.reg(CssProp.CP.border_top_width);
|
||||||
|
CssProp.BOX_SHADOW = CssProp.reg(CssProp.CP.box_shadow);
|
||||||
|
CssProp.CLIP = CssProp.reg(CssProp.CP.clip);
|
||||||
|
CssProp.DISPLAY_INSIDE = CssProp.reg(CssProp.CP.display_inside);
|
||||||
|
CssProp.FONT_SIZE = CssProp.reg(CssProp.CP.font_size);
|
||||||
|
CssProp.LINE_HEIGHT = CssProp.reg(CssProp.CP.line_height);
|
||||||
|
CssProp.MARGIN_LEFT = CssProp.reg(CssProp.CP.margin_left);
|
||||||
|
CssProp.MAX_WIDTH = CssProp.reg(CssProp.CP.max_width);
|
||||||
|
CssProp.OUTLINE_STYLE = CssProp.reg(CssProp.CP.outline_style);
|
||||||
|
CssProp.PADDING_BOTTOM = CssProp.reg(CssProp.CP.padding_bottom);
|
||||||
|
CssProp.PADDING_RIGHT = CssProp.reg(CssProp.CP.padding_right);
|
||||||
|
CssProp.PERSPECTIVE = CssProp.reg(CssProp.CP.perspective);
|
||||||
|
CssProp.RICHNESS = CssProp.reg(CssProp.CP.richness);
|
||||||
|
CssProp.TEXT_OVERFLOW = CssProp.reg(CssProp.CP.text_overflow);
|
||||||
|
CssProp.TOP = CssProp.reg(CssProp.CP.top);
|
||||||
|
CssProp.WIDTH = CssProp.reg(CssProp.CP.width);
|
||||||
|
CssProp.Z_INDEX = CssProp.reg(CssProp.CP.z_index);
|
||||||
|
CssProp.BACKGROUND = CssProp.reg(CssProp.CP.background);
|
||||||
|
CssProp.BACKGROUND_SIZE = CssProp.reg(CssProp.CP.background_size);
|
||||||
|
CssProp.BORDER_BOTTOM_LEFT_RADIUS = CssProp.reg(
|
||||||
|
CssProp.CP.border_bottom_left_radius
|
||||||
|
);
|
||||||
|
CssProp.BORDER_BOTTOM_WIDTH = CssProp.reg(CssProp.CP.border_bottom_width);
|
||||||
|
CssProp.BORDER_LEFT_STYLE = CssProp.reg(CssProp.CP.border_left_style);
|
||||||
|
CssProp.BORDER_RIGHT_STYLE = CssProp.reg(CssProp.CP.border_right_style);
|
||||||
|
CssProp.BORDER_TOP = CssProp.reg(CssProp.CP.border_top);
|
||||||
|
CssProp.BOTTOM = CssProp.reg(CssProp.CP.bottom);
|
||||||
|
CssProp.LIST_STYLE = CssProp.reg(CssProp.CP.list_style);
|
||||||
|
CssProp.MARGIN_TOP = CssProp.reg(CssProp.CP.margin_top);
|
||||||
|
CssProp.OUTLINE = CssProp.reg(CssProp.CP.outline);
|
||||||
|
CssProp.OVERFLOW_Y = CssProp.reg(CssProp.CP.overflow_y);
|
||||||
|
CssProp.PITCH = CssProp.reg(CssProp.CP.pitch);
|
||||||
|
CssProp.VERTICAL_ALIGN = CssProp.reg(CssProp.CP.vertical_align);
|
||||||
|
CssProp.WORD_SPACING = CssProp.reg(CssProp.CP.word_spacing);
|
||||||
|
CssProp.BACKGROUND_IMAGE = CssProp.reg(CssProp.CP.background_image);
|
||||||
|
CssProp.BORDER_BOTTOM_RIGHT_RADIUS = CssProp.reg(
|
||||||
|
CssProp.CP.border_bottom_right_radius
|
||||||
|
);
|
||||||
|
CssProp.BORDER_LEFT_WIDTH = CssProp.reg(CssProp.CP.border_left_width);
|
||||||
|
CssProp.BORDER_RIGHT_WIDTH = CssProp.reg(CssProp.CP.border_right_width);
|
||||||
|
CssProp.LEFT = CssProp.reg(CssProp.CP.left);
|
||||||
|
CssProp.MARGIN_BOTTOM = CssProp.reg(CssProp.CP.margin_bottom);
|
||||||
|
CssProp.PAUSE_AFTER = CssProp.reg(CssProp.CP.pause_after);
|
||||||
|
CssProp.SPEECH_RATE = CssProp.reg(CssProp.CP.speech_rate);
|
||||||
|
CssProp.TRANSITION_DURATION = CssProp.reg(CssProp.CP.transition_duration);
|
||||||
|
CssProp.BORDER_BOTTOM = CssProp.reg(CssProp.CP.border_bottom);
|
||||||
|
CssProp.BORDER_RIGHT = CssProp.reg(CssProp.CP.border_right);
|
||||||
|
CssProp.MARGIN = CssProp.reg(CssProp.CP.margin);
|
||||||
|
CssProp.PADDING_LEFT = CssProp.reg(CssProp.CP.padding_left);
|
||||||
|
CssProp.BORDER_LEFT = CssProp.reg(CssProp.CP.border_left);
|
||||||
|
CssProp.FONT = CssProp.reg(CssProp.CP.font);
|
||||||
|
CssProp.QUOTES = CssProp.reg(CssProp.CP.quotes);
|
||||||
|
CssProp.BORDER_TOP_RIGHT_RADIUS = CssProp.reg(
|
||||||
|
CssProp.CP.border_top_right_radius
|
||||||
|
);
|
||||||
|
CssProp.MIN_WIDTH = CssProp.reg(CssProp.CP.min_width);
|
||||||
|
/**
|
||||||
|
* A class to sanitize HTML strings.
|
||||||
|
*/
|
||||||
|
export class Sanitizer {
|
||||||
|
constructor() {
|
||||||
|
this._options = {
|
||||||
|
// HTML tags that are allowed to be used. Tags were extracted from Google Caja
|
||||||
|
allowedTags: [
|
||||||
|
"a",
|
||||||
|
"abbr",
|
||||||
|
"acronym",
|
||||||
|
"address",
|
||||||
|
"area",
|
||||||
|
"article",
|
||||||
|
"aside",
|
||||||
|
"audio",
|
||||||
|
"b",
|
||||||
|
"bdi",
|
||||||
|
"bdo",
|
||||||
|
"big",
|
||||||
|
"blockquote",
|
||||||
|
"br",
|
||||||
|
"button",
|
||||||
|
"canvas",
|
||||||
|
"caption",
|
||||||
|
"center",
|
||||||
|
"cite",
|
||||||
|
"code",
|
||||||
|
"col",
|
||||||
|
"colgroup",
|
||||||
|
"colspan",
|
||||||
|
"command",
|
||||||
|
"data",
|
||||||
|
"datalist",
|
||||||
|
"dd",
|
||||||
|
"del",
|
||||||
|
"details",
|
||||||
|
"dfn",
|
||||||
|
"dir",
|
||||||
|
"div",
|
||||||
|
"dl",
|
||||||
|
"dt",
|
||||||
|
"em",
|
||||||
|
"fieldset",
|
||||||
|
"figcaption",
|
||||||
|
"figure",
|
||||||
|
"font",
|
||||||
|
"footer",
|
||||||
|
"form",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"h4",
|
||||||
|
"h5",
|
||||||
|
"h6",
|
||||||
|
"header",
|
||||||
|
"hgroup",
|
||||||
|
"hr",
|
||||||
|
"i",
|
||||||
|
// 'iframe' is allowed by Google Caja, but disallowed by default by sanitize-html
|
||||||
|
// , 'iframe'
|
||||||
|
"img",
|
||||||
|
"input",
|
||||||
|
"ins",
|
||||||
|
"kbd",
|
||||||
|
"label",
|
||||||
|
"legend",
|
||||||
|
"li",
|
||||||
|
"map",
|
||||||
|
"mark",
|
||||||
|
"menu",
|
||||||
|
"meter",
|
||||||
|
"nav",
|
||||||
|
"nobr",
|
||||||
|
"ol",
|
||||||
|
"optgroup",
|
||||||
|
"option",
|
||||||
|
"output",
|
||||||
|
"p",
|
||||||
|
"pre",
|
||||||
|
"progress",
|
||||||
|
"q",
|
||||||
|
"rowspan",
|
||||||
|
"s",
|
||||||
|
"samp",
|
||||||
|
"section",
|
||||||
|
"select",
|
||||||
|
"small",
|
||||||
|
"source",
|
||||||
|
"span",
|
||||||
|
"strike",
|
||||||
|
"strong",
|
||||||
|
"sub",
|
||||||
|
"summary",
|
||||||
|
"sup",
|
||||||
|
"table",
|
||||||
|
"tbody",
|
||||||
|
"td",
|
||||||
|
"textarea",
|
||||||
|
"tfoot",
|
||||||
|
"th",
|
||||||
|
"thead",
|
||||||
|
"time",
|
||||||
|
"tr",
|
||||||
|
"track",
|
||||||
|
"tt",
|
||||||
|
"u",
|
||||||
|
"ul",
|
||||||
|
"var",
|
||||||
|
"video",
|
||||||
|
"wbr",
|
||||||
|
],
|
||||||
|
// Attributes that HTML tags are allowed to have, extracted from Google Caja.
|
||||||
|
// See https://github.com/jupyterlab/jupyterlab/issues/1812#issuecomment-285848435
|
||||||
|
allowedAttributes: {
|
||||||
|
"*": [
|
||||||
|
"class",
|
||||||
|
"dir",
|
||||||
|
"draggable",
|
||||||
|
"hidden",
|
||||||
|
"id",
|
||||||
|
"inert",
|
||||||
|
"itemprop",
|
||||||
|
"itemref",
|
||||||
|
"itemscope",
|
||||||
|
"lang",
|
||||||
|
"spellcheck",
|
||||||
|
"style",
|
||||||
|
"title",
|
||||||
|
"translate",
|
||||||
|
],
|
||||||
|
// 'rel' and 'target' were *not* allowed by Google Caja
|
||||||
|
a: [
|
||||||
|
"accesskey",
|
||||||
|
"coords",
|
||||||
|
"href",
|
||||||
|
"hreflang",
|
||||||
|
"name",
|
||||||
|
"rel",
|
||||||
|
"shape",
|
||||||
|
"tabindex",
|
||||||
|
"target",
|
||||||
|
"type",
|
||||||
|
],
|
||||||
|
area: [
|
||||||
|
"accesskey",
|
||||||
|
"alt",
|
||||||
|
"coords",
|
||||||
|
"href",
|
||||||
|
"nohref",
|
||||||
|
"shape",
|
||||||
|
"tabindex",
|
||||||
|
],
|
||||||
|
// 'autoplay' was *not* allowed by Google Caja
|
||||||
|
audio: [
|
||||||
|
"autoplay",
|
||||||
|
"controls",
|
||||||
|
"loop",
|
||||||
|
"mediagroup",
|
||||||
|
"muted",
|
||||||
|
"preload",
|
||||||
|
"src",
|
||||||
|
],
|
||||||
|
bdo: ["dir"],
|
||||||
|
blockquote: ["cite"],
|
||||||
|
br: ["clear"],
|
||||||
|
button: [
|
||||||
|
"accesskey",
|
||||||
|
"data-commandlinker-args",
|
||||||
|
"data-commandlinker-command",
|
||||||
|
"disabled",
|
||||||
|
"name",
|
||||||
|
"tabindex",
|
||||||
|
"type",
|
||||||
|
"value",
|
||||||
|
],
|
||||||
|
canvas: ["height", "width"],
|
||||||
|
caption: ["align"],
|
||||||
|
col: ["align", "char", "charoff", "span", "valign", "width"],
|
||||||
|
colgroup: ["align", "char", "charoff", "span", "valign", "width"],
|
||||||
|
command: [
|
||||||
|
"checked",
|
||||||
|
"command",
|
||||||
|
"disabled",
|
||||||
|
"icon",
|
||||||
|
"label",
|
||||||
|
"radiogroup",
|
||||||
|
"type",
|
||||||
|
],
|
||||||
|
data: ["value"],
|
||||||
|
del: ["cite", "datetime"],
|
||||||
|
details: ["open"],
|
||||||
|
dir: ["compact"],
|
||||||
|
div: ["align"],
|
||||||
|
dl: ["compact"],
|
||||||
|
fieldset: ["disabled"],
|
||||||
|
font: ["color", "face", "size"],
|
||||||
|
form: [
|
||||||
|
"accept",
|
||||||
|
"autocomplete",
|
||||||
|
"enctype",
|
||||||
|
"method",
|
||||||
|
"name",
|
||||||
|
"novalidate",
|
||||||
|
],
|
||||||
|
h1: ["align"],
|
||||||
|
h2: ["align"],
|
||||||
|
h3: ["align"],
|
||||||
|
h4: ["align"],
|
||||||
|
h5: ["align"],
|
||||||
|
h6: ["align"],
|
||||||
|
hr: ["align", "noshade", "size", "width"],
|
||||||
|
iframe: [
|
||||||
|
"align",
|
||||||
|
"frameborder",
|
||||||
|
"height",
|
||||||
|
"marginheight",
|
||||||
|
"marginwidth",
|
||||||
|
"width",
|
||||||
|
],
|
||||||
|
img: [
|
||||||
|
"align",
|
||||||
|
"alt",
|
||||||
|
"border",
|
||||||
|
"height",
|
||||||
|
"hspace",
|
||||||
|
"ismap",
|
||||||
|
"name",
|
||||||
|
"src",
|
||||||
|
"usemap",
|
||||||
|
"vspace",
|
||||||
|
"width",
|
||||||
|
],
|
||||||
|
input: [
|
||||||
|
"accept",
|
||||||
|
"accesskey",
|
||||||
|
"align",
|
||||||
|
"alt",
|
||||||
|
"autocomplete",
|
||||||
|
"checked",
|
||||||
|
"disabled",
|
||||||
|
"inputmode",
|
||||||
|
"ismap",
|
||||||
|
"list",
|
||||||
|
"max",
|
||||||
|
"maxlength",
|
||||||
|
"min",
|
||||||
|
"multiple",
|
||||||
|
"name",
|
||||||
|
"placeholder",
|
||||||
|
"readonly",
|
||||||
|
"required",
|
||||||
|
"size",
|
||||||
|
"src",
|
||||||
|
"step",
|
||||||
|
"tabindex",
|
||||||
|
"type",
|
||||||
|
"usemap",
|
||||||
|
"value",
|
||||||
|
],
|
||||||
|
ins: ["cite", "datetime"],
|
||||||
|
label: ["accesskey", "for"],
|
||||||
|
legend: ["accesskey", "align"],
|
||||||
|
li: ["type", "value"],
|
||||||
|
map: ["name"],
|
||||||
|
menu: ["compact", "label", "type"],
|
||||||
|
meter: ["high", "low", "max", "min", "value"],
|
||||||
|
ol: ["compact", "reversed", "start", "type"],
|
||||||
|
optgroup: ["disabled", "label"],
|
||||||
|
option: ["disabled", "label", "selected", "value"],
|
||||||
|
output: ["for", "name"],
|
||||||
|
p: ["align"],
|
||||||
|
pre: ["width"],
|
||||||
|
progress: ["max", "min", "value"],
|
||||||
|
q: ["cite"],
|
||||||
|
select: [
|
||||||
|
"autocomplete",
|
||||||
|
"disabled",
|
||||||
|
"multiple",
|
||||||
|
"name",
|
||||||
|
"required",
|
||||||
|
"size",
|
||||||
|
"tabindex",
|
||||||
|
],
|
||||||
|
source: ["type"],
|
||||||
|
table: [
|
||||||
|
"align",
|
||||||
|
"bgcolor",
|
||||||
|
"border",
|
||||||
|
"cellpadding",
|
||||||
|
"cellspacing",
|
||||||
|
"frame",
|
||||||
|
"rules",
|
||||||
|
"summary",
|
||||||
|
"width",
|
||||||
|
],
|
||||||
|
tbody: ["align", "char", "charoff", "valign"],
|
||||||
|
td: [
|
||||||
|
"abbr",
|
||||||
|
"align",
|
||||||
|
"axis",
|
||||||
|
"bgcolor",
|
||||||
|
"char",
|
||||||
|
"charoff",
|
||||||
|
"colspan",
|
||||||
|
"headers",
|
||||||
|
"height",
|
||||||
|
"nowrap",
|
||||||
|
"rowspan",
|
||||||
|
"scope",
|
||||||
|
"valign",
|
||||||
|
"width",
|
||||||
|
],
|
||||||
|
textarea: [
|
||||||
|
"accesskey",
|
||||||
|
"autocomplete",
|
||||||
|
"cols",
|
||||||
|
"disabled",
|
||||||
|
"inputmode",
|
||||||
|
"name",
|
||||||
|
"placeholder",
|
||||||
|
"readonly",
|
||||||
|
"required",
|
||||||
|
"rows",
|
||||||
|
"tabindex",
|
||||||
|
"wrap",
|
||||||
|
],
|
||||||
|
tfoot: ["align", "char", "charoff", "valign"],
|
||||||
|
th: [
|
||||||
|
"abbr",
|
||||||
|
"align",
|
||||||
|
"axis",
|
||||||
|
"bgcolor",
|
||||||
|
"char",
|
||||||
|
"charoff",
|
||||||
|
"colspan",
|
||||||
|
"headers",
|
||||||
|
"height",
|
||||||
|
"nowrap",
|
||||||
|
"rowspan",
|
||||||
|
"scope",
|
||||||
|
"valign",
|
||||||
|
"width",
|
||||||
|
],
|
||||||
|
thead: ["align", "char", "charoff", "valign"],
|
||||||
|
tr: ["align", "bgcolor", "char", "charoff", "valign"],
|
||||||
|
track: ["default", "kind", "label", "srclang"],
|
||||||
|
ul: ["compact", "type"],
|
||||||
|
video: [
|
||||||
|
"autoplay",
|
||||||
|
"controls",
|
||||||
|
"height",
|
||||||
|
"loop",
|
||||||
|
"mediagroup",
|
||||||
|
"muted",
|
||||||
|
"poster",
|
||||||
|
"preload",
|
||||||
|
"src",
|
||||||
|
"width",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Inline CSS styles that HTML tags may have (and their allowed values)
|
||||||
|
allowedStyles: {
|
||||||
|
// To simplify the data, all styles are allowed on all tags that allow the style attribute
|
||||||
|
"*": {
|
||||||
|
"backface-visibility": [CssProp.BACKFACE_VISIBILITY],
|
||||||
|
background: [CssProp.BACKGROUND],
|
||||||
|
"background-attachment": [CssProp.BACKGROUND_ATTACHMENT],
|
||||||
|
"background-clip": [CssProp.BACKGROUND_CLIP],
|
||||||
|
"background-color": [CssProp.BACKGROUND_COLOR],
|
||||||
|
"background-image": [CssProp.BACKGROUND_IMAGE],
|
||||||
|
"background-origin": [CssProp.BACKGROUND_ORIGIN],
|
||||||
|
"background-position": [CssProp.BACKGROUND_POSITION],
|
||||||
|
"background-repeat": [CssProp.BACKGROUND_REPEAT],
|
||||||
|
"background-size": [CssProp.BACKGROUND_SIZE],
|
||||||
|
border: [CssProp.BORDER],
|
||||||
|
"border-bottom": [CssProp.BORDER_BOTTOM],
|
||||||
|
"border-bottom-color": [CssProp.BORDER_BOTTOM_COLOR],
|
||||||
|
"border-bottom-left-radius": [CssProp.BORDER_BOTTOM_LEFT_RADIUS],
|
||||||
|
"border-bottom-right-radius": [CssProp.BORDER_BOTTOM_RIGHT_RADIUS],
|
||||||
|
"border-bottom-style": [CssProp.BORDER_BOTTOM_STYLE],
|
||||||
|
"border-bottom-width": [CssProp.BORDER_BOTTOM_WIDTH],
|
||||||
|
"border-collapse": [CssProp.BORDER_COLLAPSE],
|
||||||
|
"border-color": [CssProp.BORDER_COLOR],
|
||||||
|
"border-left": [CssProp.BORDER_LEFT],
|
||||||
|
"border-left-color": [CssProp.BORDER_LEFT_COLOR],
|
||||||
|
"border-left-style": [CssProp.BORDER_LEFT_STYLE],
|
||||||
|
"border-left-width": [CssProp.BORDER_LEFT_WIDTH],
|
||||||
|
"border-radius": [CssProp.BORDER_RADIUS],
|
||||||
|
"border-right": [CssProp.BORDER_RIGHT],
|
||||||
|
"border-right-color": [CssProp.BORDER_RIGHT_COLOR],
|
||||||
|
"border-right-style": [CssProp.BORDER_RIGHT_STYLE],
|
||||||
|
"border-right-width": [CssProp.BORDER_RIGHT_WIDTH],
|
||||||
|
"border-spacing": [CssProp.BORDER_SPACING],
|
||||||
|
"border-style": [CssProp.BORDER_STYLE],
|
||||||
|
"border-top": [CssProp.BORDER_TOP],
|
||||||
|
"border-top-color": [CssProp.BORDER_TOP_COLOR],
|
||||||
|
"border-top-left-radius": [CssProp.BORDER_TOP_LEFT_RADIUS],
|
||||||
|
"border-top-right-radius": [CssProp.BORDER_TOP_RIGHT_RADIUS],
|
||||||
|
"border-top-style": [CssProp.BORDER_TOP_STYLE],
|
||||||
|
"border-top-width": [CssProp.BORDER_TOP_WIDTH],
|
||||||
|
"border-width": [CssProp.BORDER_WIDTH],
|
||||||
|
bottom: [CssProp.BOTTOM],
|
||||||
|
box: [CssProp.BOX],
|
||||||
|
"box-shadow": [CssProp.BOX_SHADOW],
|
||||||
|
"box-sizing": [CssProp.BOX_SIZING],
|
||||||
|
"caption-side": [CssProp.CAPTION_SIDE],
|
||||||
|
clear: [CssProp.CLEAR],
|
||||||
|
clip: [CssProp.CLIP],
|
||||||
|
color: [CssProp.COLOR],
|
||||||
|
cursor: [CssProp.CURSOR],
|
||||||
|
direction: [CssProp.DIRECTION],
|
||||||
|
display: [CssProp.DISPLAY],
|
||||||
|
"display-inside": [CssProp.DISPLAY_INSIDE],
|
||||||
|
"display-outside": [CssProp.DISPLAY_OUTSIDE],
|
||||||
|
elevation: [CssProp.ELEVATION],
|
||||||
|
"empty-cells": [CssProp.EMPTY_CELLS],
|
||||||
|
float: [CssProp.FLOAT],
|
||||||
|
font: [CssProp.FONT],
|
||||||
|
"font-family": [CssProp.FONT_FAMILY],
|
||||||
|
"font-size": [CssProp.FONT_SIZE],
|
||||||
|
"font-stretch": [CssProp.FONT_STRETCH],
|
||||||
|
"font-style": [CssProp.FONT_STYLE],
|
||||||
|
"font-variant": [CssProp.FONT_VARIANT],
|
||||||
|
"font-weight": [CssProp.FONT_WEIGHT],
|
||||||
|
height: [CssProp.HEIGHT],
|
||||||
|
left: [CssProp.LEFT],
|
||||||
|
"letter-spacing": [CssProp.LETTER_SPACING],
|
||||||
|
"line-height": [CssProp.LINE_HEIGHT],
|
||||||
|
"list-style": [CssProp.LIST_STYLE],
|
||||||
|
"list-style-image": [CssProp.LIST_STYLE_IMAGE],
|
||||||
|
"list-style-position": [CssProp.LIST_STYLE_POSITION],
|
||||||
|
"list-style-type": [CssProp.LIST_STYLE_TYPE],
|
||||||
|
margin: [CssProp.MARGIN],
|
||||||
|
"margin-bottom": [CssProp.MARGIN_BOTTOM],
|
||||||
|
"margin-left": [CssProp.MARGIN_LEFT],
|
||||||
|
"margin-right": [CssProp.MARGIN_RIGHT],
|
||||||
|
"margin-top": [CssProp.MARGIN_TOP],
|
||||||
|
"max-height": [CssProp.MAX_HEIGHT],
|
||||||
|
"max-width": [CssProp.MAX_WIDTH],
|
||||||
|
"min-height": [CssProp.MIN_HEIGHT],
|
||||||
|
"min-width": [CssProp.MIN_WIDTH],
|
||||||
|
opacity: [CssProp.OPACITY],
|
||||||
|
outline: [CssProp.OUTLINE],
|
||||||
|
"outline-color": [CssProp.OUTLINE_COLOR],
|
||||||
|
"outline-style": [CssProp.OUTLINE_STYLE],
|
||||||
|
"outline-width": [CssProp.OUTLINE_WIDTH],
|
||||||
|
overflow: [CssProp.OVERFLOW],
|
||||||
|
"overflow-wrap": [CssProp.OVERFLOW_WRAP],
|
||||||
|
"overflow-x": [CssProp.OVERFLOW_X],
|
||||||
|
"overflow-y": [CssProp.OVERFLOW_Y],
|
||||||
|
padding: [CssProp.PADDING],
|
||||||
|
"padding-bottom": [CssProp.PADDING_BOTTOM],
|
||||||
|
"padding-left": [CssProp.PADDING_LEFT],
|
||||||
|
"padding-right": [CssProp.PADDING_RIGHT],
|
||||||
|
"padding-top": [CssProp.PADDING_TOP],
|
||||||
|
"page-break-after": [CssProp.PAGE_BREAK_AFTER],
|
||||||
|
"page-break-before": [CssProp.PAGE_BREAK_BEFORE],
|
||||||
|
"page-break-inside": [CssProp.PAGE_BREAK_INSIDE],
|
||||||
|
"pause-after": [CssProp.PAUSE_AFTER],
|
||||||
|
perspective: [CssProp.PERSPECTIVE],
|
||||||
|
pitch: [CssProp.PITCH],
|
||||||
|
"pitch-range": [CssProp.PITCH_RANGE],
|
||||||
|
position: [CssProp.POSITION],
|
||||||
|
quotes: [CssProp.QUOTES],
|
||||||
|
resize: [CssProp.RESIZE],
|
||||||
|
richness: [CssProp.RICHNESS],
|
||||||
|
right: [CssProp.RIGHT],
|
||||||
|
speak: [CssProp.SPEAK],
|
||||||
|
"speak-header": [CssProp.SPEAK_HEADER],
|
||||||
|
"speak-numeral": [CssProp.SPEAK_NUMERAL],
|
||||||
|
"speak-punctuation": [CssProp.SPEAK_PUNCTUATION],
|
||||||
|
"speech-rate": [CssProp.SPEECH_RATE],
|
||||||
|
stress: [CssProp.STRESS],
|
||||||
|
"table-layout": [CssProp.TABLE_LAYOUT],
|
||||||
|
"text-align": [CssProp.TEXT_ALIGN],
|
||||||
|
"text-decoration": [CssProp.TEXT_DECORATION],
|
||||||
|
"text-indent": [CssProp.TEXT_INDENT],
|
||||||
|
"text-overflow": [CssProp.TEXT_OVERFLOW],
|
||||||
|
"text-shadow": [CssProp.TEXT_SHADOW],
|
||||||
|
"text-transform": [CssProp.TEXT_TRANSFORM],
|
||||||
|
"text-wrap": [CssProp.TEXT_WRAP],
|
||||||
|
top: [CssProp.TOP],
|
||||||
|
"unicode-bidi": [CssProp.UNICODE_BIDI],
|
||||||
|
"vertical-align": [CssProp.VERTICAL_ALIGN],
|
||||||
|
visibility: [CssProp.VISIBILITY],
|
||||||
|
volume: [CssProp.VOLUME],
|
||||||
|
"white-space": [CssProp.WHITE_SPACE],
|
||||||
|
width: [CssProp.WIDTH],
|
||||||
|
"word-break": [CssProp.WORD_BREAK],
|
||||||
|
"word-spacing": [CssProp.WORD_SPACING],
|
||||||
|
"word-wrap": [CssProp.WORD_WRAP],
|
||||||
|
"z-index": [CssProp.Z_INDEX],
|
||||||
|
zoom: [CssProp.ZOOM],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transformTags: {
|
||||||
|
// Set the "rel" attribute for <a> tags to "nofollow".
|
||||||
|
a: sanitize.simpleTransform("a", { rel: "nofollow" }),
|
||||||
|
// Set the "disabled" attribute for <input> tags.
|
||||||
|
input: sanitize.simpleTransform("input", { disabled: "disabled" }),
|
||||||
|
},
|
||||||
|
allowedSchemesByTag: {
|
||||||
|
// Allow 'attachment:' img src (used for markdown cell attachments).
|
||||||
|
img: sanitize.defaults.allowedSchemes.concat(["attachment"]),
|
||||||
|
},
|
||||||
|
// Override of the default option, so we can skip 'src' attribute validation.
|
||||||
|
// 'src' Attributes are validated to be URIs, which does not allow for embedded (image) data.
|
||||||
|
// Since embedded data is no longer deemed to be a threat, validation can be skipped.
|
||||||
|
// See https://github.com/jupyterlab/jupyterlab/issues/5183
|
||||||
|
allowedSchemesAppliedToAttributes: ["href", "cite"],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sanitize an HTML string.
|
||||||
|
*
|
||||||
|
* @param dirty - The dirty text.
|
||||||
|
*
|
||||||
|
* @param options - The optional sanitization options.
|
||||||
|
*
|
||||||
|
* @returns The sanitized string.
|
||||||
|
*/
|
||||||
|
sanitize(dirty, options) {
|
||||||
|
return sanitize(dirty, { ...this._options, ...(options || {}) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The default instance of an `ISanitizer` meant for use by user code.
|
||||||
|
*/
|
||||||
|
export const defaultSanitizer = new Sanitizer();
|
||||||
15
utils/notebook/style/base.css
Normal file
15
utils/notebook/style/base.css
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Left-justify the MathJax preview in cell outputs. */
|
||||||
|
.jp-OutputArea-output.jp-RenderedLatex .MathJax_Preview .MJXp-display {
|
||||||
|
padding: var(--jp-code-padding);
|
||||||
|
text-align: left !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left-justify the MathJax display equation in cell outputs. */
|
||||||
|
.jp-OutputArea-output.jp-RenderedLatex .MathJax_Display {
|
||||||
|
text-align: left !important;
|
||||||
|
}
|
||||||
8
utils/notebook/style/index.css
Normal file
8
utils/notebook/style/index.css
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This file was auto-generated by ensurePackage() in @jupyterlab/buildutils */
|
||||||
|
|
||||||
|
@import url('./base.css');
|
||||||
8
utils/notebook/style/index.js
Normal file
8
utils/notebook/style/index.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
| Copyright (c) Jupyter Development Team.
|
||||||
|
| Distributed under the terms of the Modified BSD License.
|
||||||
|
|----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This file was auto-generated by ensurePackage() in @jupyterlab/buildutils */
|
||||||
|
|
||||||
|
import './base.css';
|
||||||
1803
特征工程.ipynb
Normal file
1803
特征工程.ipynb
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user