|
@@ -15,7 +15,7 @@ import { getLastHeadingLevel } from './get_last_heading_level';
|
|
|
import { getMarkdownHeading } from './get_markdown_heading';
|
|
|
import { getRenderedHTMLHeading } from './get_rendered_html_heading';
|
|
|
import { appendHeading } from './append_heading';
|
|
|
-import { appendCollapsibleHeading } from './append_collapsible_heading';
|
|
|
+import { appendMarkdownHeading } from './append_markdown_heading';
|
|
|
import { render } from './render';
|
|
|
import { toolbar } from './toolbar_generator';
|
|
|
|
|
@@ -23,7 +23,7 @@ import { toolbar } from './toolbar_generator';
|
|
|
* Returns a ToC generator for notebooks.
|
|
|
*
|
|
|
* @private
|
|
|
- * @param tracker - file editor tracker
|
|
|
+ * @param tracker - notebook tracker
|
|
|
* @param widget - table of contents widget
|
|
|
* @param sanitizer - HTML sanitizer
|
|
|
* @returns ToC generator capable of parsing notebooks
|
|
@@ -41,183 +41,172 @@ function createNotebookGenerator(
|
|
|
tracker,
|
|
|
usesLatex: true,
|
|
|
options: options,
|
|
|
- toolbarGenerator: () => {
|
|
|
- return toolbar(options, tracker);
|
|
|
- },
|
|
|
- itemRenderer: (item: INotebookHeading) => {
|
|
|
- return render(options, tracker, item);
|
|
|
- },
|
|
|
- generate: panel => {
|
|
|
- let headings: INotebookHeading[] = [];
|
|
|
- let collapseLevel = -1;
|
|
|
- let dict = {};
|
|
|
+ toolbarGenerator: generateToolbar,
|
|
|
+ itemRenderer: renderItem,
|
|
|
+ generate: generate
|
|
|
+ };
|
|
|
|
|
|
- // Initialize a variable for keeping track of the previous heading:
|
|
|
- let prev: INotebookHeading | null = null;
|
|
|
+ /**
|
|
|
+ * Returns a toolbar generator.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @returns toolbar generator
|
|
|
+ */
|
|
|
+ function generateToolbar() {
|
|
|
+ return toolbar(options, tracker);
|
|
|
+ }
|
|
|
|
|
|
- // Generate headings by iterating through all notebook cells...
|
|
|
- for (let i = 0; i < panel.content.widgets.length; i++) {
|
|
|
- let cell: Cell = panel.content.widgets[i];
|
|
|
- let model = cell.model;
|
|
|
+ /**
|
|
|
+ * Renders a table of contents item.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @param item - heading to render
|
|
|
+ * @returns rendered item
|
|
|
+ */
|
|
|
+ function renderItem(item: INotebookHeading) {
|
|
|
+ return render(options, tracker, item);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Generates a table of contents.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @param panel - notebook widget
|
|
|
+ * @returns a list of headings
|
|
|
+ */
|
|
|
+ function generate(panel: NotebookPanel): INotebookHeading[] {
|
|
|
+ let headings: INotebookHeading[] = [];
|
|
|
+ let collapseLevel = -1;
|
|
|
+ let dict = {};
|
|
|
|
|
|
- let collapsed = cell.model.metadata.get('toc-hr-collapsed') as boolean;
|
|
|
- collapsed = collapsed || false;
|
|
|
+ // Initialize a variable for keeping track of the previous heading:
|
|
|
+ let prev: INotebookHeading | null = null;
|
|
|
|
|
|
- if (model.type === 'code') {
|
|
|
- if (!widget || (widget && options.showCode)) {
|
|
|
- const onClick = (line: number) => {
|
|
|
- return () => {
|
|
|
- panel.content.activeCellIndex = i;
|
|
|
- cell.node.scrollIntoView();
|
|
|
- };
|
|
|
- };
|
|
|
- let count = (cell as CodeCell).model.executionCount as
|
|
|
- | number
|
|
|
- | null;
|
|
|
- let executionCount = count !== null ? '[' + count + ']: ' : '[ ]: ';
|
|
|
- let heading = getCodeCellHeading(
|
|
|
- (model as CodeCellModel).value.text,
|
|
|
- onClick,
|
|
|
- executionCount,
|
|
|
- getLastHeadingLevel(headings),
|
|
|
- cell
|
|
|
- );
|
|
|
- [headings, prev] = appendHeading(
|
|
|
- headings,
|
|
|
- heading,
|
|
|
- prev,
|
|
|
- collapseLevel,
|
|
|
- options.filtered
|
|
|
- );
|
|
|
- }
|
|
|
- // Iterate over the code cell outputs to check for Markdown or HTML from which we can generate ToC headings...
|
|
|
- for (let j = 0; j < (model as CodeCellModel).outputs.length; j++) {
|
|
|
- const m = (model as CodeCellModel).outputs.get(j);
|
|
|
+ // Generate headings by iterating through all notebook cells...
|
|
|
+ for (let i = 0; i < panel.content.widgets.length; i++) {
|
|
|
+ let cell: Cell = panel.content.widgets[i];
|
|
|
+ let model = cell.model;
|
|
|
|
|
|
- let dtypes = Object.keys(m.data);
|
|
|
- dtypes = dtypes.filter(t => isMarkdown(t) || isDOM(t));
|
|
|
- if (!dtypes.length) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- const onClick = (el: Element) => {
|
|
|
- return () => {
|
|
|
- panel.content.activeCellIndex = i;
|
|
|
- panel.content.mode = 'command';
|
|
|
- el.scrollIntoView();
|
|
|
- };
|
|
|
+ let collapsed = cell.model.metadata.get('toc-hr-collapsed') as boolean;
|
|
|
+ collapsed = collapsed || false;
|
|
|
+
|
|
|
+ if (model.type === 'code') {
|
|
|
+ if (!widget || (widget && options.showCode)) {
|
|
|
+ const onClick = (line: number) => {
|
|
|
+ return () => {
|
|
|
+ panel.content.activeCellIndex = i;
|
|
|
+ cell.node.scrollIntoView();
|
|
|
};
|
|
|
- let heading = getRenderedHTMLHeading(
|
|
|
- (cell as CodeCell).outputArea.widgets[j].node,
|
|
|
- onClick,
|
|
|
- sanitizer,
|
|
|
- dict,
|
|
|
- getLastHeadingLevel(headings),
|
|
|
- options.numbering,
|
|
|
- cell
|
|
|
- );
|
|
|
- [headings, prev, collapseLevel] = Private.processMD(
|
|
|
- heading,
|
|
|
- options.showMarkdown,
|
|
|
- headings,
|
|
|
- prev,
|
|
|
- collapseLevel,
|
|
|
- options.filtered,
|
|
|
- collapsed
|
|
|
- );
|
|
|
- }
|
|
|
- continue;
|
|
|
+ };
|
|
|
+ let count = (cell as CodeCell).model.executionCount as number | null;
|
|
|
+ let executionCount = count !== null ? '[' + count + ']: ' : '[ ]: ';
|
|
|
+ let heading = getCodeCellHeading(
|
|
|
+ (model as CodeCellModel).value.text,
|
|
|
+ onClick,
|
|
|
+ executionCount,
|
|
|
+ getLastHeadingLevel(headings),
|
|
|
+ cell
|
|
|
+ );
|
|
|
+ [headings, prev] = appendHeading(
|
|
|
+ headings,
|
|
|
+ heading,
|
|
|
+ prev,
|
|
|
+ collapseLevel,
|
|
|
+ options.filtered
|
|
|
+ );
|
|
|
}
|
|
|
- if (model.type === 'markdown') {
|
|
|
- let mcell = cell as MarkdownCell;
|
|
|
- let heading: INotebookHeading | undefined;
|
|
|
- let lastLevel = getLastHeadingLevel(headings);
|
|
|
+ // Iterate over the code cell outputs to check for Markdown or HTML from which we can generate ToC headings...
|
|
|
+ for (let j = 0; j < (model as CodeCellModel).outputs.length; j++) {
|
|
|
+ const m = (model as CodeCellModel).outputs.get(j);
|
|
|
|
|
|
- // If the cell is rendered, generate the ToC items from the HTML...
|
|
|
- if (mcell.rendered && !mcell.inputHidden) {
|
|
|
- const onClick = (el: Element) => {
|
|
|
- return () => {
|
|
|
- if (!mcell.rendered) {
|
|
|
- panel.content.activeCellIndex = i;
|
|
|
- el.scrollIntoView();
|
|
|
- } else {
|
|
|
- panel.content.mode = 'command';
|
|
|
- cell.node.scrollIntoView();
|
|
|
- panel.content.activeCellIndex = i;
|
|
|
- }
|
|
|
- };
|
|
|
- };
|
|
|
- heading = getRenderedHTMLHeading(
|
|
|
- cell.node,
|
|
|
- onClick,
|
|
|
- sanitizer,
|
|
|
- dict,
|
|
|
- lastLevel,
|
|
|
- options.numbering,
|
|
|
- cell
|
|
|
- );
|
|
|
- // If not rendered, generate ToC items from the cell text...
|
|
|
- } else {
|
|
|
- const onClick = (line: number) => {
|
|
|
- return () => {
|
|
|
- panel.content.activeCellIndex = i;
|
|
|
- cell.node.scrollIntoView();
|
|
|
- };
|
|
|
- };
|
|
|
- heading = getMarkdownHeading(
|
|
|
- model!.value.text,
|
|
|
- onClick,
|
|
|
- dict,
|
|
|
- lastLevel,
|
|
|
- cell
|
|
|
- );
|
|
|
+ let dtypes = Object.keys(m.data);
|
|
|
+ dtypes = dtypes.filter(t => isMarkdown(t) || isDOM(t));
|
|
|
+ if (!dtypes.length) {
|
|
|
+ continue;
|
|
|
}
|
|
|
- [headings, prev, collapseLevel] = Private.processMD(
|
|
|
+ const onClick = (el: Element) => {
|
|
|
+ return () => {
|
|
|
+ panel.content.activeCellIndex = i;
|
|
|
+ panel.content.mode = 'command';
|
|
|
+ el.scrollIntoView();
|
|
|
+ };
|
|
|
+ };
|
|
|
+ let heading = getRenderedHTMLHeading(
|
|
|
+ (cell as CodeCell).outputArea.widgets[j].node,
|
|
|
+ onClick,
|
|
|
+ sanitizer,
|
|
|
+ dict,
|
|
|
+ getLastHeadingLevel(headings),
|
|
|
+ options.numbering,
|
|
|
+ cell
|
|
|
+ );
|
|
|
+ [headings, prev, collapseLevel] = appendMarkdownHeading(
|
|
|
heading,
|
|
|
- options.showMarkdown,
|
|
|
headings,
|
|
|
prev,
|
|
|
collapseLevel,
|
|
|
options.filtered,
|
|
|
- collapsed
|
|
|
+ collapsed,
|
|
|
+ options.showMarkdown
|
|
|
);
|
|
|
}
|
|
|
+ continue;
|
|
|
}
|
|
|
- return headings;
|
|
|
- }
|
|
|
- };
|
|
|
-}
|
|
|
+ if (model.type === 'markdown') {
|
|
|
+ let mcell = cell as MarkdownCell;
|
|
|
+ let heading: INotebookHeading | undefined;
|
|
|
+ let lastLevel = getLastHeadingLevel(headings);
|
|
|
|
|
|
-namespace Private {
|
|
|
- export function processMD(
|
|
|
- heading: INotebookHeading | undefined,
|
|
|
- showMarkdown: boolean,
|
|
|
- headings: INotebookHeading[],
|
|
|
- prevHeading: INotebookHeading | null,
|
|
|
- collapseLevel: number,
|
|
|
- filtered: string[],
|
|
|
- collapsed: boolean
|
|
|
- ): [INotebookHeading[], INotebookHeading | null, number] {
|
|
|
- // If the heading is MD and MD is shown, add to headings
|
|
|
- if (heading && heading.type === 'markdown' && showMarkdown) {
|
|
|
- [headings, prevHeading] = appendHeading(
|
|
|
- headings,
|
|
|
- heading,
|
|
|
- prevHeading,
|
|
|
- collapseLevel,
|
|
|
- filtered
|
|
|
- );
|
|
|
- // Otherwise, if the heading is a header, add to headings
|
|
|
- } else if (heading && heading.type === 'header') {
|
|
|
- [headings, prevHeading, collapseLevel] = appendCollapsibleHeading(
|
|
|
- headings,
|
|
|
- heading,
|
|
|
- prevHeading,
|
|
|
- collapseLevel,
|
|
|
- filtered,
|
|
|
- collapsed
|
|
|
- );
|
|
|
+ // If the cell is rendered, generate the ToC items from the HTML...
|
|
|
+ if (mcell.rendered && !mcell.inputHidden) {
|
|
|
+ const onClick = (el: Element) => {
|
|
|
+ return () => {
|
|
|
+ if (!mcell.rendered) {
|
|
|
+ panel.content.activeCellIndex = i;
|
|
|
+ el.scrollIntoView();
|
|
|
+ } else {
|
|
|
+ panel.content.mode = 'command';
|
|
|
+ cell.node.scrollIntoView();
|
|
|
+ panel.content.activeCellIndex = i;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ };
|
|
|
+ heading = getRenderedHTMLHeading(
|
|
|
+ cell.node,
|
|
|
+ onClick,
|
|
|
+ sanitizer,
|
|
|
+ dict,
|
|
|
+ lastLevel,
|
|
|
+ options.numbering,
|
|
|
+ cell
|
|
|
+ );
|
|
|
+ // If not rendered, generate ToC items from the cell text...
|
|
|
+ } else {
|
|
|
+ const onClick = (line: number) => {
|
|
|
+ return () => {
|
|
|
+ panel.content.activeCellIndex = i;
|
|
|
+ cell.node.scrollIntoView();
|
|
|
+ };
|
|
|
+ };
|
|
|
+ heading = getMarkdownHeading(
|
|
|
+ model!.value.text,
|
|
|
+ onClick,
|
|
|
+ dict,
|
|
|
+ lastLevel,
|
|
|
+ cell
|
|
|
+ );
|
|
|
+ }
|
|
|
+ [headings, prev, collapseLevel] = appendMarkdownHeading(
|
|
|
+ heading,
|
|
|
+ headings,
|
|
|
+ prev,
|
|
|
+ collapseLevel,
|
|
|
+ options.filtered,
|
|
|
+ collapsed,
|
|
|
+ options.showMarkdown
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
- return [headings, prevHeading, collapseLevel];
|
|
|
+ return headings;
|
|
|
}
|
|
|
}
|
|
|
|