Browse Source

Removed duplicate/dead code and moved repeated chunks to functions

Markelle Kelly 6 years ago
parent
commit
b98ac468a8
1 changed files with 199 additions and 320 deletions
  1. 199 320
      packages/toc/src/generators/notebookgenerator/index.ts

+ 199 - 320
packages/toc/src/generators/notebookgenerator/index.ts

@@ -7,6 +7,8 @@ import { CodeCell, CodeCellModel, MarkdownCell, Cell } from '@jupyterlab/cells';
 
 import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
 
+//import { IOutputModel } from '@jupyterlab/rendermime';
+
 import { notebookItemRenderer } from './itemrenderer';
 
 import { notebookGeneratorToolbar } from './toolbargenerator';
@@ -57,42 +59,34 @@ export function createNotebookGenerator(
       let headings: INotebookHeading[] = [];
       let numberingDict: { [level: number]: number } = {};
       let currentCollapseLevel = -1;
-
-      // Keep track of the previous heading that is shown in TOC, used for
-      // determine whether one header has child
+      // Keep track of the previous heading, so it can be
+      // marked as having a child if one is discovered
       let prevHeading: INotebookHeading | null = null;
+      // Iterate through the cells in the notebook, generating their headings
       for (let i = 0; i < panel.content.widgets.length; i++) {
         let cell: Cell = panel.content.widgets[i];
-        let collapsed = false;
-        collapsed = cell.model.metadata.get('toc-hr-collapsed') as boolean;
+        let collapsed = cell.model.metadata.get('toc-hr-collapsed') as boolean;
         collapsed = collapsed !== undefined ? collapsed : false;
         let model = cell.model;
         if (model.type === 'code') {
-          // Get the execution count prompt for code cells
-          let executionCountNumber = (cell as CodeCell).model.executionCount as
-            | number
-            | null;
-          let executionCount =
-            executionCountNumber !== null
-              ? '[' + executionCountNumber + ']: '
-              : '[ ]: ';
-          // Iterate over the outputs, and parse them if they
-          // are rendered markdown or HTML.
-          let showCode = true;
-          if (widget) {
-            showCode = options.showCode;
-          }
-          if (showCode) {
+          // Code is shown by default, overridden by previously saved settings
+          if (!widget || (widget && options.showCode)) {
+            // Generate the heading and add to headings if appropriate
+            let executionCountNumber = (cell as CodeCell).model
+              .executionCount as number | null;
+            let executionCount =
+              executionCountNumber !== null
+                ? '[' + executionCountNumber + ']: '
+                : '[ ]: ';
             let text = (model as CodeCellModel).value.text;
             const onClickFactory = (line: number) => {
-              // Activate the corresponding cell if user click on the TOC entry
               return () => {
                 panel.content.activeCellIndex = i;
                 cell.node.scrollIntoView();
               };
             };
             let lastLevel = Private.getLastLevel(headings);
-            let renderedHeadings = Private.getCodeCells(
+            let renderedHeading = Private.getCodeCells(
               text,
               onClickFactory,
               numberingDict,
@@ -100,53 +94,23 @@ export function createNotebookGenerator(
               lastLevel,
               cell
             );
-            if (
-              !Private.headingIsFilteredOut(
-                renderedHeadings[0],
-                options.filtered
-              ) &&
-              prevHeading &&
-              prevHeading.type === 'header' &&
-              text &&
-              options.showCode
-            ) {
-              for (let j = headings.length - 1; j >= 0; j--) {
-                if (headings[j] === prevHeading) {
-                  headings[j].hasChild = true;
-                }
-              }
-            }
-            // Do not render the code cell in TOC if it is filtered out by tags
-            if (
-              currentCollapseLevel < 0 &&
-              !Private.headingIsFilteredOut(
-                renderedHeadings[0],
-                options.filtered
-              )
-            ) {
-              headings = headings.concat(renderedHeadings);
-            }
-
-            // Keep a copy of the TOC entry in prevHeadings
-            if (
-              !Private.headingIsFilteredOut(
-                renderedHeadings[0],
-                options.filtered
-              )
-            ) {
-              prevHeading = renderedHeadings[0];
-            }
+            [headings, prevHeading] = Private.addMDOrCode(
+              headings,
+              renderedHeading,
+              prevHeading,
+              currentCollapseLevel,
+              options.filtered
+            );
           }
+          // Iterate over the code cell outputs to check for MD/HTML
           for (let j = 0; j < (model as CodeCellModel).outputs.length; j++) {
-            // Filter out the outputs that are not rendered HTML
-            // (that is, markdown, vdom, or text/html)
             const outputModel = (model as CodeCellModel).outputs.get(j);
             const dataTypes = Object.keys(outputModel.data);
             const htmlData = dataTypes.filter(t => isMarkdown(t) || isDOM(t));
             if (!htmlData.length) {
               continue;
             }
-            // If the output has rendered HTML, parse it for headers.
+            // Generate the heading
             const outputWidget = (cell as CodeCell).outputArea.widgets[j];
             const onClickFactory = (el: Element) => {
               return () => {
@@ -166,117 +130,39 @@ export function createNotebookGenerator(
               numbering,
               cell
             );
-            if (renderedHeading && renderedHeading.type === 'markdown') {
-              // Do not put the item in TOC if its filtered out by tags
-              if (
-                !Private.headingIsFilteredOut(
-                  renderedHeading,
-                  options.filtered
-                ) &&
-                prevHeading &&
-                prevHeading.type === 'header' &&
-                renderedHeading.text &&
-                options.showMarkdown &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                for (let j = headings.length - 1; j >= 0; j--) {
-                  if (headings[j] === prevHeading) {
-                    headings[j].hasChild = true;
-                  }
-                }
-              }
-              if (
-                currentCollapseLevel < 0 &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                headings.push(renderedHeading);
-              }
-            } else if (renderedHeading && renderedHeading.type === 'header') {
-              // Determine whether the heading has children
-              if (
-                prevHeading &&
-                prevHeading.type === 'header' &&
-                prevHeading.level < renderedHeading.level &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                for (let j = headings.length - 1; j >= 0; j--) {
-                  if (headings[j] === prevHeading) {
-                    headings[j].hasChild = true;
-                  }
-                }
-              }
-              // Do not put the item in TOC if its header is collapsed
-              // or filtered out by tags
-              if (
-                (currentCollapseLevel >= renderedHeading.level ||
-                  currentCollapseLevel < 0) &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                headings.push(renderedHeading);
-                if (collapsed) {
-                  currentCollapseLevel = renderedHeading.level;
-                } else {
-                  currentCollapseLevel = -1;
-                }
-              } else {
-                if (
-                  Private.headingIsFilteredOut(
-                    renderedHeading,
-                    options.filtered
-                  ) &&
-                  prevHeading &&
-                  renderedHeading.level <= prevHeading.level
-                ) {
-                  let k = headings.length - 1;
-                  let parentHeading = false;
-                  while (k >= 0 && parentHeading === false) {
-                    if (headings[k].level < renderedHeading.level) {
-                      prevHeading = headings[k];
-                      parentHeading = true;
-                    }
-                    k--;
-                  }
-                  if (!parentHeading) {
-                    prevHeading = null;
-                    currentCollapseLevel = -1;
-                  } else {
-                    let parentCollapsed = headings[
-                      k + 1
-                    ].cellRef.model.metadata.get('toc-hr-collapsed') as boolean;
-                    parentCollapsed =
-                      parentCollapsed !== undefined ? parentCollapsed : false;
-                    if (parentCollapsed) {
-                      currentCollapseLevel = headings[k + 1].level;
-                    } else {
-                      currentCollapseLevel = -1;
-                    }
-                  }
-                }
-              }
-            }
+            // If the heading is MD and it's appropriate, add to headings
             if (
               renderedHeading &&
-              !Private.headingIsFilteredOut(renderedHeading, options.filtered)
+              renderedHeading.type === 'markdown' &&
+              options.showMarkdown
             ) {
-              if (
-                !(renderedHeading.type === 'markdown') ||
-                options.showMarkdown
-              ) {
-                prevHeading = renderedHeading;
-              }
+              [headings, prevHeading] = Private.addMDOrCode(
+                headings,
+                renderedHeading,
+                prevHeading,
+                currentCollapseLevel,
+                options.filtered
+              );
+            } else if (renderedHeading && renderedHeading.type === 'header') {
+              [headings, prevHeading, currentCollapseLevel] = Private.addHeader(
+                headings,
+                renderedHeading,
+                prevHeading,
+                currentCollapseLevel,
+                options.filtered,
+                collapsed
+              );
             }
           }
         } else if (model.type === 'markdown') {
           // If the cell is rendered, generate the ToC items from
           // the HTML. If it is not rendered, generate them from
           // the text of the cell.
-          if (
-            (cell as MarkdownCell).rendered &&
-            !(cell as MarkdownCell).inputHidden
-          ) {
+          let mdCell = cell as MarkdownCell;
+          if (mdCell.rendered && !mdCell.inputHidden) {
             const onClickFactory = (el: Element) => {
               return () => {
-                if (!(cell as MarkdownCell).rendered) {
+                if (!mdCell.rendered) {
                   panel.content.activeCellIndex = i;
                   el.scrollIntoView();
                 } else {
@@ -298,41 +184,64 @@ export function createNotebookGenerator(
               numbering,
               cell
             );
-            if (renderedHeading && renderedHeading.type === 'markdown') {
-              // Do not put the item in TOC if it's filtered out by tags
-              if (
-                !Private.headingIsFilteredOut(
-                  renderedHeading,
-                  options.filtered
-                ) &&
-                prevHeading &&
-                prevHeading.type === 'header' &&
-                renderedHeading.text &&
-                options.showMarkdown &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                for (let j = headings.length - 1; j >= 0; j--) {
-                  if (headings[j] === prevHeading) {
-                    headings[j].hasChild = true;
-                  }
-                }
-              }
-              if (
-                currentCollapseLevel < 0 &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                headings.push(renderedHeading);
-              }
-            } else if (
-              (renderedHeading && renderedHeading.type === 'header') ||
-              !renderedHeading
+            if (
+              renderedHeading &&
+              renderedHeading.type === 'markdown' &&
+              options.showMarkdown
             ) {
+              [headings, prevHeading] = Private.addMDOrCode(
+                headings,
+                renderedHeading,
+                prevHeading,
+                currentCollapseLevel,
+                options.filtered
+              );
+            } else if (renderedHeading && renderedHeading.type === 'header') {
+              [headings, prevHeading, currentCollapseLevel] = Private.addHeader(
+                headings,
+                renderedHeading,
+                prevHeading,
+                currentCollapseLevel,
+                options.filtered,
+                collapsed
+              );
+            }
+          } else {
+            const onClickFactory = (line: number) => {
+              return () => {
+                panel.content.activeCellIndex = i;
+                cell.node.scrollIntoView();
+              };
+            };
+            let lastLevel = Private.getLastLevel(headings);
+            let renderedHeading: INotebookHeading | null = null;
+            if (cell) {
+              renderedHeading = Private.getMarkdownHeading(
+                model!.value.text,
+                onClickFactory,
+                numberingDict,
+                lastLevel,
+                cell
+              );
+            }
+            if (
+              renderedHeading &&
+              renderedHeading.type === 'markdown' &&
+              options.showMarkdown
+            ) {
+              [headings, prevHeading] = Private.addMDOrCode(
+                headings,
+                renderedHeading,
+                prevHeading,
+                currentCollapseLevel,
+                options.filtered
+              );
+            } else if (renderedHeading && renderedHeading.type === 'header') {
               // Determine whether the heading has children
               if (
                 prevHeading &&
                 prevHeading.type === 'header' &&
-                (renderedHeading &&
-                  prevHeading.level < renderedHeading.level) &&
+                prevHeading.level < renderedHeading.level &&
                 !Private.headingIsFilteredOut(renderedHeading, options.filtered)
               ) {
                 for (let j = headings.length - 1; j >= 0; j--) {
@@ -344,7 +253,6 @@ export function createNotebookGenerator(
               // Do not put the item in TOC if its header is collapsed
               // or filtered out by tags
               if (
-                renderedHeading &&
                 (currentCollapseLevel >= renderedHeading.level ||
                   currentCollapseLevel < 0) &&
                 !Private.headingIsFilteredOut(renderedHeading, options.filtered)
@@ -356,7 +264,6 @@ export function createNotebookGenerator(
                   currentCollapseLevel = -1;
                 }
               } else if (
-                renderedHeading &&
                 Private.headingIsFilteredOut(
                   renderedHeading,
                   options.filtered
@@ -389,123 +296,7 @@ export function createNotebookGenerator(
                   }
                 }
               }
-            }
-            if (
-              renderedHeading &&
-              !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-            ) {
-              if (
-                (renderedHeading && !(renderedHeading.type === 'markdown')) ||
-                options.showMarkdown
-              ) {
-                prevHeading = renderedHeading;
-              }
-            }
-          } else {
-            const onClickFactory = (line: number) => {
-              return () => {
-                panel.content.activeCellIndex = i;
-                cell.node.scrollIntoView();
-              };
-            };
-            let lastLevel = Private.getLastLevel(headings);
-            let renderedHeading: INotebookHeading | null = null;
-            if (cell) {
-              renderedHeading = Private.getMarkdownHeading(
-                model!.value.text,
-                onClickFactory,
-                numberingDict,
-                lastLevel,
-                cell
-              );
-            }
-            if (renderedHeading && renderedHeading.type === 'markdown') {
-              if (
-                prevHeading &&
-                prevHeading.type === 'header' &&
-                prevHeading.level < renderedHeading.level &&
-                options.showMarkdown &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                for (let j = headings.length - 1; j >= 0; j--) {
-                  if (headings[j] === prevHeading) {
-                    headings[j].hasChild = true;
-                  }
-                }
-              }
-              if (
-                renderedHeading &&
-                currentCollapseLevel < 0 &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                headings.push(renderedHeading);
-              }
-            } else if (renderedHeading && renderedHeading.type === 'header') {
-              // Determine whether the heading has children
-              if (
-                prevHeading &&
-                prevHeading.type === 'header' &&
-                prevHeading.level < renderedHeading.level &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                for (let j = headings.length - 1; j >= 0; j--) {
-                  if (headings[j] === prevHeading) {
-                    headings[j].hasChild = true;
-                  }
-                }
-              }
-              // Do not put the item in TOC if its header is collapsed
-              // or filtered out by tags
-              if (
-                renderedHeading &&
-                (currentCollapseLevel >= renderedHeading.level ||
-                  currentCollapseLevel < 0) &&
-                !Private.headingIsFilteredOut(renderedHeading, options.filtered)
-              ) {
-                headings.push(renderedHeading);
-                if (collapsed) {
-                  currentCollapseLevel = renderedHeading.level;
-                } else {
-                  currentCollapseLevel = -1;
-                }
-              } else {
-                if (
-                  renderedHeading &&
-                  Private.headingIsFilteredOut(
-                    renderedHeading,
-                    options.filtered
-                  ) &&
-                  prevHeading &&
-                  renderedHeading.level <= prevHeading.level
-                ) {
-                  let k = headings.length - 1;
-                  let parentHeading = false;
-                  while (k >= 0 && parentHeading === false) {
-                    if (headings[k].level < renderedHeading.level) {
-                      prevHeading = headings[k];
-                      parentHeading = true;
-                    }
-                    k--;
-                  }
-                  if (!parentHeading) {
-                    prevHeading = null;
-                    currentCollapseLevel = -1;
-                  } else {
-                    let parentCollapsed = headings[
-                      k + 1
-                    ].cellRef.model.metadata.get('toc-hr-collapsed') as boolean;
-                    parentCollapsed =
-                      parentCollapsed !== undefined ? parentCollapsed : false;
-                    if (parentCollapsed) {
-                      currentCollapseLevel = headings[k + 1].level;
-                    } else {
-                      currentCollapseLevel = -1;
-                    }
-                  }
-                }
-              }
               if (
-                renderedHeading &&
                 !Private.headingIsFilteredOut(renderedHeading, options.filtered)
               ) {
                 prevHeading = renderedHeading;
@@ -566,6 +357,102 @@ namespace Private {
     return 0;
   }
 
+  export function addMDOrCode(
+    headings: INotebookHeading[],
+    renderedHeading: INotebookHeading,
+    prevHeading: INotebookHeading | null,
+    currentCollapseLevel: number,
+    filtered: string[]
+  ): [INotebookHeading[], INotebookHeading | null] {
+    if (
+      !Private.headingIsFilteredOut(renderedHeading, filtered) &&
+      renderedHeading &&
+      renderedHeading.text
+    ) {
+      // If there is a previous header, find it and mark hasChild true
+      if (prevHeading && prevHeading.type === 'header') {
+        for (let j = headings.length - 1; j >= 0; j--) {
+          if (headings[j] === prevHeading) {
+            headings[j].hasChild = true;
+          }
+        }
+      }
+      if (currentCollapseLevel < 0) {
+        headings.push(renderedHeading);
+      }
+      prevHeading = renderedHeading;
+    }
+    return [headings, prevHeading];
+  }
+
+  export function addHeader(
+    headings: INotebookHeading[],
+    renderedHeading: INotebookHeading,
+    prevHeading: INotebookHeading | null,
+    currentCollapseLevel: number,
+    filtered: string[],
+    collapsed: boolean
+  ): [INotebookHeading[], INotebookHeading | null, number] {
+    let filter = Private.headingIsFilteredOut(renderedHeading, filtered);
+    if (
+      prevHeading &&
+      prevHeading.type === 'header' &&
+      prevHeading.level < renderedHeading.level &&
+      !filter
+    ) {
+      for (let j = headings.length - 1; j >= 0; j--) {
+        if (headings[j] === prevHeading) {
+          headings[j].hasChild = true;
+        }
+      }
+    }
+    if (
+      (currentCollapseLevel >= renderedHeading.level ||
+        currentCollapseLevel < 0) &&
+      !filter
+    ) {
+      headings.push(renderedHeading);
+      if (collapsed) {
+        currentCollapseLevel = renderedHeading.level;
+      } else {
+        currentCollapseLevel = -1;
+      }
+    } else if (
+      filter &&
+      prevHeading &&
+      renderedHeading.level <= prevHeading.level
+    ) {
+      let k = headings.length - 1;
+      let parentHeading = false;
+      while (k >= 0 && parentHeading === false) {
+        if (headings[k].level < renderedHeading.level) {
+          prevHeading = headings[k];
+          parentHeading = true;
+        }
+        k--;
+      }
+      if (!parentHeading) {
+        prevHeading = null;
+        currentCollapseLevel = -1;
+      } else {
+        let parentCollapsed = headings[k + 1].cellRef.model.metadata.get(
+          'toc-hr-collapsed'
+        ) as boolean;
+        parentCollapsed =
+          parentCollapsed !== undefined ? parentCollapsed : false;
+        if (parentCollapsed) {
+          currentCollapseLevel = headings[k + 1].level;
+        } else {
+          currentCollapseLevel = -1;
+        }
+      }
+    }
+    if (!filter) {
+      prevHeading = renderedHeading;
+    }
+    return [headings, prevHeading, currentCollapseLevel];
+  }
+
   /**
    * Given a string of code, get the code entry.
    */
@@ -576,13 +463,11 @@ namespace Private {
     executionCount: string,
     lastLevel: number,
     cellRef: Cell
-  ): INotebookHeading[] {
+  ): INotebookHeading {
     let headings: INotebookHeading[] = [];
     if (text) {
       const lines = text.split('\n');
       let headingText = '';
-
-      // Take at most first 3 lines
       let numLines = Math.min(lines.length, 3);
       for (let i = 0; i < numLines - 1; i++) {
         headingText = headingText + lines[i] + '\n';
@@ -600,12 +485,11 @@ namespace Private {
         hasChild: false
       });
     }
-    return headings;
+    return headings[0];
   }
 
   /**
-   * Given a string of markdown, get the markdown headings
-   * in that string.
+   * Given a string of markdown, get the markdown headings in that string.
    */
   export function getMarkdownHeading(
     text: string,
@@ -614,15 +498,10 @@ namespace Private {
     lastLevel: number,
     cellRef: Cell
   ): INotebookHeading {
-    // Split the text into lines.
     const lines = text.split('\n');
-
-    // Get the first line an check if it is a header.
     const line = lines[0];
     const line2 = lines.length > 1 ? lines[1] : undefined;
-    // Make an onClick handler for this line.
     const onClick = onClickFactory(0);
-
     // First test for '#'-style headers.
     let match = line.match(/^([#]{1,6}) (.*)/);
     let match2 = line2 && line2.match(/^([=]{2,}|[-]{2,})/);