├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── package.json ├── src ├── extension.ts ├── generators │ ├── index.ts │ ├── latexgenerator.ts │ ├── markdowndocgenerator │ │ ├── index.ts │ │ ├── itemrenderer.tsx │ │ ├── optionsmanager.ts │ │ └── toolbargenerator.tsx │ ├── notebookgenerator │ │ ├── codemirror.tsx │ │ ├── heading.ts │ │ ├── index.ts │ │ ├── itemrenderer.tsx │ │ ├── optionsmanager.ts │ │ ├── tagstool │ │ │ ├── index.tsx │ │ │ ├── tag.tsx │ │ │ └── tagslist.tsx │ │ └── toolbargenerator.tsx │ └── shared.ts ├── index.ts ├── registry.ts └── toc.tsx ├── style ├── img │ ├── autonumbering.svg │ ├── autonumbering_darktheme.svg │ ├── check.svg │ ├── code.svg │ ├── code_darktheme.svg │ ├── eyeball_hidden.svg │ ├── eyeball_hover.svg │ ├── eyeball_view.svg │ ├── markdown.svg │ ├── markdown_darktheme.svg │ ├── menu_arrow.svg │ ├── numbering.svg │ ├── tag.svg │ ├── tag_darktheme.svg │ ├── toggle_down.svg │ ├── toggle_down_darktheme.svg │ ├── toggle_right.svg │ └── toggle_right_darktheme.svg ├── index.css ├── list-dark.svg └── list-light.svg ├── toc.gif ├── tsconfig.json ├── tslint.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | *.bundle.* 2 | lib/ 3 | node_modules/ 4 | *.egg-info/ 5 | .ipynb_checkpoints 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/lib 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Project Jupyter Contributors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jupyterlab-toc 2 | 3 | A Table of Contents extension for JupyterLab. 4 | This auto-generates a table of contents in the left area when you have a notebook 5 | or markdown document open. The entries are clickable, and scroll the document 6 | to the heading in question. 7 | 8 | Here is an animation showing the extension's use, with a notebook from the 9 | [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook): 10 | ![Table of Contents](toc.gif 'Table of Contents') 11 | 12 | ## Prerequisites 13 | 14 | - JupyterLab 1.0 15 | 16 | ## Installation 17 | 18 | ```bash 19 | jupyter labextension install @jupyterlab/toc 20 | ``` 21 | 22 | ## Development 23 | 24 | For a development install, do the following in the repository directory: 25 | 26 | ```bash 27 | jlpm install 28 | jlpm run build 29 | jupyter labextension install . 30 | ``` 31 | 32 | You can then run JupyterLab in watch mode to automatically pick up changes to `@jupyterlab/toc`. 33 | Open a terminal in the `@jupyterlab/toc` repository directory and enter 34 | 35 | ```bash 36 | jlpm run watch 37 | ``` 38 | 39 | Then launch JupyterLab using 40 | 41 | ```bash 42 | jupyter lab --watch 43 | ``` 44 | 45 | This will automatically recompile `@jupyterlab/toc` upon changes, 46 | and JupyterLab will rebuild itself. You should then be able to refresh the 47 | page and see your changes. 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jupyterlab/toc", 3 | "version": "1.0.0-pre.1", 4 | "private": false, 5 | "description": "Table of Contents extension for JupyterLab", 6 | "keywords": [ 7 | "jupyter", 8 | "jupyterlab", 9 | "jupyterlab-extension" 10 | ], 11 | "homepage": "https://github.com/jupyterlab/jupyterlab-toc", 12 | "bugs": { 13 | "url": "https://github.com/jupyterlab/jupyterlab-toc/issues" 14 | }, 15 | "license": "BSD-3-Clause", 16 | "author": "Project Jupyter", 17 | "files": [ 18 | "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", 19 | "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}" 20 | ], 21 | "main": "lib/index.js", 22 | "types": "lib/index.d.ts", 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/jupyterlab/jupyterlab-toc.git" 26 | }, 27 | "scripts": { 28 | "build": "tsc", 29 | "clean": "rimraf lib", 30 | "precommit": "lint-staged", 31 | "prettier": "prettier --write '**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}'", 32 | "watch": "tsc -w" 33 | }, 34 | "dependencies": { 35 | "@jupyterlab/application": "^1.0.0-alpha.6", 36 | "@jupyterlab/apputils": "^1.0.0-alpha.6", 37 | "@jupyterlab/cells": "^1.0.0-alpha.6", 38 | "@jupyterlab/coreutils": "3.0.0-alpha.6", 39 | "@jupyterlab/docmanager": "^1.0.0-alpha.6", 40 | "@jupyterlab/docregistry": "^1.0.0-alpha.6", 41 | "@jupyterlab/fileeditor": "^1.0.0-alpha.6", 42 | "@jupyterlab/markdownviewer": "^1.0.0-alpha.6", 43 | "@jupyterlab/notebook": "^1.0.0-alpha.7", 44 | "@jupyterlab/rendermime": "^1.0.0-alpha.6", 45 | "@phosphor/algorithm": "^1.1.2", 46 | "@phosphor/coreutils": "^1.3.0", 47 | "@phosphor/messaging": "^1.2.2", 48 | "@phosphor/widgets": "^1.6.0", 49 | "react": "~16.4.2", 50 | "react-dom": "~16.4.2" 51 | }, 52 | "devDependencies": { 53 | "@types/react": "~16.4.13", 54 | "@types/react-dom": "~16.0.5", 55 | "husky": "^0.14.3", 56 | "lint-staged": "^7.2.0", 57 | "prettier": "^1.13.7", 58 | "rimraf": "^2.6.1", 59 | "tslint": "^5.10.0", 60 | "tslint-config-prettier": "^1.13.0", 61 | "tslint-plugin-prettier": "^1.3.0", 62 | "typescript": "~3.1.1" 63 | }, 64 | "jupyterlab": { 65 | "extension": "lib/extension.js" 66 | }, 67 | "lint-staged": { 68 | "**/*{.ts,.tsx,.css,.json,.md}": [ 69 | "prettier --write", 70 | "git add" 71 | ] 72 | }, 73 | "resolutions": { 74 | "@types/react": "~16.4.13" 75 | }, 76 | "publishConfig": { 77 | "access": "public" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { 5 | ILabShell, 6 | ILayoutRestorer, 7 | JupyterFrontEnd, 8 | JupyterFrontEndPlugin 9 | } from '@jupyterlab/application'; 10 | 11 | import { IDocumentManager } from '@jupyterlab/docmanager'; 12 | 13 | import { IEditorTracker } from '@jupyterlab/fileeditor'; 14 | 15 | import { IMarkdownViewerTracker } from '@jupyterlab/markdownviewer'; 16 | 17 | import { INotebookTracker } from '@jupyterlab/notebook'; 18 | 19 | import { IRenderMimeRegistry } from '@jupyterlab/rendermime'; 20 | 21 | import { TableOfContents } from './toc'; 22 | 23 | import { 24 | createLatexGenerator, 25 | createNotebookGenerator, 26 | createMarkdownGenerator, 27 | createRenderedMarkdownGenerator 28 | } from './generators'; 29 | 30 | import { ITableOfContentsRegistry, TableOfContentsRegistry } from './registry'; 31 | 32 | import '../style/index.css'; 33 | 34 | /** 35 | * Initialization data for the jupyterlab-toc extension. 36 | */ 37 | const extension: JupyterFrontEndPlugin = { 38 | id: 'jupyterlab-toc', 39 | autoStart: true, 40 | provides: ITableOfContentsRegistry, 41 | requires: [ 42 | IDocumentManager, 43 | IEditorTracker, 44 | ILabShell, 45 | ILayoutRestorer, 46 | IMarkdownViewerTracker, 47 | INotebookTracker, 48 | IRenderMimeRegistry 49 | ], 50 | activate: activateTOC 51 | }; 52 | 53 | /** 54 | * Activate the ToC extension. 55 | */ 56 | function activateTOC( 57 | app: JupyterFrontEnd, 58 | docmanager: IDocumentManager, 59 | editorTracker: IEditorTracker, 60 | labShell: ILabShell, 61 | restorer: ILayoutRestorer, 62 | markdownViewerTracker: IMarkdownViewerTracker, 63 | notebookTracker: INotebookTracker, 64 | rendermime: IRenderMimeRegistry 65 | ): ITableOfContentsRegistry { 66 | // Create the ToC widget. 67 | const toc = new TableOfContents({ docmanager, rendermime }); 68 | 69 | // Create the ToC registry. 70 | const registry = new TableOfContentsRegistry(); 71 | 72 | // Add the ToC to the left area. 73 | toc.title.iconClass = 'jp-TableOfContents-icon jp-SideBar-tabIcon'; 74 | toc.title.caption = 'Table of Contents'; 75 | toc.id = 'table-of-contents'; 76 | labShell.add(toc, 'left', { rank: 700 }); 77 | 78 | // Add the ToC widget to the application restorer. 79 | restorer.add(toc, 'juputerlab-toc'); 80 | 81 | // Create a notebook TableOfContentsRegistry.IGenerator 82 | const notebookGenerator = createNotebookGenerator( 83 | notebookTracker, 84 | rendermime.sanitizer, 85 | toc 86 | ); 87 | registry.addGenerator(notebookGenerator); 88 | 89 | // Create an markdown editor TableOfContentsRegistry.IGenerator 90 | const markdownGenerator = createMarkdownGenerator( 91 | editorTracker, 92 | toc, 93 | rendermime.sanitizer 94 | ); 95 | registry.addGenerator(markdownGenerator); 96 | 97 | // Create an rendered markdown editor TableOfContentsRegistry.IGenerator 98 | const renderedMarkdownGenerator = createRenderedMarkdownGenerator( 99 | markdownViewerTracker, 100 | rendermime.sanitizer, 101 | toc 102 | ); 103 | registry.addGenerator(renderedMarkdownGenerator); 104 | 105 | // Create a latex editor TableOfContentsRegistry.IGenerator 106 | const latexGenerator = createLatexGenerator(editorTracker); 107 | registry.addGenerator(latexGenerator); 108 | 109 | // Change the ToC when the active widget changes. 110 | labShell.currentChanged.connect(() => { 111 | let widget = app.shell.currentWidget; 112 | if (!widget) { 113 | return; 114 | } 115 | let generator = registry.findGeneratorForWidget(widget); 116 | if (!generator) { 117 | // If the previously used widget is still available, stick with it. 118 | // Otherwise, set the current TOC widget to null. 119 | if (toc.current && toc.current.widget.isDisposed) { 120 | toc.current = null; 121 | } 122 | return; 123 | } 124 | toc.current = { widget, generator }; 125 | }); 126 | 127 | return registry; 128 | } 129 | export default extension; 130 | -------------------------------------------------------------------------------- /src/generators/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | export * from './markdowndocgenerator'; 5 | export * from './latexgenerator'; 6 | export * from './notebookgenerator'; 7 | -------------------------------------------------------------------------------- /src/generators/latexgenerator.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { IDocumentWidget } from '@jupyterlab/docregistry'; 5 | 6 | import { FileEditor, IEditorTracker } from '@jupyterlab/fileeditor'; 7 | 8 | import { TableOfContentsRegistry } from '../registry'; 9 | 10 | import { IHeading } from '../toc'; 11 | 12 | /** 13 | * Create a TOC generator for LaTeX files. 14 | * 15 | * @param tracker: A file editor tracker. 16 | * 17 | * @returns A TOC generator that can parse LaTeX files. 18 | */ 19 | export function createLatexGenerator( 20 | tracker: IEditorTracker 21 | ): TableOfContentsRegistry.IGenerator> { 22 | return { 23 | tracker, 24 | usesLatex: true, 25 | isEnabled: editor => { 26 | // Only enable this if the editor mimetype matches 27 | // one of a few LaTeX variants. 28 | let mime = editor.content.model.mimeType; 29 | return mime === 'text/x-latex' || mime === 'text/x-stex'; 30 | }, 31 | generate: editor => { 32 | let headings: IHeading[] = []; 33 | let model = editor.content.model; 34 | 35 | // Split the text into lines, with the line number for each. 36 | // We will use the line number to scroll the editor upon 37 | // TOC item click. 38 | const lines = model.value.text.split('\n').map((value, idx) => { 39 | return { value, idx }; 40 | }); 41 | 42 | // Iterate over the lines to get the header level and 43 | // the text for the line. 44 | lines.forEach(line => { 45 | const match = line.value.match( 46 | /^\s*\\(section|subsection|subsubsection){(.+)}/ 47 | ); 48 | if (match) { 49 | const level = Private.latexLevels[match[1]]; 50 | const text = match[2]; 51 | const onClick = () => { 52 | editor.content.editor.setCursorPosition({ 53 | line: line.idx, 54 | column: 0 55 | }); 56 | }; 57 | headings.push({ text, level, onClick }); 58 | } 59 | }); 60 | return headings; 61 | } 62 | }; 63 | } 64 | 65 | /** 66 | * A private namespace for miscellaneous things. 67 | */ 68 | namespace Private { 69 | /** 70 | * A mapping from LaTeX section headers to HTML header 71 | * levels. `part` and `chapter` are less common in my experience, 72 | * so assign them to header level 1. 73 | */ 74 | export const latexLevels: { [label: string]: number } = { 75 | part: 1, // Only available for report and book classes 76 | chapter: 1, // Only available for report and book classes 77 | section: 1, 78 | subsection: 2, 79 | subsubsection: 3, 80 | paragraph: 4, 81 | subparagraph: 5 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /src/generators/markdowndocgenerator/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { ISanitizer } from '@jupyterlab/apputils'; 5 | 6 | import { IDocumentWidget } from '@jupyterlab/docregistry'; 7 | 8 | import { FileEditor, IEditorTracker } from '@jupyterlab/fileeditor'; 9 | 10 | import { 11 | IMarkdownViewerTracker, 12 | MarkdownDocument 13 | } from '@jupyterlab/markdownviewer'; 14 | 15 | import { TableOfContentsRegistry } from '../../registry'; 16 | 17 | import { 18 | generateNumbering, 19 | sanitizerOptions, 20 | isMarkdown, 21 | INumberedHeading 22 | } from '../shared'; 23 | 24 | import { MarkdownDocGeneratorOptionsManager } from './optionsmanager'; 25 | 26 | import { TableOfContents } from '../../toc'; 27 | 28 | import { markdownDocItemRenderer } from './itemrenderer'; 29 | 30 | import { markdownDocGeneratorToolbar } from './toolbargenerator'; 31 | 32 | /** 33 | * Create a TOC generator for markdown files. 34 | * 35 | * @param tracker: A file editor tracker. 36 | * 37 | * @returns A TOC generator that can parse markdown files. 38 | */ 39 | export function createMarkdownGenerator( 40 | tracker: IEditorTracker, 41 | widget: TableOfContents, 42 | sanitizer: ISanitizer 43 | ): TableOfContentsRegistry.IGenerator> { 44 | // Create a option manager to manage user settings 45 | const options = new MarkdownDocGeneratorOptionsManager(widget, { 46 | needsNumbering: true, 47 | sanitizer 48 | }); 49 | return { 50 | tracker, 51 | usesLatex: true, 52 | options: options, 53 | toolbarGenerator: () => { 54 | return markdownDocGeneratorToolbar(options); 55 | }, 56 | itemRenderer: (item: INumberedHeading) => { 57 | return markdownDocItemRenderer(options, item); 58 | }, 59 | isEnabled: editor => { 60 | // Only enable this if the editor mimetype matches 61 | // one of a few markdown variants. 62 | return isMarkdown(editor.content.model.mimeType); 63 | }, 64 | generate: editor => { 65 | let numberingDict: { [level: number]: number } = {}; 66 | let model = editor.content.model; 67 | let onClickFactory = (line: number) => { 68 | return () => { 69 | editor.content.editor.setCursorPosition({ line, column: 0 }); 70 | }; 71 | }; 72 | return Private.getMarkdownDocHeadings( 73 | model.value.text, 74 | onClickFactory, 75 | numberingDict 76 | ); 77 | } 78 | }; 79 | } 80 | 81 | /** 82 | * Create a TOC generator for rendered markdown files. 83 | * 84 | * @param tracker: A file editor tracker. 85 | * 86 | * @returns A TOC generator that can parse markdown files. 87 | */ 88 | export function createRenderedMarkdownGenerator( 89 | tracker: IMarkdownViewerTracker, 90 | sanitizer: ISanitizer, 91 | widget: TableOfContents 92 | ): TableOfContentsRegistry.IGenerator { 93 | const options = new MarkdownDocGeneratorOptionsManager(widget, { 94 | needsNumbering: true, 95 | sanitizer 96 | }); 97 | return { 98 | tracker, 99 | usesLatex: true, 100 | options: options, 101 | toolbarGenerator: () => { 102 | return markdownDocGeneratorToolbar(options); 103 | }, 104 | itemRenderer: (item: INumberedHeading) => { 105 | return markdownDocItemRenderer(options, item); 106 | }, 107 | generate: widget => { 108 | let numberingDict: { [level: number]: number } = {}; 109 | return Private.getRenderedHTMLHeadingsForMarkdownDoc( 110 | widget.content.node, 111 | sanitizer, 112 | numberingDict, 113 | options.numbering 114 | ); 115 | } 116 | }; 117 | } 118 | 119 | /** 120 | * A private namespace for miscellaneous things. 121 | */ 122 | namespace Private { 123 | export function getMarkdownDocHeadings( 124 | text: string, 125 | onClickFactory: (line: number) => (() => void), 126 | numberingDict: { [level: number]: number } 127 | ): INumberedHeading[] { 128 | // Split the text into lines. 129 | const lines = text.split('\n'); 130 | let headings: INumberedHeading[] = []; 131 | 132 | let inCodeBlock = false; 133 | // Iterate over the lines to get the header level and 134 | // the text for the line. 135 | lines.forEach((line, idx) => { 136 | // Don't check for markdown headings if we 137 | // are in a code block (demarcated by backticks). 138 | if (line.indexOf('```') === 0) { 139 | inCodeBlock = !inCodeBlock; 140 | } 141 | if (inCodeBlock) { 142 | return; 143 | } 144 | // Make an onClick handler for this line. 145 | const onClick = onClickFactory(idx); 146 | 147 | // First test for '#'-style headers. 148 | let match = line.match(/^([#]{1,6}) (.*)/); 149 | if (match) { 150 | const level = match[1].length; 151 | // Take special care to parse markdown links into raw text. 152 | const text = match[2].replace(/\[(.+)\]\(.+\)/g, '$1'); 153 | let numbering = generateNumbering(numberingDict, level); 154 | headings.push({ 155 | text, 156 | numbering, 157 | level, 158 | onClick 159 | }); 160 | return; 161 | } 162 | 163 | // Next test for '==='-style headers. 164 | match = line.match(/^([=]{2,}|[-]{2,})/); 165 | if (match && idx > 0) { 166 | const level = match[1][0] === '=' ? 1 : 2; 167 | const prev = lines[idx - 1]; 168 | // If the previous line is already a '#'-style heading, 169 | // then this is not a '===' style heading. 170 | const prevMatch = prev.match(/^([#]{1,6}) (.*)/); 171 | if (prevMatch) { 172 | return; 173 | } 174 | // Take special care to parse markdown links into raw text. 175 | const text = prev.replace(/\[(.+)\]\(.+\)/g, '$1'); 176 | let numbering = generateNumbering(numberingDict, level); 177 | headings.push({ 178 | text, 179 | numbering, 180 | level, 181 | onClick 182 | }); 183 | return; 184 | } 185 | 186 | // Finally test for HTML headers. This will not catch multiline 187 | // headers, nor will it catch multiple headers on the same line. 188 | // It should do a decent job of catching many, though. 189 | match = line.match(/(.*)<\/h\1>/i); 190 | if (match) { 191 | const level = parseInt(match[1], 10); 192 | const text = match[2]; 193 | let numbering = generateNumbering(numberingDict, level); 194 | headings.push({ 195 | text, 196 | numbering, 197 | level, 198 | onClick 199 | }); 200 | return; 201 | } 202 | }); 203 | return headings; 204 | } 205 | 206 | /** 207 | * Given a HTML DOM element, get the markdown headings 208 | * in that string. 209 | */ 210 | export function getRenderedHTMLHeadingsForMarkdownDoc( 211 | node: HTMLElement, 212 | sanitizer: ISanitizer, 213 | numberingDict: { [level: number]: number }, 214 | needsNumbering = true 215 | ): INumberedHeading[] { 216 | let headings: INumberedHeading[] = []; 217 | let headingNodes = node.querySelectorAll('h1, h2, h3, h4, h5, h6'); 218 | for (let i = 0; i < headingNodes.length; i++) { 219 | const heading = headingNodes[i]; 220 | const level = parseInt(heading.tagName[1], 10); 221 | let text = heading.textContent ? heading.textContent : ''; 222 | let shallHide = !needsNumbering; 223 | 224 | // Show/hide numbering DOM element based on user settings 225 | if (heading.getElementsByClassName('numbering-entry').length > 0) { 226 | heading.removeChild( 227 | heading.getElementsByClassName('numbering-entry')[0] 228 | ); 229 | } 230 | let html = sanitizer.sanitize(heading.innerHTML, sanitizerOptions); 231 | html = html.replace('¶', ''); // Remove the anchor symbol. 232 | const onClick = () => { 233 | heading.scrollIntoView(); 234 | }; 235 | 236 | // Get the numbering string 237 | let numbering = generateNumbering(numberingDict, level); 238 | 239 | // Generate the DOM element for numbering 240 | let numDOM = ''; 241 | if (!shallHide) { 242 | numDOM = '' + numbering + ''; 243 | } 244 | 245 | // Add DOM numbering element to document 246 | heading.innerHTML = numDOM + html; 247 | 248 | text = text.replace('¶', ''); 249 | headings.push({ 250 | level, 251 | text, 252 | numbering, 253 | html, 254 | onClick 255 | }); 256 | } 257 | return headings; 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/generators/markdowndocgenerator/itemrenderer.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { MarkdownDocGeneratorOptionsManager } from './optionsmanager'; 5 | 6 | import { INumberedHeading, sanitizerOptions } from '../shared'; 7 | 8 | import * as React from 'react'; 9 | 10 | export function markdownDocItemRenderer( 11 | options: MarkdownDocGeneratorOptionsManager, 12 | item: INumberedHeading 13 | ) { 14 | let fontSizeClass = 'toc-level-size-default'; 15 | 16 | // Render numbering if needed 17 | let numbering = item.numbering && options.numbering ? item.numbering : ''; 18 | fontSizeClass = 'toc-level-size-' + item.level; 19 | let jsx; 20 | if (item.html) { 21 | jsx = ( 22 | 29 | ); 30 | } else { 31 | jsx = {numbering + item.text}; 32 | } 33 | return jsx; 34 | } 35 | -------------------------------------------------------------------------------- /src/generators/markdowndocgenerator/optionsmanager.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { ISanitizer } from '@jupyterlab/apputils'; 5 | 6 | import { TableOfContentsRegistry } from '../../registry'; 7 | 8 | import { TableOfContents } from '../../toc'; 9 | 10 | export class MarkdownDocGeneratorOptionsManager extends TableOfContentsRegistry.IGeneratorOptionsManager { 11 | constructor( 12 | widget: TableOfContents, 13 | options: { needsNumbering: boolean; sanitizer: ISanitizer } 14 | ) { 15 | super(); 16 | this._numbering = options.needsNumbering; 17 | this._widget = widget; 18 | this.sanitizer = options.sanitizer; 19 | } 20 | 21 | readonly sanitizer: ISanitizer; 22 | 23 | set numbering(value: boolean) { 24 | this._numbering = value; 25 | this._widget.update(); 26 | } 27 | 28 | get numbering() { 29 | return this._numbering; 30 | } 31 | 32 | // initialize options, will NOT change notebook metadata 33 | initializeOptions(numbering: boolean) { 34 | this._numbering = numbering; 35 | this._widget.update(); 36 | } 37 | 38 | private _numbering: boolean; 39 | private _widget: TableOfContents; 40 | } 41 | -------------------------------------------------------------------------------- /src/generators/markdowndocgenerator/toolbargenerator.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { MarkdownDocGeneratorOptionsManager } from './optionsmanager'; 5 | 6 | import * as React from 'react'; 7 | 8 | interface INotebookGeneratorToolbarProps {} 9 | 10 | interface INotebookGeneratorToolbarState { 11 | numbering: boolean; 12 | } 13 | 14 | export function markdownDocGeneratorToolbar( 15 | options: MarkdownDocGeneratorOptionsManager 16 | ) { 17 | // Render the toolbar 18 | return class extends React.Component< 19 | INotebookGeneratorToolbarProps, 20 | INotebookGeneratorToolbarState 21 | > { 22 | constructor(props: INotebookGeneratorToolbarProps) { 23 | super(props); 24 | this.state = { numbering: false }; 25 | options.initializeOptions(false); 26 | } 27 | 28 | render() { 29 | const toggleAutoNumbering = () => { 30 | options.numbering = !options.numbering; 31 | this.setState({ numbering: options.numbering }); 32 | }; 33 | let numberingIcon = this.state.numbering ? ( 34 |
toggleAutoNumbering()} 37 | > 38 |
44 |
45 | ) : ( 46 |
toggleAutoNumbering()} 49 | > 50 |
56 |
57 | ); 58 | 59 | return ( 60 |
61 |
{numberingIcon}
62 |
63 | ); 64 | } 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/codemirror.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import * as React from 'react'; 5 | 6 | import { ISanitizer } from '@jupyterlab/apputils'; 7 | 8 | import { INotebookHeading } from './heading'; 9 | 10 | import { sanitizerOptions } from '../shared'; 11 | 12 | export interface ICodeComponentProps { 13 | sanitizer: ISanitizer; 14 | heading: INotebookHeading; 15 | } 16 | 17 | export interface ICodeComponentState { 18 | heading: INotebookHeading; 19 | } 20 | 21 | export class CodeComponent extends React.Component< 22 | ICodeComponentProps, 23 | ICodeComponentState 24 | > { 25 | constructor(props: ICodeComponentProps) { 26 | super(props); 27 | this.state = { heading: props.heading }; 28 | } 29 | 30 | componentWillReceiveProps(nextProps: ICodeComponentProps) { 31 | this.setState({ heading: nextProps.heading }); 32 | } 33 | 34 | render() { 35 | // Grab the rendered CodeMirror DOM in the document, show it in TOC. 36 | let html = this.state.heading.cellRef!.editor.host.innerHTML; 37 | // Sanitize it to be safe. 38 | html = this.props.sanitizer.sanitize(html, sanitizerOptions); 39 | return ( 40 |
41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/heading.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { Cell } from '@jupyterlab/cells'; 5 | 6 | import { INumberedHeading } from '../shared'; 7 | 8 | /** 9 | * A heading for a notebook cell. 10 | */ 11 | export interface INotebookHeading extends INumberedHeading { 12 | type: 'header' | 'markdown' | 'code'; 13 | prompt?: string; 14 | cellRef: Cell; 15 | hasChild?: boolean; 16 | } 17 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { ISanitizer } from '@jupyterlab/apputils'; 5 | 6 | import { CodeCell, CodeCellModel, MarkdownCell, Cell } from '@jupyterlab/cells'; 7 | 8 | import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook'; 9 | 10 | import { notebookItemRenderer } from './itemrenderer'; 11 | 12 | import { notebookGeneratorToolbar } from './toolbargenerator'; 13 | 14 | import { TableOfContentsRegistry } from '../../registry'; 15 | 16 | import { TableOfContents } from '../../toc'; 17 | 18 | import { NotebookGeneratorOptionsManager } from './optionsmanager'; 19 | 20 | import { INotebookHeading } from './heading'; 21 | 22 | import { 23 | generateNumbering, 24 | isDOM, 25 | isMarkdown, 26 | sanitizerOptions 27 | } from '../shared'; 28 | 29 | /** 30 | * Create a TOC generator for notebooks. 31 | * 32 | * @param tracker: A notebook tracker. 33 | * 34 | * @returns A TOC generator that can parse notebooks. 35 | */ 36 | export function createNotebookGenerator( 37 | tracker: INotebookTracker, 38 | sanitizer: ISanitizer, 39 | widget: TableOfContents 40 | ): TableOfContentsRegistry.IGenerator { 41 | // Create a option manager to manage user settings 42 | const options = new NotebookGeneratorOptionsManager(widget, tracker, { 43 | needsNumbering: false, 44 | sanitizer: sanitizer 45 | }); 46 | return { 47 | tracker, 48 | usesLatex: true, 49 | options: options, 50 | toolbarGenerator: () => { 51 | return notebookGeneratorToolbar(options, tracker); 52 | }, 53 | itemRenderer: (item: INotebookHeading) => { 54 | return notebookItemRenderer(options, item); 55 | }, 56 | generate: panel => { 57 | let headings: INotebookHeading[] = []; 58 | let numberingDict: { [level: number]: number } = {}; 59 | let collapseLevel = -1; 60 | // Keep track of the previous heading, so it can be 61 | // marked as having a child if one is discovered 62 | let prevHeading: INotebookHeading | null = null; 63 | // Iterate through the cells in the notebook, generating their headings 64 | for (let i = 0; i < panel.content.widgets.length; i++) { 65 | let cell: Cell = panel.content.widgets[i]; 66 | let collapsed = cell.model.metadata.get('toc-hr-collapsed') as boolean; 67 | collapsed = collapsed !== undefined ? collapsed : false; 68 | let model = cell.model; 69 | if (model.type === 'code') { 70 | // Code is shown by default, overridden by previously saved settings 71 | if (!widget || (widget && options.showCode)) { 72 | // Generate the heading and add to headings if appropriate 73 | let executionCountNumber = (cell as CodeCell).model 74 | .executionCount as number | null; 75 | let executionCount = 76 | executionCountNumber !== null 77 | ? '[' + executionCountNumber + ']: ' 78 | : '[ ]: '; 79 | let text = (model as CodeCellModel).value.text; 80 | const onClickFactory = (line: number) => { 81 | return () => { 82 | panel.content.activeCellIndex = i; 83 | cell.node.scrollIntoView(); 84 | }; 85 | }; 86 | let lastLevel = Private.getLastLevel(headings); 87 | let renderedHeading = Private.getCodeCells( 88 | text, 89 | onClickFactory, 90 | executionCount, 91 | lastLevel, 92 | cell 93 | ); 94 | [headings, prevHeading] = Private.addMDOrCode( 95 | headings, 96 | renderedHeading, 97 | prevHeading, 98 | collapseLevel, 99 | options.filtered 100 | ); 101 | } 102 | // Iterate over the code cell outputs to check for MD/HTML 103 | for (let j = 0; j < (model as CodeCellModel).outputs.length; j++) { 104 | const outputModel = (model as CodeCellModel).outputs.get(j); 105 | const dataTypes = Object.keys(outputModel.data); 106 | const htmlData = dataTypes.filter(t => isMarkdown(t) || isDOM(t)); 107 | if (!htmlData.length) { 108 | continue; 109 | } 110 | // If MD/HTML generate the heading and add to headings if applicable 111 | const outputWidget = (cell as CodeCell).outputArea.widgets[j]; 112 | const onClickFactory = (el: Element) => { 113 | return () => { 114 | panel.content.activeCellIndex = i; 115 | panel.content.mode = 'command'; 116 | el.scrollIntoView(); 117 | }; 118 | }; 119 | let lastLevel = Private.getLastLevel(headings); 120 | let numbering = options.numbering; 121 | let renderedHeading = Private.getRenderedHTMLHeading( 122 | outputWidget.node, 123 | onClickFactory, 124 | sanitizer, 125 | numberingDict, 126 | lastLevel, 127 | numbering, 128 | cell 129 | ); 130 | [headings, prevHeading, collapseLevel] = Private.processMD( 131 | renderedHeading, 132 | options.showMarkdown, 133 | headings, 134 | prevHeading, 135 | collapseLevel, 136 | options.filtered, 137 | collapsed 138 | ); 139 | } 140 | } else if (model.type === 'markdown') { 141 | let mdCell = cell as MarkdownCell; 142 | let renderedHeading: INotebookHeading | undefined = undefined; 143 | let lastLevel = Private.getLastLevel(headings); 144 | // If the cell is rendered, generate the ToC items from the HTML 145 | if (mdCell.rendered && !mdCell.inputHidden) { 146 | const onClickFactory = (el: Element) => { 147 | return () => { 148 | if (!mdCell.rendered) { 149 | panel.content.activeCellIndex = i; 150 | el.scrollIntoView(); 151 | } else { 152 | panel.content.mode = 'command'; 153 | cell.node.scrollIntoView(); 154 | panel.content.activeCellIndex = i; 155 | } 156 | }; 157 | }; 158 | renderedHeading = Private.getRenderedHTMLHeading( 159 | cell.node, 160 | onClickFactory, 161 | sanitizer, 162 | numberingDict, 163 | lastLevel, 164 | options.numbering, 165 | cell 166 | ); 167 | // If not rendered, generate ToC items from the text of the cell 168 | } else { 169 | const onClickFactory = (line: number) => { 170 | return () => { 171 | panel.content.activeCellIndex = i; 172 | cell.node.scrollIntoView(); 173 | }; 174 | }; 175 | renderedHeading = Private.getMarkdownHeading( 176 | model!.value.text, 177 | onClickFactory, 178 | numberingDict, 179 | lastLevel, 180 | cell 181 | ); 182 | } 183 | // Add to headings if applicable 184 | [headings, prevHeading, collapseLevel] = Private.processMD( 185 | renderedHeading, 186 | options.showMarkdown, 187 | headings, 188 | prevHeading, 189 | collapseLevel, 190 | options.filtered, 191 | collapsed 192 | ); 193 | } 194 | } 195 | return headings; 196 | } 197 | }; 198 | } 199 | 200 | namespace Private { 201 | /** 202 | * Determine whether a heading is filtered out by selected tags. 203 | */ 204 | export function headingIsFilteredOut( 205 | heading: INotebookHeading, 206 | tags: string[] 207 | ) { 208 | if (tags.length === 0) { 209 | return false; 210 | } 211 | if (heading && heading.cellRef) { 212 | let cellMetadata = heading.cellRef.model.metadata; 213 | let cellTagsData = cellMetadata.get('tags') as string[]; 214 | if (cellTagsData) { 215 | for (let j = 0; j < cellTagsData.length; j++) { 216 | let name = cellTagsData[j]; 217 | for (let k = 0; k < tags.length; k++) { 218 | if (tags[k] === name) { 219 | return false; 220 | } 221 | } 222 | } 223 | } 224 | } 225 | return true; 226 | } 227 | 228 | export function getLastLevel(headings: INotebookHeading[]) { 229 | if (headings.length > 0) { 230 | let location = headings.length - 1; 231 | while (location >= 0) { 232 | if (headings[location].type === 'header') { 233 | return headings[location].level; 234 | } 235 | location = location - 1; 236 | } 237 | } 238 | return 0; 239 | } 240 | 241 | export function processMD( 242 | renderedHeading: INotebookHeading | undefined, 243 | showMarkdown: boolean, 244 | headings: INotebookHeading[], 245 | prevHeading: INotebookHeading | null, 246 | collapseLevel: number, 247 | filtered: string[], 248 | collapsed: boolean 249 | ): [INotebookHeading[], INotebookHeading | null, number] { 250 | // If the heading is MD and MD is shown, add to headings 251 | if ( 252 | renderedHeading && 253 | renderedHeading.type === 'markdown' && 254 | showMarkdown 255 | ) { 256 | [headings, prevHeading] = Private.addMDOrCode( 257 | headings, 258 | renderedHeading, 259 | prevHeading, 260 | collapseLevel, 261 | filtered 262 | ); 263 | // Otherwise, if the heading is a header, add to headings 264 | } else if (renderedHeading && renderedHeading.type === 'header') { 265 | [headings, prevHeading, collapseLevel] = Private.addHeader( 266 | headings, 267 | renderedHeading, 268 | prevHeading, 269 | collapseLevel, 270 | filtered, 271 | collapsed 272 | ); 273 | } 274 | return [headings, prevHeading, collapseLevel]; 275 | } 276 | 277 | export function addMDOrCode( 278 | headings: INotebookHeading[], 279 | renderedHeading: INotebookHeading, 280 | prevHeading: INotebookHeading | null, 281 | collapseLevel: number, 282 | filtered: string[] 283 | ): [INotebookHeading[], INotebookHeading | null] { 284 | if ( 285 | !Private.headingIsFilteredOut(renderedHeading, filtered) && 286 | renderedHeading && 287 | renderedHeading.text 288 | ) { 289 | // If there is a previous header, find it and mark hasChild true 290 | if (prevHeading && prevHeading.type === 'header') { 291 | for (let j = headings.length - 1; j >= 0; j--) { 292 | if (headings[j] === prevHeading) { 293 | headings[j].hasChild = true; 294 | } 295 | } 296 | } 297 | if (collapseLevel < 0) { 298 | headings.push(renderedHeading); 299 | } 300 | prevHeading = renderedHeading; 301 | } 302 | return [headings, prevHeading]; 303 | } 304 | 305 | export function addHeader( 306 | headings: INotebookHeading[], 307 | renderedHeading: INotebookHeading, 308 | prevHeading: INotebookHeading | null, 309 | collapseLevel: number, 310 | filtered: string[], 311 | collapsed: boolean 312 | ): [INotebookHeading[], INotebookHeading | null, number] { 313 | if (!Private.headingIsFilteredOut(renderedHeading, filtered)) { 314 | // if the previous heading is a header of a higher level, 315 | // find it and mark it as having a child 316 | if ( 317 | prevHeading && 318 | prevHeading.type === 'header' && 319 | prevHeading.level < renderedHeading.level 320 | ) { 321 | for (let j = headings.length - 1; j >= 0; j--) { 322 | if (headings[j] === prevHeading) { 323 | headings[j].hasChild = true; 324 | } 325 | } 326 | } 327 | // if the collapse level doesn't include the header, or if there is no 328 | // collapsing, add to headings and adjust the collapse level appropriately 329 | if (collapseLevel >= renderedHeading.level || collapseLevel < 0) { 330 | headings.push(renderedHeading); 331 | collapseLevel = collapsed ? renderedHeading.level : -1; 332 | } 333 | prevHeading = renderedHeading; 334 | } else if (prevHeading && renderedHeading.level <= prevHeading.level) { 335 | // If header is filtered out and has a previous heading of smaller level, go 336 | // back through headings to determine if it has a parent 337 | let k = headings.length - 1; 338 | let parentHeading = false; 339 | while (k >= 0 && parentHeading === false) { 340 | if (headings[k].level < renderedHeading.level) { 341 | prevHeading = headings[k]; 342 | parentHeading = true; 343 | } 344 | k--; 345 | } 346 | // If there is no parent, set prevHeading to null and reset collapsing 347 | if (!parentHeading) { 348 | prevHeading = null; 349 | collapseLevel = -1; 350 | // Otherwise, reset collapsing appropriately 351 | } else { 352 | let parentState = headings[k + 1].cellRef.model.metadata.get( 353 | 'toc-hr-collapsed' 354 | ) as boolean; 355 | parentState = parentState !== undefined ? parentState : false; 356 | collapseLevel = parentState ? headings[k + 1].level : -1; 357 | } 358 | } 359 | return [headings, prevHeading, collapseLevel]; 360 | } 361 | 362 | /** 363 | * Given a string of code, get the code entry. 364 | */ 365 | export function getCodeCells( 366 | text: string, 367 | onClickFactory: (line: number) => (() => void), 368 | executionCount: string, 369 | lastLevel: number, 370 | cellRef: Cell 371 | ): INotebookHeading { 372 | let headings: INotebookHeading[] = []; 373 | if (text) { 374 | const lines = text.split('\n'); 375 | let headingText = ''; 376 | let numLines = Math.min(lines.length, 3); 377 | for (let i = 0; i < numLines - 1; i++) { 378 | headingText = headingText + lines[i] + '\n'; 379 | } 380 | headingText = headingText + lines[numLines - 1]; 381 | const onClick = onClickFactory(0); 382 | const level = lastLevel + 1; 383 | headings.push({ 384 | text: headingText, 385 | level, 386 | onClick, 387 | type: 'code', 388 | prompt: executionCount, 389 | cellRef: cellRef, 390 | hasChild: false 391 | }); 392 | } 393 | return headings[0]; 394 | } 395 | 396 | /** 397 | * Given a string of markdown, get the markdown headings in that string. 398 | */ 399 | export function getMarkdownHeading( 400 | text: string, 401 | onClickFactory: (line: number) => (() => void), 402 | numberingDict: any, 403 | lastLevel: number, 404 | cellRef: Cell 405 | ): INotebookHeading { 406 | const lines = text.split('\n'); 407 | const line = lines[0]; 408 | const line2 = lines.length > 1 ? lines[1] : undefined; 409 | const onClick = onClickFactory(0); 410 | // First test for '#'-style headers. 411 | let match = line.match(/^([#]{1,6}) (.*)/); 412 | let match2 = line2 && line2.match(/^([=]{2,}|[-]{2,})/); 413 | let match3 = line.match(/(.*)<\/h\1>/i); 414 | if (match) { 415 | const level = match[1].length; 416 | // Take special care to parse markdown links into raw text. 417 | const text = match[2].replace(/\[(.+)\]\(.+\)/g, '$1'); 418 | let numbering = generateNumbering(numberingDict, level); 419 | return { 420 | text, 421 | level, 422 | numbering, 423 | onClick, 424 | type: 'header', 425 | cellRef: cellRef, 426 | hasChild: false 427 | }; 428 | } else if (match2) { 429 | // Next test for '==='-style headers. 430 | const level = match2[1][0] === '=' ? 1 : 2; 431 | // Take special care to parse markdown links into raw text. 432 | const text = line.replace(/\[(.+)\]\(.+\)/g, '$1'); 433 | let numbering = generateNumbering(numberingDict, level); 434 | return { 435 | text, 436 | level, 437 | numbering, 438 | onClick, 439 | type: 'header', 440 | cellRef: cellRef, 441 | hasChild: false 442 | }; 443 | } else if (match3) { 444 | // Finally test for HTML headers. This will not catch multiline 445 | // headers, nor will it catch multiple headers on the same line. 446 | // It should do a decent job of catching many, though. 447 | const level = parseInt(match3[1], 10); 448 | const text = match3[2]; 449 | let numbering = generateNumbering(numberingDict, level); 450 | return { 451 | text, 452 | level, 453 | numbering, 454 | onClick, 455 | type: 'header', 456 | cellRef: cellRef, 457 | hasChild: false 458 | }; 459 | } else { 460 | return { 461 | text: line, 462 | level: lastLevel + 1, 463 | onClick, 464 | type: 'markdown', 465 | cellRef: cellRef, 466 | hasChild: false 467 | }; 468 | } 469 | } 470 | 471 | /** 472 | * Given an HTML element, generate ToC headings 473 | * by finding all the headers and making IHeading objects for them. 474 | */ 475 | export function getRenderedHTMLHeading( 476 | node: HTMLElement, 477 | onClickFactory: (el: Element) => (() => void), 478 | sanitizer: ISanitizer, 479 | numberingDict: { [level: number]: number }, 480 | lastLevel: number, 481 | needsNumbering = false, 482 | cellRef: Cell 483 | ): INotebookHeading | undefined { 484 | let headingNodes = node.querySelectorAll('h1, h2, h3, h4, h5, h6, p'); 485 | if (headingNodes.length > 0) { 486 | let markdownCell = headingNodes[0]; 487 | if (markdownCell.nodeName.toLowerCase() === 'p') { 488 | if (markdownCell.innerHTML) { 489 | let html = sanitizer.sanitize( 490 | markdownCell.innerHTML, 491 | sanitizerOptions 492 | ); 493 | html = html.replace('¶', ''); 494 | return { 495 | level: lastLevel + 1, 496 | html: html, 497 | text: markdownCell.textContent ? markdownCell.textContent : '', 498 | onClick: onClickFactory(markdownCell), 499 | type: 'markdown', 500 | cellRef: cellRef, 501 | hasChild: false 502 | }; 503 | } 504 | } else { 505 | const heading = headingNodes[0]; 506 | const level = parseInt(heading.tagName[1], 10); 507 | const text = heading.textContent ? heading.textContent : ''; 508 | let shallHide = !needsNumbering; 509 | if (heading.getElementsByClassName('numbering-entry').length > 0) { 510 | heading.removeChild( 511 | heading.getElementsByClassName('numbering-entry')[0] 512 | ); 513 | } 514 | let html = sanitizer.sanitize(heading.innerHTML, sanitizerOptions); 515 | html = html.replace('¶', ''); 516 | const onClick = onClickFactory(heading); 517 | let numbering = generateNumbering(numberingDict, level); 518 | let numDOM = ''; 519 | if (!shallHide) { 520 | numDOM = '' + numbering + ''; 521 | } 522 | heading.innerHTML = numDOM + html; 523 | return { 524 | level, 525 | text, 526 | numbering, 527 | html, 528 | onClick, 529 | type: 'header', 530 | cellRef: cellRef, 531 | hasChild: false 532 | }; 533 | } 534 | } 535 | return undefined; 536 | } 537 | } 538 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/itemrenderer.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { CodeComponent } from './codemirror'; 5 | 6 | import { Cell } from '@jupyterlab/cells'; 7 | 8 | import { NotebookGeneratorOptionsManager } from './optionsmanager'; 9 | 10 | import { INotebookHeading } from './heading'; 11 | 12 | import { sanitizerOptions } from '../shared'; 13 | 14 | import * as React from 'react'; 15 | 16 | export function notebookItemRenderer( 17 | options: NotebookGeneratorOptionsManager, 18 | item: INotebookHeading 19 | ) { 20 | let jsx; 21 | if (item.type === 'markdown' || item.type === 'header') { 22 | const collapseOnClick = (cellRef?: Cell) => { 23 | let collapsed = cellRef!.model.metadata.get( 24 | 'toc-hr-collapsed' 25 | ) as boolean; 26 | collapsed = collapsed != undefined ? collapsed : false; 27 | cellRef!.model.metadata.set('toc-hr-collapsed', !collapsed); 28 | options.updateWidget(); 29 | }; 30 | let fontSizeClass = 'toc-level-size-default'; 31 | let numbering = item.numbering && options.numbering ? item.numbering : ''; 32 | if (item.type === 'header') { 33 | fontSizeClass = 'toc-level-size-' + item.level; 34 | } 35 | if (item.html && (item.type === 'header' || options.showMarkdown)) { 36 | jsx = ( 37 | 45 | ); 46 | // Render the headers 47 | if (item.type === 'header') { 48 | let collapsed = item.cellRef!.model.metadata.get( 49 | 'toc-hr-collapsed' 50 | ) as boolean; 51 | collapsed = collapsed != undefined ? collapsed : false; 52 | 53 | // Render the twist button 54 | let twistButton = ( 55 |
{ 58 | event.stopPropagation(); 59 | collapseOnClick(item.cellRef); 60 | }} 61 | > 62 |
placeholder
63 |
64 |
65 | ); 66 | if (collapsed) { 67 | twistButton = ( 68 |
{ 71 | event.stopPropagation(); 72 | collapseOnClick(item.cellRef); 73 | }} 74 | > 75 |
placeholder
76 |
77 |
78 | ); 79 | } 80 | // Render the header item 81 | jsx = ( 82 |
83 | {item.hasChild && twistButton} 84 | {jsx} 85 |
86 | ); 87 | } 88 | } else if (item.type === 'header' || options.showMarkdown) { 89 | // Render headers/markdown for plain text 90 | jsx = ( 91 | 92 | {numbering + item.text} 93 | 94 | ); 95 | if (item.type === 'header') { 96 | let collapsed = item.cellRef!.model.metadata.get( 97 | 'toc-hr-collapsed' 98 | ) as boolean; 99 | collapsed = collapsed != undefined ? collapsed : false; 100 | let twistButton = ( 101 |
{ 104 | event.stopPropagation(); 105 | collapseOnClick(item.cellRef); 106 | }} 107 | > 108 |
placeholder
109 |
110 |
111 | ); 112 | if (collapsed) { 113 | twistButton = ( 114 |
{ 117 | event.stopPropagation(); 118 | collapseOnClick(item.cellRef); 119 | }} 120 | > 121 |
placeholder
122 |
123 |
124 | ); 125 | } 126 | jsx = ( 127 |
128 | {item.hasChild && twistButton} 129 | {jsx} 130 |
131 | ); 132 | } 133 | } else { 134 | jsx = null; 135 | } 136 | } else if (item.type === 'code' && options.showCode) { 137 | // Render code cells 138 | jsx = ( 139 |
140 |
{item.prompt}
141 | 142 | 143 | 144 |
145 | ); 146 | } else { 147 | jsx = null; 148 | } 149 | return jsx; 150 | } 151 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/optionsmanager.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { ISanitizer } from '@jupyterlab/apputils'; 5 | 6 | import { INotebookTracker } from '@jupyterlab/notebook'; 7 | 8 | import { TableOfContentsRegistry } from '../../registry'; 9 | 10 | import { TableOfContents } from '../../toc'; 11 | 12 | import { TagsToolComponent } from './tagstool'; 13 | 14 | export class NotebookGeneratorOptionsManager extends TableOfContentsRegistry.IGeneratorOptionsManager { 15 | constructor( 16 | widget: TableOfContents, 17 | notebook: INotebookTracker, 18 | options: { 19 | needsNumbering: boolean; 20 | sanitizer: ISanitizer; 21 | tagTool?: TagsToolComponent; 22 | } 23 | ) { 24 | super(); 25 | this._numbering = options.needsNumbering; 26 | this._widget = widget; 27 | this._notebook = notebook; 28 | this.sanitizer = options.sanitizer; 29 | this.tagTool = null; 30 | this.storeTags = []; 31 | } 32 | 33 | readonly sanitizer: ISanitizer; 34 | public tagTool?: TagsToolComponent | null; 35 | 36 | set notebookMetadata(value: [string, any]) { 37 | if (this._notebook.currentWidget != null) { 38 | this._notebook.currentWidget.model.metadata.set(value[0], value[1]); 39 | } 40 | } 41 | 42 | set numbering(value: boolean) { 43 | this._numbering = value; 44 | this._widget.update(); 45 | this.notebookMetadata = ['toc-autonumbering', this._numbering]; 46 | } 47 | 48 | get numbering() { 49 | return this._numbering; 50 | } 51 | 52 | set showCode(value: boolean) { 53 | this._showCode = value; 54 | this.notebookMetadata = ['toc-showcode', this._showCode]; 55 | this._widget.update(); 56 | } 57 | 58 | get showCode() { 59 | return this._showCode; 60 | } 61 | 62 | set showMarkdown(value: boolean) { 63 | this._showMarkdown = value; 64 | this.notebookMetadata = ['toc-showmarkdowntxt', this._showMarkdown]; 65 | this._widget.update(); 66 | } 67 | 68 | get showMarkdown() { 69 | return this._showMarkdown; 70 | } 71 | 72 | set showTags(value: boolean) { 73 | this._showTags = value; 74 | this.notebookMetadata = ['toc-showtags', this._showTags]; 75 | this._widget.update(); 76 | } 77 | 78 | get showTags() { 79 | return this._showTags; 80 | } 81 | 82 | get filtered() { 83 | if (this.tagTool) { 84 | this._filtered = this.tagTool.getFiltered(); 85 | } else if (this.storeTags.length > 0) { 86 | this._filtered = this.storeTags; 87 | } else { 88 | this._filtered = []; 89 | } 90 | return this._filtered; 91 | } 92 | 93 | set preRenderedToolbar(value: any) { 94 | this._preRenderedToolbar = value; 95 | } 96 | 97 | get preRenderedToolbar() { 98 | return this._preRenderedToolbar; 99 | } 100 | 101 | updateWidget() { 102 | this._widget.update(); 103 | } 104 | 105 | setTagTool(tagTool: TagsToolComponent | null) { 106 | this.tagTool = tagTool; 107 | } 108 | 109 | // initialize options, will NOT change notebook metadata 110 | initializeOptions( 111 | numbering: boolean, 112 | showCode: boolean, 113 | showMarkdown: boolean, 114 | showTags: boolean 115 | ) { 116 | this._numbering = numbering; 117 | this._showCode = showCode; 118 | this._showMarkdown = showMarkdown; 119 | this._showTags = showTags; 120 | this._widget.update(); 121 | } 122 | 123 | private _preRenderedToolbar: any = null; 124 | private _filtered: string[] = []; 125 | private _numbering: boolean; 126 | private _showCode = false; 127 | private _showMarkdown = false; 128 | private _showTags = false; 129 | private _notebook: INotebookTracker; 130 | private _widget: TableOfContents; 131 | public storeTags: string[]; 132 | } 133 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/tagstool/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { INotebookTracker } from '@jupyterlab/notebook'; 5 | import { Cell } from '@jupyterlab/cells'; 6 | import { TagListComponent } from './tagslist'; 7 | import * as React from 'react'; 8 | import { NotebookGeneratorOptionsManager } from '../optionsmanager'; 9 | 10 | export interface ITagsToolComponentProps { 11 | allTagsList: string[]; 12 | tracker: INotebookTracker; 13 | generatorOptionsRef: NotebookGeneratorOptionsManager; 14 | inputFilter: string[]; 15 | } 16 | 17 | export interface ITagsToolComponentState { 18 | selected: string[]; 19 | } 20 | 21 | /* 22 | * Create a React component that handles state for the tag dropdown 23 | */ 24 | export class TagsToolComponent extends React.Component< 25 | ITagsToolComponentProps, 26 | ITagsToolComponentState 27 | > { 28 | constructor(props: ITagsToolComponentProps) { 29 | super(props); 30 | this.state = { 31 | selected: this.props.inputFilter 32 | }; 33 | } 34 | 35 | /* 36 | * Manage the selection state of the dropdown, taking in the name of a tag and 37 | * whether to add or remove it. 38 | */ 39 | changeSelectionState = (newState: string, add: boolean) => { 40 | if (add) { 41 | let selectedTags = this.state.selected; 42 | selectedTags.push(newState); 43 | this.setState({ selected: selectedTags }); 44 | this.filterTags(selectedTags); 45 | } else { 46 | let selectedTags = this.state.selected; 47 | let newSelectedTags: string[] = []; 48 | for (let i = 0; i < selectedTags.length; i++) { 49 | if (selectedTags[i] !== newState) { 50 | newSelectedTags.push(selectedTags[i]); 51 | } 52 | } 53 | if (newSelectedTags.length === 0) { 54 | newSelectedTags = []; 55 | } 56 | this.setState({ selected: newSelectedTags }); 57 | this.filterTags(newSelectedTags); 58 | } 59 | }; 60 | 61 | public getFiltered() { 62 | return this.state.selected; 63 | } 64 | 65 | /* 66 | * Deselect all tags in the dropdown and clear filters in the TOC. 67 | */ 68 | deselectAllTags = () => { 69 | this.setState({ selected: [] }); 70 | this.props.generatorOptionsRef.updateWidget(); 71 | }; 72 | 73 | /** 74 | * Check whether a cell is tagged with a certain string 75 | */ 76 | containsTag(tag: string, cell: Cell) { 77 | if (cell === null) { 78 | return false; 79 | } 80 | let tagList = cell.model.metadata.get('tags') as string[]; 81 | if (tagList) { 82 | for (let i = 0; i < tagList.length; i++) { 83 | if (tagList[i] === tag) { 84 | return true; 85 | } 86 | } 87 | return false; 88 | } 89 | } 90 | 91 | /* 92 | * Tells the generator to filter the TOC by the selected tags. 93 | */ 94 | filterTags = (selected: string[]) => { 95 | this.setState({ selected }); 96 | this.props.generatorOptionsRef.updateWidget(); 97 | }; 98 | 99 | updateFilters = () => { 100 | let temp: string[] = []; 101 | let idx = 0; 102 | let needsUpdate = false; 103 | for (let i = 0; i < this.state.selected.length; i++) { 104 | if ( 105 | this.props.allTagsList.indexOf(this.state.selected[i] as string) > -1 106 | ) { 107 | temp[idx] = this.state.selected[i]; 108 | idx++; 109 | } else if (this.props.generatorOptionsRef.showTags === true) { 110 | needsUpdate = true; 111 | } 112 | } 113 | if (needsUpdate) { 114 | this.filterTags(temp); 115 | this.setState({ selected: temp }); 116 | } 117 | }; 118 | 119 | componentWillUpdate() { 120 | this.updateFilters(); 121 | } 122 | 123 | /* 124 | * Render the interior of the tag dropdown. 125 | */ 126 | render() { 127 | let renderedJSX =
No Tags Available
; 128 | let filterText; 129 | if (this.state.selected.length === 0) { 130 | filterText = ( 131 | Clear Filters 132 | ); 133 | } else if (this.state.selected.length === 1) { 134 | filterText = ( 135 | this.deselectAllTags()} 138 | > 139 | {' '} 140 | Clear 1 Filter{' '} 141 | 142 | ); 143 | } else { 144 | filterText = ( 145 | this.deselectAllTags()} 148 | > 149 | {' '} 150 | Clear {this.state.selected.length} Filters{' '} 151 | 152 | ); 153 | } 154 | if (this.props.allTagsList && this.props.allTagsList.length > 0) { 155 | renderedJSX = ( 156 |
157 | 162 | {filterText} 163 |
164 | ); 165 | } 166 | return renderedJSX; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/tagstool/tag.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import * as React from 'react'; 5 | 6 | export interface ITagComponentProps { 7 | selectionStateHandler: (newState: string, add: boolean) => void; 8 | selectedTags: string[]; 9 | tag: string; 10 | } 11 | 12 | /* 13 | * Create a React component containing one tag label 14 | */ 15 | export abstract class TagComponent extends React.Component { 16 | constructor(props: ITagComponentProps) { 17 | super(props); 18 | } 19 | 20 | render() { 21 | const tag = this.props.tag as string; 22 | return ( 23 |
24 | 27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/tagstool/tagslist.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { TagComponent } from './tag'; 5 | 6 | import * as React from 'react'; 7 | 8 | /* 9 | * The TagList takes a list of selected tags, a handler to change selection state, 10 | * and a list of all tags (strings). 11 | */ 12 | export interface ITagListComponentProps { 13 | selectedTags: string[]; 14 | selectionStateHandler: (newState: string, add: boolean) => void; 15 | allTagsList: string[] | null; 16 | } 17 | 18 | /* 19 | * The TagList state contains a list of selected tags 20 | */ 21 | export interface ITagListComponentState { 22 | selected: string[]; 23 | } 24 | 25 | /* 26 | * Create a React component that renders all tags in a list. 27 | */ 28 | export class TagListComponent extends React.Component< 29 | ITagListComponentProps, 30 | ITagListComponentState 31 | > { 32 | constructor(props: ITagListComponentProps) { 33 | super(props); 34 | this.state = { selected: this.props.selectedTags }; 35 | } 36 | 37 | /* 38 | * Toggle whether a tag is selected when it is clicked 39 | */ 40 | selectedTagWithName = (name: string) => { 41 | if (this.props.selectedTags.indexOf(name) >= 0) { 42 | this.props.selectionStateHandler(name, false); 43 | } else { 44 | this.props.selectionStateHandler(name, true); 45 | } 46 | }; 47 | 48 | /* 49 | * Render a tag, putting it in a TagComponent 50 | */ 51 | renderElementForTags = (tags: string[]) => { 52 | const selectedTags = this.props.selectedTags; 53 | const _self = this; 54 | return tags.map((tag, index) => { 55 | const tagClass = 56 | selectedTags.indexOf(tag) >= 0 57 | ? 'toc-selected-tag toc-tag' 58 | : 'toc-unselected-tag toc-tag'; 59 | return ( 60 |
{ 64 | _self.selectedTagWithName(tag); 65 | }} 66 | tabIndex={-1} 67 | > 68 | 73 |
74 | ); 75 | }); 76 | }; 77 | 78 | /* 79 | * Render the list of tags in the TOC tags dropdown. 80 | */ 81 | render() { 82 | let allTagsList = this.props.allTagsList; 83 | let renderedTagsForAllCells = null; 84 | if (allTagsList) { 85 | renderedTagsForAllCells = this.renderElementForTags(allTagsList); 86 | } 87 | return
{renderedTagsForAllCells}
; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/generators/notebookgenerator/toolbargenerator.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { INotebookTracker } from '@jupyterlab/notebook'; 5 | 6 | import { JSONValue } from '@phosphor/coreutils'; 7 | 8 | import { NotebookGeneratorOptionsManager } from './optionsmanager'; 9 | 10 | import * as React from 'react'; 11 | 12 | import { TagsToolComponent } from './tagstool'; 13 | 14 | interface INotebookGeneratorToolbarProps {} 15 | 16 | interface INotebookGeneratorToolbarState { 17 | showCode: boolean; 18 | showMarkdown: boolean; 19 | showTags: boolean; 20 | numbering: boolean; 21 | } 22 | 23 | export function notebookGeneratorToolbar( 24 | options: NotebookGeneratorOptionsManager, 25 | tracker: INotebookTracker 26 | ) { 27 | // Render the toolbar 28 | return class extends React.Component< 29 | INotebookGeneratorToolbarProps, 30 | INotebookGeneratorToolbarState 31 | > { 32 | constructor(props: INotebookGeneratorToolbarProps) { 33 | super(props); 34 | this.tagTool = null; 35 | this.state = { 36 | showCode: true, 37 | showMarkdown: false, 38 | showTags: false, 39 | numbering: false 40 | }; 41 | if (tracker.currentWidget) { 42 | // Read saved user settings in notebook metadata 43 | tracker.currentWidget.context.ready.then(() => { 44 | if (tracker.currentWidget) { 45 | tracker.currentWidget.content.activeCellChanged.connect(() => { 46 | options.updateWidget(); 47 | }); 48 | let _numbering = tracker.currentWidget.model.metadata.get( 49 | 'toc-autonumbering' 50 | ) as boolean; 51 | let numbering = 52 | _numbering != undefined ? _numbering : options.numbering; 53 | let _showCode = tracker.currentWidget.model.metadata.get( 54 | 'toc-showcode' 55 | ) as boolean; 56 | let showCode = 57 | _showCode != undefined ? _showCode : options.showCode; 58 | let _showMarkdown = tracker.currentWidget.model.metadata.get( 59 | 'toc-showmarkdowntxt' 60 | ) as boolean; 61 | let showMarkdown = 62 | _showMarkdown != undefined ? _showMarkdown : options.showMarkdown; 63 | let _showTags = tracker.currentWidget.model.metadata.get( 64 | 'toc-showtags' 65 | ) as boolean; 66 | let showTags = 67 | _showTags != undefined ? _showTags : options.showTags; 68 | this.allTags = []; 69 | options.initializeOptions( 70 | numbering, 71 | showCode, 72 | showMarkdown, 73 | showTags 74 | ); 75 | this.setState({ 76 | showCode: options.showCode, 77 | showMarkdown: options.showMarkdown, 78 | showTags: options.showTags, 79 | numbering: options.numbering 80 | }); 81 | } 82 | }); 83 | } 84 | } 85 | 86 | toggleCode = (component: React.Component) => { 87 | options.showCode = !options.showCode; 88 | this.setState({ showCode: options.showCode }); 89 | }; 90 | 91 | toggleMarkdown = (component: React.Component) => { 92 | options.showMarkdown = !options.showMarkdown; 93 | this.setState({ showMarkdown: options.showMarkdown }); 94 | }; 95 | 96 | toggleAutoNumbering = () => { 97 | options.numbering = !options.numbering; 98 | this.setState({ numbering: options.numbering }); 99 | }; 100 | 101 | toggleTagDropdown = () => { 102 | if (options.showTags && this.tagTool) { 103 | options.storeTags = this.tagTool.state.selected; 104 | } 105 | options.showTags = !options.showTags; 106 | this.setState({ showTags: options.showTags }); 107 | }; 108 | 109 | // Load all tags in the document 110 | getTags = () => { 111 | let notebook = tracker.currentWidget; 112 | if (notebook) { 113 | const cells = notebook.model.cells; 114 | const tagSet = new Set(); 115 | this.allTags = []; 116 | for (let i = 0; i < cells.length; i++) { 117 | const cell = cells.get(i)!; 118 | const tagData = cell.metadata.get('tags') as JSONValue; 119 | if (Array.isArray(tagData)) { 120 | tagData.forEach((tag: string) => tag && tagSet.add(tag)); 121 | } 122 | } 123 | this.allTags = Array.from(tagSet); 124 | } 125 | }; 126 | 127 | render() { 128 | let codeIcon = this.state.showCode ? ( 129 |
this.toggleCode.bind(this)()} 132 | > 133 |
139 |
140 | ) : ( 141 |
this.toggleCode.bind(this)()} 144 | > 145 |
151 |
152 | ); 153 | 154 | let markdownIcon = this.state.showMarkdown ? ( 155 |
this.toggleMarkdown.bind(this)()} 158 | > 159 |
165 |
166 | ) : ( 167 |
this.toggleMarkdown.bind(this)()} 170 | > 171 |
177 |
178 | ); 179 | 180 | let numberingIcon = this.state.numbering ? ( 181 |
this.toggleAutoNumbering()} 184 | > 185 |
191 |
192 | ) : ( 193 |
this.toggleAutoNumbering()} 196 | > 197 |
203 |
204 | ); 205 | 206 | let tagDropdown =
; 207 | let tagIcon = ( 208 |
209 |
215 |
216 | ); 217 | if (this.state.showTags) { 218 | this.getTags(); 219 | let tagTool = ( 220 | (this.tagTool = tagTool)} 226 | /> 227 | ); 228 | options.setTagTool(this.tagTool); 229 | tagDropdown =
{tagTool}
; 230 | tagIcon = ( 231 |
237 | ); 238 | } 239 | 240 | return ( 241 |
242 |
243 | {codeIcon} 244 | {markdownIcon} 245 | {numberingIcon} 246 |
this.toggleTagDropdown()} 249 | > 250 | {tagIcon} 251 |
252 |
253 | {tagDropdown} 254 |
255 | ); 256 | } 257 | 258 | allTags: string[]; 259 | tagTool: TagsToolComponent | null; 260 | }; 261 | } 262 | -------------------------------------------------------------------------------- /src/generators/shared.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { IHeading } from '../toc'; 5 | 6 | const VDOM_MIME_TYPE = 'application/vdom.v1+json'; 7 | 8 | const HTML_MIME_TYPE = 'text/html'; 9 | 10 | export interface INumberedHeading extends IHeading { 11 | numbering?: string | null; 12 | } 13 | 14 | /** 15 | * Given a dictionary that keep tracks of the numbering and the level, 16 | * update the dictionary. 17 | */ 18 | function incrementNumberingDict(dict: any, level: number) { 19 | let x = level + 1; 20 | while (x <= 6) { 21 | if (dict[x] != undefined) { 22 | dict[x] = undefined; 23 | } 24 | x++; 25 | } 26 | if (dict[level] === undefined) { 27 | dict[level] = 1; 28 | } else { 29 | dict[level]++; 30 | } 31 | } 32 | 33 | /** 34 | * Given a dictionary that keep tracks of the numbering and the current level, 35 | * generate the current numbering based on the dictionary and current level. 36 | */ 37 | export function generateNumbering( 38 | numberingDict: { [level: number]: number }, 39 | level: number 40 | ) { 41 | let numbering = undefined; 42 | if (numberingDict != null) { 43 | incrementNumberingDict(numberingDict, level); 44 | numbering = ''; 45 | for (let j = 1; j <= level; j++) { 46 | numbering += 47 | (numberingDict[j] == undefined ? '0' : numberingDict[j]) + '.'; 48 | if (j === level) { 49 | numbering += ' '; 50 | } 51 | } 52 | } 53 | return numbering; 54 | } 55 | 56 | /** 57 | * Return whether the mime type is some flavor of markdown. 58 | */ 59 | export function isMarkdown(mime: string): boolean { 60 | return ( 61 | mime === 'text/x-ipythongfm' || 62 | mime === 'text/x-markdown' || 63 | mime === 'text/x-gfm' || 64 | mime === 'text/markdown' 65 | ); 66 | } 67 | 68 | /** 69 | * Return whether the mime type is DOM-ish (html or vdom). 70 | */ 71 | export function isDOM(mime: string): boolean { 72 | return mime === VDOM_MIME_TYPE || mime === HTML_MIME_TYPE; 73 | } 74 | 75 | /** 76 | * Allowed HTML tags for the ToC entries. We use this to 77 | * sanitize HTML headings, if they are given. We specifically 78 | * disallow anchor tags, since we are adding our own. 79 | */ 80 | export const sanitizerOptions = { 81 | allowedTags: [ 82 | 'p', 83 | 'blockquote', 84 | 'b', 85 | 'i', 86 | 'strong', 87 | 'em', 88 | 'strike', 89 | 'code', 90 | 'br', 91 | 'div', 92 | 'span', 93 | 'pre', 94 | 'del' 95 | ], 96 | allowedAttributes: { 97 | // Allow "class" attribute for tags. 98 | code: ['class'], 99 | // Allow "class" attribute for tags. 100 | span: ['class'], 101 | // Allow "class" attribute for
tags. 102 | div: ['class'], 103 | // Allow "class" attribute for

tags. 104 | p: ['class'], 105 | // Allow "class" attribute for

 tags.
106 |     pre: ['class']
107 |   }
108 | };
109 | 


--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) Jupyter Development Team.
2 | // Distributed under the terms of the Modified BSD License.
3 | 
4 | export * from './toc';
5 | export * from './registry';
6 | export * from './generators';
7 | 


--------------------------------------------------------------------------------
/src/registry.ts:
--------------------------------------------------------------------------------
  1 | // Copyright (c) Jupyter Development Team.
  2 | // Distributed under the terms of the Modified BSD License.
  3 | 
  4 | import { IInstanceTracker } from '@jupyterlab/apputils';
  5 | 
  6 | import { Token } from '@phosphor/coreutils';
  7 | 
  8 | import { Widget } from '@phosphor/widgets';
  9 | 
 10 | import { IHeading } from './toc';
 11 | 
 12 | /**
 13 |  * An interface for a TableOfContentsRegistry.
 14 |  */
 15 | export interface ITableOfContentsRegistry extends TableOfContentsRegistry {}
 16 | 
 17 | /* tslint:disable */
 18 | /**
 19 |  * The TableOfContentsRegistry token.
 20 |  */
 21 | export const ITableOfContentsRegistry = new Token(
 22 |   'jupyterlab-toc:ITableOfContentsRegistry'
 23 | );
 24 | /* tslint:enable */
 25 | 
 26 | /**
 27 |  * A class that keeps track of the different kinds
 28 |  * of widgets for which there can be tables-of-contents.
 29 |  */
 30 | export class TableOfContentsRegistry {
 31 |   /**
 32 |    * Given a widget, find an IGenerator for it,
 33 |    * or undefined if none can be found.
 34 |    */
 35 |   findGeneratorForWidget(
 36 |     widget: Widget
 37 |   ): TableOfContentsRegistry.IGenerator | undefined {
 38 |     let generator: TableOfContentsRegistry.IGenerator | undefined;
 39 |     this._generators.forEach(gen => {
 40 |       if (gen.tracker.has(widget)) {
 41 |         // If isEnabled is present, check for it.
 42 |         if (gen.isEnabled && !gen.isEnabled(widget)) {
 43 |           return;
 44 |         }
 45 |         generator = gen;
 46 |       }
 47 |     });
 48 |     return generator;
 49 |   }
 50 | 
 51 |   /**
 52 |    * Add a new IGenerator to the registry.
 53 |    */
 54 |   addGenerator(generator: TableOfContentsRegistry.IGenerator): void {
 55 |     this._generators.push(generator);
 56 |   }
 57 | 
 58 |   private _generators: TableOfContentsRegistry.IGenerator[] = [];
 59 | }
 60 | 
 61 | /**
 62 |  * A namespace for TableOfContentsRegistry statics.
 63 |  */
 64 | export namespace TableOfContentsRegistry {
 65 |   /**
 66 |    * An interface for an object that knows how to generate a table-of-contents
 67 |    * for a type of widget.
 68 |    */
 69 | 
 70 |   export abstract class IGeneratorOptionsManager {}
 71 | 
 72 |   export interface IGenerator {
 73 |     /**
 74 |      * An instance tracker for the widget.
 75 |      */
 76 |     tracker: IInstanceTracker;
 77 | 
 78 |     /**
 79 |      * A function to test whether to generate a ToC for a widget.
 80 |      *
 81 |      * #### Notes
 82 |      * By default is assumed to be enabled if the widget
 83 |      * is hosted in `tracker`. However, the user may want to add
 84 |      * additional checks. For instance, this can be used to generate
 85 |      * a ToC for text files only if they have a given mimeType.
 86 |      */
 87 |     isEnabled?: (widget: W) => boolean;
 88 | 
 89 |     /**
 90 |      * Whether the document uses LaTeX typesetting.
 91 |      *
 92 |      * Defaults to `false`.
 93 |      */
 94 |     usesLatex?: boolean;
 95 | 
 96 |     /**
 97 |      * An object that manage user settings for the generator.
 98 |      *
 99 |      * Defaults to `undefined`.
100 |      */
101 |     options?: IGeneratorOptionsManager;
102 | 
103 |     /**
104 |      * A function that generates JSX element for each heading
105 |      *
106 |      * If not given, the default renderer will be used, which renders the text
107 |      */
108 |     itemRenderer?: (item: IHeading) => JSX.Element | null;
109 | 
110 |     /**
111 |      * A function that generates a toolbar for the generator
112 |      *
113 |      * If not given, no toolbar will show up
114 |      */
115 |     toolbarGenerator?: () => any;
116 | 
117 |     /**
118 |      * A function that takes the widget, and produces
119 |      * a list of headings.
120 |      */
121 |     generate(widget: W): IHeading[];
122 |   }
123 | }
124 | 


--------------------------------------------------------------------------------
/src/toc.tsx:
--------------------------------------------------------------------------------
  1 | // Copyright (c) Jupyter Development Team.
  2 | // Distributed under the terms of the Modified BSD License.
  3 | 
  4 | import { ActivityMonitor, PathExt } from '@jupyterlab/coreutils';
  5 | 
  6 | import { IDocumentManager } from '@jupyterlab/docmanager';
  7 | 
  8 | import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
  9 | 
 10 | import { Message } from '@phosphor/messaging';
 11 | 
 12 | import { Widget } from '@phosphor/widgets';
 13 | 
 14 | import { TableOfContentsRegistry } from './registry';
 15 | 
 16 | import * as React from 'react';
 17 | import * as ReactDOM from 'react-dom';
 18 | 
 19 | /**
 20 |  * Timeout for throttling TOC rendering.
 21 |  */
 22 | const RENDER_TIMEOUT = 1000;
 23 | 
 24 | /**
 25 |  * A widget for hosting a notebook table-of-contents.
 26 |  */
 27 | export class TableOfContents extends Widget {
 28 |   /**
 29 |    * Create a new table of contents.
 30 |    */
 31 |   constructor(options: TableOfContents.IOptions) {
 32 |     super();
 33 |     this._docmanager = options.docmanager;
 34 |     this._rendermime = options.rendermime;
 35 |   }
 36 | 
 37 |   /**
 38 |    * The current widget-generator tuple for the ToC.
 39 |    */
 40 |   get current(): TableOfContents.ICurrentWidget | null {
 41 |     return this._current;
 42 |   }
 43 |   set current(value: TableOfContents.ICurrentWidget | null) {
 44 |     // If they are the same as previously, do nothing.
 45 |     if (
 46 |       value &&
 47 |       this._current &&
 48 |       this._current.widget === value.widget &&
 49 |       this._current.generator === value.generator
 50 |     ) {
 51 |       return;
 52 |     }
 53 |     this._current = value;
 54 | 
 55 |     if (this.generator && this.generator.toolbarGenerator) {
 56 |       this._toolbar = this.generator.toolbarGenerator();
 57 |     }
 58 | 
 59 |     // Dispose an old activity monitor if it existsd
 60 |     if (this._monitor) {
 61 |       this._monitor.dispose();
 62 |       this._monitor = null;
 63 |     }
 64 |     // If we are wiping the ToC, update and return.
 65 |     if (!this._current) {
 66 |       this.updateTOC();
 67 |       return;
 68 |     }
 69 | 
 70 |     // Find the document model associated with the widget.
 71 |     const context = this._docmanager.contextForWidget(this._current.widget);
 72 |     if (!context || !context.model) {
 73 |       throw Error('Could not find a context for the Table of Contents');
 74 |     }
 75 | 
 76 |     // Throttle the rendering rate of the table of contents.
 77 |     this._monitor = new ActivityMonitor({
 78 |       signal: context.model.contentChanged,
 79 |       timeout: RENDER_TIMEOUT
 80 |     });
 81 |     this._monitor.activityStopped.connect(this.update, this);
 82 |     this.updateTOC();
 83 |   }
 84 | 
 85 |   /**
 86 |    * Handle an update request.
 87 |    */
 88 |   protected onUpdateRequest(msg: Message): void {
 89 |     // Don't bother if the TOC is not visible
 90 |     /* if (!this.isVisible) {
 91 |       return;
 92 |     } */
 93 |     this.updateTOC();
 94 |   }
 95 | 
 96 |   updateTOC() {
 97 |     let toc: IHeading[] = [];
 98 |     let title = 'Table of Contents';
 99 |     if (this._current) {
100 |       toc = this._current.generator.generate(this._current.widget);
101 |       const context = this._docmanager.contextForWidget(this._current.widget);
102 |       if (context) {
103 |         title = PathExt.basename(context.localPath);
104 |       }
105 |     }
106 |     let itemRenderer: (item: IHeading) => JSX.Element | null = (
107 |       item: IHeading
108 |     ) => {
109 |       return {item.text};
110 |     };
111 |     if (this._current && this._current.generator.itemRenderer) {
112 |       itemRenderer = this._current.generator.itemRenderer!;
113 |     }
114 |     let renderedJSX = (
115 |       
116 |
{title}
117 |
118 | ); 119 | if (this._current && this._current.generator) { 120 | renderedJSX = ( 121 | 128 | ); 129 | } 130 | ReactDOM.render(renderedJSX, this.node, () => { 131 | if ( 132 | this._current && 133 | this._current.generator.usesLatex === true && 134 | this._rendermime.latexTypesetter 135 | ) { 136 | this._rendermime.latexTypesetter.typeset(this.node); 137 | } 138 | }); 139 | } 140 | 141 | get generator() { 142 | if (this._current) { 143 | return this._current.generator; 144 | } 145 | return null; 146 | } 147 | 148 | /** 149 | * Rerender after showing. 150 | */ 151 | protected onAfterShow(msg: Message): void { 152 | this.update(); 153 | } 154 | 155 | private _toolbar: any; 156 | private _rendermime: IRenderMimeRegistry; 157 | private _docmanager: IDocumentManager; 158 | private _current: TableOfContents.ICurrentWidget | null; 159 | private _monitor: ActivityMonitor | null; 160 | } 161 | 162 | /** 163 | * A namespace for TableOfContents statics. 164 | */ 165 | export namespace TableOfContents { 166 | /** 167 | * Options for the constructor. 168 | */ 169 | export interface IOptions { 170 | /** 171 | * The document manager for the application. 172 | */ 173 | docmanager: IDocumentManager; 174 | 175 | /** 176 | * The rendermime for the application. 177 | */ 178 | rendermime: IRenderMimeRegistry; 179 | } 180 | 181 | /** 182 | * A type representing a tuple of a widget, 183 | * and a generator that knows how to generate 184 | * heading information from that widget. 185 | */ 186 | export interface ICurrentWidget { 187 | widget: W; 188 | generator: TableOfContentsRegistry.IGenerator; 189 | } 190 | } 191 | 192 | /** 193 | * An object that represents a heading. 194 | */ 195 | export interface IHeading { 196 | /** 197 | * The text of the heading. 198 | */ 199 | text: string; 200 | 201 | /** 202 | * The HTML header level for the heading. 203 | */ 204 | level: number; 205 | 206 | /** 207 | * A function to execute when clicking the ToC 208 | * item. Typically this will be used to scroll 209 | * the parent widget to this item. 210 | */ 211 | onClick: () => void; 212 | 213 | /** 214 | * If there is special markup, we can instead 215 | * render the heading using a raw HTML string. This 216 | * HTML *should be properly sanitized!* 217 | * 218 | * For instance, this can be used to render 219 | * already-renderd-to-html markdown headings. 220 | */ 221 | html?: string; 222 | } 223 | 224 | /** 225 | * Props for the TOCItem component. 226 | */ 227 | export interface ITOCItemProps extends React.Props { 228 | /** 229 | * An IHeading to render. 230 | */ 231 | heading: IHeading; 232 | itemRenderer: (item: IHeading) => JSX.Element | null; 233 | } 234 | 235 | export interface ITOCItemStates {} 236 | 237 | /** 238 | * A React component for a table of contents entry. 239 | */ 240 | export class TOCItem extends React.Component { 241 | /** 242 | * Render the item. 243 | */ 244 | render() { 245 | const { heading } = this.props; 246 | 247 | // Create an onClick handler for the TOC item 248 | // that scrolls the anchor into view. 249 | const handleClick = (event: React.SyntheticEvent) => { 250 | event.preventDefault(); 251 | event.stopPropagation(); 252 | heading.onClick(); 253 | }; 254 | 255 | let content = this.props.itemRenderer(heading); 256 | return content &&
  • {content}
  • ; 257 | } 258 | } 259 | 260 | export interface ITOCTreeStates {} 261 | 262 | /** 263 | * Props for the TOCTree component. 264 | */ 265 | export interface ITOCTreeProps extends React.Props { 266 | /** 267 | * A title to display. 268 | */ 269 | title: string; 270 | 271 | /** 272 | * A list of IHeadings to render. 273 | */ 274 | toc: IHeading[]; 275 | toolbar: any; 276 | generator: TableOfContentsRegistry.IGenerator | null; 277 | itemRenderer: (item: IHeading) => JSX.Element | null; 278 | } 279 | 280 | /** 281 | * A React component for a table of contents. 282 | */ 283 | export class TOCTree extends React.Component { 284 | /** 285 | * Render the TOCTree. 286 | */ 287 | 288 | render() { 289 | // Map the heading objects onto a list of JSX elements. 290 | let i = 0; 291 | const Toolbar = this.props.toolbar; 292 | let listing: JSX.Element[] = this.props.toc.map(el => { 293 | return ( 294 | 299 | ); 300 | }); 301 | return ( 302 |
    303 |
    {this.props.title}
    304 | {Toolbar && } 305 |
      {listing}
    306 |
    307 | ); 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /style/img/autonumbering.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /style/img/autonumbering_darktheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /style/img/code_darktheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/eyeball_hidden.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/eyeball_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/eyeball_view.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/markdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /style/img/markdown_darktheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/menu_arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/numbering.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/tag.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /style/img/tag_darktheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /style/img/toggle_down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/toggle_down_darktheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/toggle_right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/img/toggle_right_darktheme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /style/index.css: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | 6 | /*----------------------------------------------------------------------------- 7 | | Table of Contents 8 | |----------------------------------------------------------------------------*/ 9 | 10 | .jp-TableOfContents-content { 11 | flex: 1 1 auto; 12 | margin: 0; 13 | padding: 0; 14 | list-style-type: none; 15 | overflow: auto; 16 | background-color: var(--jp-layout-color1); 17 | } 18 | 19 | .jp-TableOfContents-content li { 20 | display: flex; 21 | flex-direction: row; 22 | padding: 4px 12px; 23 | -webkit-user-select: none; 24 | -moz-user-select: none; 25 | -ms-user-select: none; 26 | user-select: none; 27 | cursor: pointer; 28 | padding-top: 8px; 29 | padding-bottom: 8px; 30 | } 31 | 32 | .jp-TableOfContents-content li:hover { 33 | background: var(--jp-layout-color2); 34 | } 35 | 36 | .jp-TableOfContents { 37 | display: flex; 38 | flex-direction: column; 39 | background: var(--jp-layout-color1); 40 | color: var(--jp-ui-font-color1); 41 | font-size: var(--jp-ui-font-size0); 42 | height: 100%; 43 | } 44 | 45 | .jp-TableOfContents header { 46 | border-bottom: var(--jp-border-width) solid var(--jp-border-color2); 47 | flex: 0 0 auto; 48 | font-size: var(--jp-ui-font-size0); 49 | font-weight: 600; 50 | letter-spacing: 1px; 51 | margin: 0px; 52 | padding: 12px 0 4px 12px; 53 | text-transform: uppercase; 54 | } 55 | 56 | [data-theme-light='true'] .jp-TableOfContents-icon { 57 | background-image: url(list-light.svg); 58 | } 59 | 60 | [data-theme-light='false'] .jp-TableOfContents-icon { 61 | background-image: url(list-dark.svg); 62 | } 63 | 64 | .jp-TableOfContents-codeContainer { 65 | overflow: hidden; 66 | } 67 | 68 | .jp-TableOfContents-code { 69 | font-size: 9px; 70 | max-height: 70px; 71 | } 72 | 73 | .cm-toc .CodeMirror { 74 | font-size: 9px; 75 | z-index: 0; 76 | border: var(--jp-border-width) solid var(--jp-cell-editor-border-color); 77 | border-radius: 0px; 78 | background: var(--jp-cell-editor-background); 79 | max-width: 100%; 80 | max-height: 36px; 81 | } 82 | 83 | .toc-code-span { 84 | width: 100%; 85 | max-width: 100%; 86 | overflow: hidden; 87 | } 88 | 89 | .cm-toc .CodeMirror-scroll { 90 | overflow: hidden !important; 91 | } 92 | 93 | .CodeMirror-scroll::-webkit-scrollbar-track { 94 | background-color: transparent; 95 | } 96 | 97 | .toc-toolbar-icon, 98 | .toc-toolbar-icon-selected { 99 | float: left; 100 | padding: 0px; 101 | margin: 4px; 102 | background-repeat: no-repeat; 103 | background-color: none; 104 | background-size: 100%; 105 | background-position: center; 106 | height: 24px; 107 | width: 24px; 108 | margin: 4px; 109 | border-radius: 2px; 110 | } 111 | 112 | [data-theme-light='true'] .toc-toolbar-code-icon { 113 | background-image: url('img/code.svg'); 114 | } 115 | 116 | [data-theme-light='false'] .toc-toolbar-code-icon { 117 | background-image: url('img/code_darktheme.svg'); 118 | } 119 | 120 | [data-theme-light='true'] .toc-toolbar-markdown-icon { 121 | background-image: url('img/markdown.svg'); 122 | } 123 | 124 | [data-theme-light='false'] .toc-toolbar-markdown-icon { 125 | background-image: url('img/markdown_darktheme.svg'); 126 | } 127 | 128 | [data-theme-light='true'] .toc-toolbar-auto-numbering-icon { 129 | background-image: url('img/autonumbering.svg'); 130 | } 131 | 132 | [data-theme-light='false'] .toc-toolbar-auto-numbering-icon { 133 | background-image: url('img/autonumbering_darktheme.svg'); 134 | } 135 | 136 | .toc-toolbar-tag-icon { 137 | width: 30px; 138 | height: 22px; 139 | margin: 4px 9px 4px 4px; 140 | } 141 | 142 | [data-theme-light='true'] .toc-toolbar-tag-icon { 143 | background-image: url('img/tag.svg'); 144 | } 145 | 146 | [data-theme-light='false'] .toc-toolbar-tag-icon { 147 | background-image: url('img/tag_darktheme.svg'); 148 | } 149 | 150 | [data-theme-light='true'] .toc-toolbar-icon:hover { 151 | background-color: var(--jp-input-background); 152 | } 153 | 154 | [data-theme-light='false'] .toc-toolbar-icon:hover { 155 | background-color: #3a3a3a; 156 | } 157 | 158 | [data-theme-light='true'] .toc-toolbar-icon-selected { 159 | background-color: var(--jp-layout-color2); 160 | } 161 | 162 | [data-theme-light='false'] .toc-toolbar-icon-selected { 163 | background-color: #565656; 164 | } 165 | 166 | .toc-code-cell-prompt { 167 | flex: 0 0 27px; 168 | color: var(--jp-cell-prompt-not-active-font-color); 169 | opacity: var(--jp-cell-prompt-not-active-opacity); 170 | font-family: var(--jp-cell-prompt-font-family); 171 | padding: var(--jp-code-padding); 172 | padding-right: 0px; 173 | padding-left: 0px; 174 | letter-spacing: var(--jp-cell-prompt-letter-spacing); 175 | line-height: var(--jp-code-line-height); 176 | font-size: 8px; 177 | border: var(--jp-border-width) solid transparent; 178 | text-align: left; 179 | white-space: nowrap; 180 | overflow: hidden; 181 | text-overflow: ellipsis; 182 | -webkit-user-select: none; 183 | -moz-user-select: none; 184 | -ms-user-select: none; 185 | user-select: none; 186 | } 187 | 188 | .toc-toolbar { 189 | position: relative; 190 | width: 100%; 191 | margin: 0px; 192 | user-select: none; 193 | border-bottom: var(--jp-border-width) solid var(--jp-border-color2); 194 | height: 36px; 195 | display: flex; 196 | align-items: center; 197 | } 198 | 199 | .toc-code-cell-div { 200 | display: inline-flex; 201 | width: 100%; 202 | } 203 | 204 | .toc-entry-holder { 205 | display: inline-flex; 206 | position: relative; 207 | align-items: center; 208 | width: 100%; 209 | } 210 | 211 | .toc-collapse-button { 212 | padding-left: 3px; 213 | cursor: default; 214 | min-width: 11px; 215 | position: absolute; 216 | } 217 | 218 | .toc-arrow-img { 219 | top: 0; 220 | bottom: 0; 221 | margin: auto; 222 | position: absolute; 223 | background-repeat: no-repeat; 224 | } 225 | 226 | .toc-downarrow-img { 227 | width: 12px; 228 | height: 6px; 229 | } 230 | 231 | [data-theme-light='true'] .toc-downarrow-img { 232 | background-image: url('img/toggle_down.svg'); 233 | } 234 | 235 | [data-theme-light='false'] .toc-downarrow-img { 236 | background-image: url('img/toggle_down_darktheme.svg'); 237 | } 238 | 239 | .toc-rightarrow-img { 240 | width: 7px; 241 | height: 12px; 242 | } 243 | 244 | [data-theme-light='true'] .toc-rightarrow-img { 245 | background-image: url('img/toggle_right.svg'); 246 | } 247 | 248 | [data-theme-light='false'] .toc-rightarrow-img { 249 | background-image: url('img/toggle_right_darktheme.svg'); 250 | } 251 | 252 | .toc-twist-placeholder { 253 | max-width: 10px; 254 | opacity: 0; 255 | overflow: hidden; 256 | } 257 | 258 | .cm-toc-plain-span { 259 | width: 100%; 260 | white-space: pre-wrap; 261 | display: block; 262 | } 263 | 264 | .cm-toc-plain-textarea { 265 | font-size: 9px; 266 | z-index: 0; 267 | border: var(--jp-border-width) solid var(--jp-cell-editor-border-color2); 268 | border-radius: 0px; 269 | background: var(--jp-cell-editor-background); 270 | width: calc(100% - 9px); 271 | overflow: hidden; 272 | max-height: 74px; 273 | resize: none; 274 | font-family: var(--jp-code-font-family); 275 | outline: none; 276 | user-select: none; 277 | white-space: pre; 278 | padding: var(--jp-code-padding); 279 | } 280 | 281 | .cm-toc .CodeMirror-sizer { 282 | min-width: 0px !important; 283 | min-height: 0px !important; 284 | margin-bottom: 0px !important; 285 | } 286 | 287 | .cm-toc .CodeMirror-line { 288 | white-space: pre-wrap; 289 | cursor: pointer; 290 | } 291 | 292 | .cm-toc .CodeMirror-lines { 293 | cursor: pointer; 294 | } 295 | 296 | .toc-tag-dropdown { 297 | display: flex; 298 | width: 100%; 299 | } 300 | 301 | .toc-tag-dropdown-button { 302 | margin-left: auto; 303 | } 304 | 305 | .toc-tags-container { 306 | padding: 4px; 307 | border-bottom: var(--jp-border-width) solid var(--jp-border-color2); 308 | } 309 | 310 | .toc-clear-button { 311 | font-size: 12px; 312 | color: var(--jp-ui-font-color1); 313 | padding-left: 15px; 314 | /* padding-top: 7px; */ 315 | user-select: none; 316 | float: right; 317 | } 318 | 319 | .toc-clear-button:hover { 320 | font-size: 12px; 321 | color: var(--jp-ui-font-color2); 322 | padding-left: 15px; 323 | /* padding-top: 7px; */ 324 | user-select: none; 325 | } 326 | 327 | .toc-filter-button { 328 | background-color: var(--jp-layout-color1); 329 | border: solid 1px var(--jp-layout-color4); 330 | border-radius: 3px; 331 | width: fit-content; 332 | padding: 5px; 333 | padding-left: 6px; 334 | padding-right: 6px; 335 | margin-right: 17px; 336 | color: var(--jp-layout-color5); 337 | float: right; 338 | font-size: 12px; 339 | user-select: none; 340 | margin-bottom: 13px; 341 | } 342 | 343 | .toc-filter-button:hover { 344 | background-color: var(--jp-layout-color4); 345 | border: solid 1px var(--jp-layout-color4); 346 | color: var(--jp-layout-color1); 347 | } 348 | 349 | .toc-filter-button-na { 350 | background-color: var(--jp-layout-color1); 351 | border: solid 1px var(--jp-ui-font-color3); 352 | border-radius: 3px; 353 | width: fit-content; 354 | padding: 5px; 355 | padding-left: 6px; 356 | padding-right: 6px; 357 | margin-right: 17px; 358 | color: var(--jp-ui-font-color3); 359 | float: right; 360 | font-size: 12px; 361 | user-select: none; 362 | margin-bottom: 13px; 363 | } 364 | 365 | .toc-no-tags-div { 366 | font-size: 12px; 367 | padding: 3px; 368 | padding-bottom: 6px; 369 | margin: auto; 370 | color: var(--jp-layout-color4); 371 | } 372 | 373 | .toc-tags-container { 374 | width: 100%; 375 | } 376 | 377 | .jp-TableOfContents-content code { 378 | font-size: inherit; 379 | } 380 | 381 | .toc-cell-item { 382 | padding-left: 24px; 383 | } 384 | 385 | /* styles for tags */ 386 | 387 | .toc-tag-label { 388 | font-size: 11px; 389 | max-width: 100%; 390 | text-overflow: ellipsis; 391 | display: inline-block; 392 | overflow: hidden; 393 | box-sizing: border-box; 394 | padding-top: 0px; 395 | margin-top: -1px; 396 | margin-bottom: 0px; 397 | user-select: none; 398 | } 399 | 400 | .toc-tag { 401 | box-sizing: border-box; 402 | height: 24px; 403 | border-radius: 20px; 404 | padding: 10px; 405 | padding-bottom: 4px; 406 | padding-top: 5px; 407 | margin: 3px; 408 | width: fit-content; 409 | max-width: calc(100% - 25px); 410 | } 411 | 412 | .toc-selected-tag { 413 | color: white; 414 | background-color: #2196f3; 415 | outline: none; 416 | } 417 | 418 | .toc-unselected-tag { 419 | background-color: var(--jp-layout-color2); 420 | outline: none; 421 | } 422 | 423 | .toc-tag-holder { 424 | display: flex; 425 | flex-wrap: wrap; 426 | height: fit-content; 427 | padding-bottom: 6px; 428 | padding-right: 20px; 429 | padding-left: 9px; 430 | padding-top: 6px; 431 | } 432 | 433 | /* Font level sizes */ 434 | 435 | .toc-level-size-1 { 436 | font-size: 16.89px; 437 | } 438 | 439 | .toc-level-size-2 { 440 | font-size: 14.82px; 441 | } 442 | 443 | .toc-level-size-3 { 444 | font-size: 13px; 445 | } 446 | 447 | .toc-level-size-4 { 448 | font-size: 11.4px; 449 | } 450 | 451 | .toc-level-size-5 { 452 | font-size: 10px; 453 | } 454 | 455 | .toc-level-size-6 { 456 | font-size: 9px; 457 | } 458 | 459 | .toc-level-size-default { 460 | font-size: 9px; 461 | } 462 | -------------------------------------------------------------------------------- /style/list-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /style/list-light.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /toc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ian-r-rose/jupyterlab-toc/d1f81f37aad25ca59dd9e1d75129c30fdef947a2/toc.gif -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "noImplicitAny": true, 5 | "strictNullChecks": true, 6 | "skipLibCheck": true, 7 | "noEmitOnError": true, 8 | "noUnusedLocals": true, 9 | "lib": ["DOM", "ES6"], 10 | "module": "commonjs", 11 | "moduleResolution": "node", 12 | "target": "ES6", 13 | "outDir": "lib", 14 | "rootDir": "src", 15 | "jsx": "react" 16 | }, 17 | "include": ["src/**/*"] 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": ["tslint-plugin-prettier"], 3 | "rules": { 4 | "prettier": [true, { "singleQuote": true }], 5 | "align": [true, "parameters", "statements"], 6 | "ban": [ 7 | true, 8 | ["_", "forEach"], 9 | ["_", "each"], 10 | ["$", "each"], 11 | ["angular", "forEach"] 12 | ], 13 | "class-name": true, 14 | "comment-format": [true, "check-space"], 15 | "curly": true, 16 | "eofline": true, 17 | "forin": false, 18 | "indent": [true, "spaces", 2], 19 | "interface-name": [true, "always-prefix"], 20 | "jsdoc-format": true, 21 | "label-position": true, 22 | "max-line-length": [false], 23 | "member-access": false, 24 | "member-ordering": [false], 25 | "new-parens": true, 26 | "no-angle-bracket-type-assertion": true, 27 | "no-any": false, 28 | "no-arg": true, 29 | "no-bitwise": true, 30 | "no-conditional-assignment": true, 31 | "no-consecutive-blank-lines": false, 32 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"], 33 | "no-construct": true, 34 | "no-debugger": true, 35 | "no-default-export": false, 36 | "no-duplicate-variable": true, 37 | "no-empty": true, 38 | "no-eval": true, 39 | "no-inferrable-types": false, 40 | "no-internal-module": true, 41 | "no-invalid-this": [true, "check-function-in-method"], 42 | "no-null-keyword": false, 43 | "no-reference": true, 44 | "no-require-imports": false, 45 | "no-shadowed-variable": false, 46 | "no-string-literal": false, 47 | "no-switch-case-fall-through": true, 48 | "no-trailing-whitespace": true, 49 | "no-unused-expression": true, 50 | "no-use-before-declare": false, 51 | "no-var-keyword": true, 52 | "no-var-requires": true, 53 | "object-literal-sort-keys": false, 54 | "one-line": [ 55 | true, 56 | "check-open-brace", 57 | "check-catch", 58 | "check-else", 59 | "check-finally", 60 | "check-whitespace" 61 | ], 62 | "one-variable-per-declaration": [true, "ignore-for-loop"], 63 | "quotemark": [true, "single", "avoid-escape", "jsx-double"], 64 | "radix": true, 65 | "semicolon": [true, "always", "ignore-bound-class-methods"], 66 | "switch-default": true, 67 | "trailing-comma": [ 68 | false, 69 | { 70 | "multiline": "never", 71 | "singleline": "never" 72 | } 73 | ], 74 | "triple-equals": [true, "allow-null-check", "allow-undefined-check"], 75 | "typedef": [false], 76 | "typedef-whitespace": [ 77 | false, 78 | { 79 | "call-signature": "nospace", 80 | "index-signature": "nospace", 81 | "parameter": "nospace", 82 | "property-declaration": "nospace", 83 | "variable-declaration": "nospace" 84 | }, 85 | { 86 | "call-signature": "space", 87 | "index-signature": "space", 88 | "parameter": "space", 89 | "property-declaration": "space", 90 | "variable-declaration": "space" 91 | } 92 | ], 93 | "use-isnan": true, 94 | "use-strict": [false], 95 | "variable-name": [ 96 | true, 97 | "check-format", 98 | "allow-leading-underscore", 99 | "ban-keywords" 100 | ], 101 | "whitespace": [ 102 | true, 103 | "check-branch", 104 | "check-operator", 105 | "check-separator", 106 | "check-type" 107 | ] 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/runtime@^7.1.2": 6 | version "7.3.1" 7 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.1.tgz#574b03e8e8a9898eaf4a872a92ea20b7846f6f2a" 8 | dependencies: 9 | regenerator-runtime "^0.12.0" 10 | 11 | "@blueprintjs/core@^3.12.0", "@blueprintjs/core@^3.9.0": 12 | version "3.12.0" 13 | resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.12.0.tgz#98709ba9d0d0813c8e974eb49f1b5abd6c8e271b" 14 | dependencies: 15 | "@blueprintjs/icons" "^3.5.1" 16 | "@types/dom4" "^2.0.0" 17 | classnames "^2.2" 18 | dom4 "^2.0.1" 19 | normalize.css "^8.0.0" 20 | popper.js "^1.14.1" 21 | react-popper "^1.0.0" 22 | react-transition-group "^2.2.1" 23 | resize-observer-polyfill "^1.5.0" 24 | tslib "^1.9.0" 25 | 26 | "@blueprintjs/icons@^3.3.0", "@blueprintjs/icons@^3.5.1": 27 | version "3.5.1" 28 | resolved "https://registry.yarnpkg.com/@blueprintjs/icons/-/icons-3.5.1.tgz#29dabfa2edb3efeefdc472b19e71736fadf5666b" 29 | dependencies: 30 | classnames "^2.2" 31 | tslib "^1.9.0" 32 | 33 | "@blueprintjs/select@^3.3.0": 34 | version "3.6.0" 35 | resolved "https://registry.yarnpkg.com/@blueprintjs/select/-/select-3.6.0.tgz#6c42107c99c4d0007eedde239218956210d53427" 36 | dependencies: 37 | "@blueprintjs/core" "^3.12.0" 38 | classnames "^2.2" 39 | tslib "^1.9.0" 40 | 41 | "@jupyterlab/application@^1.0.0-alpha.6": 42 | version "1.0.0-alpha.6" 43 | resolved "https://registry.yarnpkg.com/@jupyterlab/application/-/application-1.0.0-alpha.6.tgz#0d7f3eca72b04ac374d7d13a7612d45c4bc907bd" 44 | integrity sha512-srw0b4u4Hvpe15qmnm3GtByXyrE3wrnTUbc5vCCOydVujPfZKy4YmY97t8rKwe8nQNKIZ/ouOokRF3UUs/0dtA== 45 | dependencies: 46 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 47 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 48 | "@jupyterlab/docregistry" "^1.0.0-alpha.6" 49 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 50 | "@jupyterlab/rendermime-interfaces" "^1.3.0-alpha.6" 51 | "@jupyterlab/services" "^4.0.0-alpha.6" 52 | "@phosphor/algorithm" "^1.1.2" 53 | "@phosphor/application" "^1.6.0" 54 | "@phosphor/commands" "^1.6.1" 55 | "@phosphor/coreutils" "^1.3.0" 56 | "@phosphor/disposable" "^1.1.2" 57 | "@phosphor/messaging" "^1.2.2" 58 | "@phosphor/properties" "^1.1.2" 59 | "@phosphor/signaling" "^1.2.2" 60 | "@phosphor/widgets" "^1.6.0" 61 | font-awesome "~4.7.0" 62 | 63 | "@jupyterlab/apputils@^1.0.0-alpha.6": 64 | version "1.0.0-alpha.6" 65 | resolved "https://registry.yarnpkg.com/@jupyterlab/apputils/-/apputils-1.0.0-alpha.6.tgz#5faac3fc34f0cedd260436fcc9c7aad081d95234" 66 | integrity sha512-Ir7LHfXl/kcFiXmGWGayaMXShyi8WkLa9pRAUJYuRYcGbhJwvpKwGpaakrFr021UGFWJtem8mTTSAJ7s3OyOlA== 67 | dependencies: 68 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 69 | "@jupyterlab/services" "^4.0.0-alpha.6" 70 | "@jupyterlab/ui-components" "^1.0.0-alpha.6" 71 | "@phosphor/algorithm" "^1.1.2" 72 | "@phosphor/commands" "^1.6.1" 73 | "@phosphor/coreutils" "^1.3.0" 74 | "@phosphor/disposable" "^1.1.2" 75 | "@phosphor/domutils" "^1.1.2" 76 | "@phosphor/messaging" "^1.2.2" 77 | "@phosphor/properties" "^1.1.2" 78 | "@phosphor/signaling" "^1.2.2" 79 | "@phosphor/virtualdom" "^1.1.2" 80 | "@phosphor/widgets" "^1.6.0" 81 | "@types/react" "~16.8.8" 82 | react "~16.8.4" 83 | react-dom "~16.8.4" 84 | sanitize-html "~1.18.2" 85 | 86 | "@jupyterlab/attachments@^1.0.0-alpha.6": 87 | version "1.0.0-alpha.6" 88 | resolved "https://registry.yarnpkg.com/@jupyterlab/attachments/-/attachments-1.0.0-alpha.6.tgz#ef35b4064ee0a6e6632302af758d0660aa36b0a7" 89 | integrity sha512-U3KFu0VkAXXYSZy570wkIFsrrYZZP2zfLR5fmZUFnKYD7kt+v9QMUYi+XuOZkrGOlDsOa7f1GUsdWM6zpW19zA== 90 | dependencies: 91 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 92 | "@jupyterlab/observables" "^2.2.0-alpha.6" 93 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 94 | "@jupyterlab/rendermime-interfaces" "^1.3.0-alpha.6" 95 | "@phosphor/disposable" "^1.1.2" 96 | "@phosphor/signaling" "^1.2.2" 97 | 98 | "@jupyterlab/cells@^1.0.0-alpha.6", "@jupyterlab/cells@^1.0.0-alpha.7": 99 | version "1.0.0-alpha.7" 100 | resolved "https://registry.yarnpkg.com/@jupyterlab/cells/-/cells-1.0.0-alpha.7.tgz#9587226f83524f322c590f59d9723983f55e88a3" 101 | integrity sha512-7TD2v0uhXJNS1wDarae+6RZqPBhMoI3zqz3Ox7ZeCwt25DKh08rjTkiJx5YrSYAjdF2h1fqQvrKZo+cB9KTZgg== 102 | dependencies: 103 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 104 | "@jupyterlab/attachments" "^1.0.0-alpha.6" 105 | "@jupyterlab/codeeditor" "^1.0.0-alpha.6" 106 | "@jupyterlab/codemirror" "^1.0.0-alpha.6" 107 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 108 | "@jupyterlab/observables" "^2.2.0-alpha.6" 109 | "@jupyterlab/outputarea" "^1.0.0-alpha.6" 110 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 111 | "@jupyterlab/services" "^4.0.0-alpha.6" 112 | "@phosphor/algorithm" "^1.1.2" 113 | "@phosphor/coreutils" "^1.3.0" 114 | "@phosphor/messaging" "^1.2.2" 115 | "@phosphor/signaling" "^1.2.2" 116 | "@phosphor/virtualdom" "^1.1.2" 117 | "@phosphor/widgets" "^1.6.0" 118 | react "~16.8.4" 119 | 120 | "@jupyterlab/codeeditor@^1.0.0-alpha.6": 121 | version "1.0.0-alpha.6" 122 | resolved "https://registry.yarnpkg.com/@jupyterlab/codeeditor/-/codeeditor-1.0.0-alpha.6.tgz#cce9ab668c9bc1d76587e095c3c3d9e9af0f3991" 123 | integrity sha512-6Y1m7s/CAEni/C+cWHToIbAsuCzahgBCtEqhrtnoHBD/LQvZ45RYuvIfhCAyEmT/ObQr1EN9gfmBkVnqzvnjXQ== 124 | dependencies: 125 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 126 | "@jupyterlab/observables" "^2.2.0-alpha.6" 127 | "@phosphor/coreutils" "^1.3.0" 128 | "@phosphor/disposable" "^1.1.2" 129 | "@phosphor/dragdrop" "^1.3.0" 130 | "@phosphor/messaging" "^1.2.2" 131 | "@phosphor/signaling" "^1.2.2" 132 | "@phosphor/widgets" "^1.6.0" 133 | 134 | "@jupyterlab/codemirror@^1.0.0-alpha.6": 135 | version "1.0.0-alpha.6" 136 | resolved "https://registry.yarnpkg.com/@jupyterlab/codemirror/-/codemirror-1.0.0-alpha.6.tgz#2a9004c5ae2bfd68886135d68511dab1017477cc" 137 | integrity sha512-fV5xh2GwnIDZyilIeTD2FCpwKLMLPOAR1k3gopBudh9UVk8KiGjjKth49fQyZfApSoVDZADgEDmvsWTmOh4JBA== 138 | dependencies: 139 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 140 | "@jupyterlab/codeeditor" "^1.0.0-alpha.6" 141 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 142 | "@jupyterlab/observables" "^2.2.0-alpha.6" 143 | "@jupyterlab/statusbar" "^1.0.0-alpha.6" 144 | "@phosphor/algorithm" "^1.1.2" 145 | "@phosphor/commands" "^1.6.1" 146 | "@phosphor/coreutils" "^1.3.0" 147 | "@phosphor/disposable" "^1.1.2" 148 | "@phosphor/signaling" "^1.2.2" 149 | "@phosphor/widgets" "^1.6.0" 150 | codemirror "~5.42.0" 151 | react "~16.8.4" 152 | 153 | "@jupyterlab/coreutils@3.0.0-alpha.6", "@jupyterlab/coreutils@^3.0.0-alpha.6": 154 | version "3.0.0-alpha.6" 155 | resolved "https://registry.yarnpkg.com/@jupyterlab/coreutils/-/coreutils-3.0.0-alpha.6.tgz#b0ec4600d357fdeb3f8d93c559f6aa9e493066a7" 156 | integrity sha512-t3Lp9iFRjzTsc573+KGKStE/YvkUbKQ2+7FF0hz9fDkeWp6+ZNCHWD97eudo6V+I/g5zRgO8eqgbjeKhGyv/KA== 157 | dependencies: 158 | "@phosphor/coreutils" "^1.3.0" 159 | "@phosphor/disposable" "^1.1.2" 160 | "@phosphor/signaling" "^1.2.2" 161 | ajv "^6.5.5" 162 | comment-json "^1.1.3" 163 | minimist "~1.2.0" 164 | moment "~2.21.0" 165 | path-posix "~1.0.0" 166 | url-parse "~1.4.3" 167 | 168 | "@jupyterlab/docmanager@^1.0.0-alpha.6": 169 | version "1.0.0-alpha.6" 170 | resolved "https://registry.yarnpkg.com/@jupyterlab/docmanager/-/docmanager-1.0.0-alpha.6.tgz#d66f99589ba39eadf0d79e4da069f24b00ec83a5" 171 | integrity sha512-iagl7b+QYLQtAjsPKma1sNPuozq8lLf9rvxNdCXYwHKAOLysaem7AYRl9x2SBn898VBCBUc+OFReNmmZNFMdgw== 172 | dependencies: 173 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 174 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 175 | "@jupyterlab/docregistry" "^1.0.0-alpha.6" 176 | "@jupyterlab/services" "^4.0.0-alpha.6" 177 | "@jupyterlab/statusbar" "^1.0.0-alpha.6" 178 | "@phosphor/algorithm" "^1.1.2" 179 | "@phosphor/coreutils" "^1.3.0" 180 | "@phosphor/disposable" "^1.1.2" 181 | "@phosphor/messaging" "^1.2.2" 182 | "@phosphor/properties" "^1.1.2" 183 | "@phosphor/signaling" "^1.2.2" 184 | "@phosphor/widgets" "^1.6.0" 185 | react "~16.8.4" 186 | 187 | "@jupyterlab/docregistry@^1.0.0-alpha.6": 188 | version "1.0.0-alpha.6" 189 | resolved "https://registry.yarnpkg.com/@jupyterlab/docregistry/-/docregistry-1.0.0-alpha.6.tgz#7c70fd36151e5f3e84b5041a03b07e0b45e3fd44" 190 | integrity sha512-Wn0SoaJqPMJ9E7BqiY6Jd7uBmz/KeePjLw/Js90NUqhI1GXLNiUoMy3JO0YlUJmWIpgra+kQExXquv86R1GvoA== 191 | dependencies: 192 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 193 | "@jupyterlab/codeeditor" "^1.0.0-alpha.6" 194 | "@jupyterlab/codemirror" "^1.0.0-alpha.6" 195 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 196 | "@jupyterlab/observables" "^2.2.0-alpha.6" 197 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 198 | "@jupyterlab/rendermime-interfaces" "^1.3.0-alpha.6" 199 | "@jupyterlab/services" "^4.0.0-alpha.6" 200 | "@phosphor/algorithm" "^1.1.2" 201 | "@phosphor/coreutils" "^1.3.0" 202 | "@phosphor/disposable" "^1.1.2" 203 | "@phosphor/messaging" "^1.2.2" 204 | "@phosphor/signaling" "^1.2.2" 205 | "@phosphor/widgets" "^1.6.0" 206 | 207 | "@jupyterlab/fileeditor@^1.0.0-alpha.6": 208 | version "1.0.0-alpha.6" 209 | resolved "https://registry.yarnpkg.com/@jupyterlab/fileeditor/-/fileeditor-1.0.0-alpha.6.tgz#9f8472b858943eccf5076809fcfbe04bcbd746f9" 210 | integrity sha512-yCI1i7oldqVWRXZVYWBR7OKDqVtyB8LSyxoSkP/UvOeLqgM8LUt0ViZQXs+G6esDa0CN8DHfAKB2jEVj4sD82Q== 211 | dependencies: 212 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 213 | "@jupyterlab/codeeditor" "^1.0.0-alpha.6" 214 | "@jupyterlab/docregistry" "^1.0.0-alpha.6" 215 | "@jupyterlab/statusbar" "^1.0.0-alpha.6" 216 | "@phosphor/coreutils" "^1.3.0" 217 | "@phosphor/messaging" "^1.2.2" 218 | "@phosphor/widgets" "^1.6.0" 219 | react "~16.8.4" 220 | 221 | "@jupyterlab/markdownviewer@^1.0.0-alpha.6": 222 | version "1.0.0-alpha.6" 223 | resolved "https://registry.yarnpkg.com/@jupyterlab/markdownviewer/-/markdownviewer-1.0.0-alpha.6.tgz#1138aa70c716618c238f787e5b78292009a5a881" 224 | integrity sha512-rVETo3Go6BlStoKRBUtDexT+QbNMAQsaf44wDI4sUFwc0B7w9UXwj7PZZ8pSHtvxyVm/GO8VKj9mXwO5aViclA== 225 | dependencies: 226 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 227 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 228 | "@jupyterlab/docregistry" "^1.0.0-alpha.6" 229 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 230 | "@phosphor/coreutils" "^1.3.0" 231 | "@phosphor/messaging" "^1.2.2" 232 | "@phosphor/widgets" "^1.6.0" 233 | 234 | "@jupyterlab/notebook@^1.0.0-alpha.7": 235 | version "1.0.0-alpha.7" 236 | resolved "https://registry.yarnpkg.com/@jupyterlab/notebook/-/notebook-1.0.0-alpha.7.tgz#d7a065c2a100c250b91118493fa5b3c51144cb3a" 237 | integrity sha512-WGC0ctC6e+NNwaR/x6Gu8K8E08N6h4dBXp43b/5VwOp1Oj9hBqNOJZVp0JnLKcKBspGTcBRXhVn6rk31Sv7v6A== 238 | dependencies: 239 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 240 | "@jupyterlab/cells" "^1.0.0-alpha.7" 241 | "@jupyterlab/codeeditor" "^1.0.0-alpha.6" 242 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 243 | "@jupyterlab/docregistry" "^1.0.0-alpha.6" 244 | "@jupyterlab/observables" "^2.2.0-alpha.6" 245 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 246 | "@jupyterlab/services" "^4.0.0-alpha.6" 247 | "@jupyterlab/statusbar" "^1.0.0-alpha.6" 248 | "@jupyterlab/ui-components" "^1.0.0-alpha.6" 249 | "@phosphor/algorithm" "^1.1.2" 250 | "@phosphor/coreutils" "^1.3.0" 251 | "@phosphor/domutils" "^1.1.2" 252 | "@phosphor/dragdrop" "^1.3.0" 253 | "@phosphor/messaging" "^1.2.2" 254 | "@phosphor/properties" "^1.1.2" 255 | "@phosphor/signaling" "^1.2.2" 256 | "@phosphor/virtualdom" "^1.1.2" 257 | "@phosphor/widgets" "^1.6.0" 258 | react "~16.8.4" 259 | 260 | "@jupyterlab/observables@^2.2.0-alpha.6": 261 | version "2.2.0-alpha.6" 262 | resolved "https://registry.yarnpkg.com/@jupyterlab/observables/-/observables-2.2.0-alpha.6.tgz#58d5d8aeb75fac878874cdaa59501d1496b6ddde" 263 | integrity sha512-u93u/knpD3Lijye3jlu3xfyZotcreFhQloZ+1iKRSXmDFwNvkjJqwTd9ibq9v1fcfGDcy+AiE50+7RqDxQ9YAQ== 264 | dependencies: 265 | "@phosphor/algorithm" "^1.1.2" 266 | "@phosphor/coreutils" "^1.3.0" 267 | "@phosphor/disposable" "^1.1.2" 268 | "@phosphor/messaging" "^1.2.2" 269 | "@phosphor/signaling" "^1.2.2" 270 | 271 | "@jupyterlab/outputarea@^1.0.0-alpha.6": 272 | version "1.0.0-alpha.6" 273 | resolved "https://registry.yarnpkg.com/@jupyterlab/outputarea/-/outputarea-1.0.0-alpha.6.tgz#9b9b77a8ae99ee5cbf5e1a5d7a2eecd3b37b6fc5" 274 | integrity sha512-H4hkKAaXNL/WUX5DxsuhbC+cSodPkrYO35t66PjeyJMfezA8MP0bz9pdoDcJ5aOOvem/HEm48r4cuM4MEErtxg== 275 | dependencies: 276 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 277 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 278 | "@jupyterlab/observables" "^2.2.0-alpha.6" 279 | "@jupyterlab/rendermime" "^1.0.0-alpha.6" 280 | "@jupyterlab/rendermime-interfaces" "^1.3.0-alpha.6" 281 | "@jupyterlab/services" "^4.0.0-alpha.6" 282 | "@phosphor/algorithm" "^1.1.2" 283 | "@phosphor/coreutils" "^1.3.0" 284 | "@phosphor/disposable" "^1.1.2" 285 | "@phosphor/messaging" "^1.2.2" 286 | "@phosphor/signaling" "^1.2.2" 287 | "@phosphor/widgets" "^1.6.0" 288 | 289 | "@jupyterlab/rendermime-interfaces@^1.3.0-alpha.6": 290 | version "1.3.0-alpha.6" 291 | resolved "https://registry.yarnpkg.com/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-1.3.0-alpha.6.tgz#479fca4c33f7b2057fb8b1207b8b7484c35b6e19" 292 | integrity sha512-4braKQb3pVWQ+QeGfvpGjMtKsXOkevRvnUTb3AICGrnmG4cGEC9JN3QiSihWgELguM6Wu08XUzCWo6MlH31Y7w== 293 | dependencies: 294 | "@phosphor/coreutils" "^1.3.0" 295 | "@phosphor/widgets" "^1.6.0" 296 | 297 | "@jupyterlab/rendermime@^1.0.0-alpha.6": 298 | version "1.0.0-alpha.6" 299 | resolved "https://registry.yarnpkg.com/@jupyterlab/rendermime/-/rendermime-1.0.0-alpha.6.tgz#dc90fd46032c0b9725d18854d4a1df03987b6631" 300 | integrity sha512-kiwxOEOumVyq+Hd5hX79olucd1uKswx6NjEmfAKi2bfneGEcP4Vd1a+X6pKT2Jqah7JBW0iEIprEsRUN6eOQFA== 301 | dependencies: 302 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 303 | "@jupyterlab/codemirror" "^1.0.0-alpha.6" 304 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 305 | "@jupyterlab/observables" "^2.2.0-alpha.6" 306 | "@jupyterlab/rendermime-interfaces" "^1.3.0-alpha.6" 307 | "@jupyterlab/services" "^4.0.0-alpha.6" 308 | "@phosphor/algorithm" "^1.1.2" 309 | "@phosphor/coreutils" "^1.3.0" 310 | "@phosphor/messaging" "^1.2.2" 311 | "@phosphor/signaling" "^1.2.2" 312 | "@phosphor/widgets" "^1.6.0" 313 | lodash.escape "^4.0.1" 314 | marked "0.5.1" 315 | 316 | "@jupyterlab/services@^4.0.0-alpha.6": 317 | version "4.0.0-alpha.6" 318 | resolved "https://registry.yarnpkg.com/@jupyterlab/services/-/services-4.0.0-alpha.6.tgz#cb51f0abf62a600949fe180cbcbb10c65edac6f5" 319 | integrity sha512-veLHmuPFMVt4ByLAks3+7GVpk3zMcBmBfUt2RiswHfeBhzGgSVEOq/Tovt59DUQ9wgBsYCUsrbBjrHHr/0jyZg== 320 | dependencies: 321 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 322 | "@jupyterlab/observables" "^2.2.0-alpha.6" 323 | "@phosphor/algorithm" "^1.1.2" 324 | "@phosphor/coreutils" "^1.3.0" 325 | "@phosphor/disposable" "^1.1.2" 326 | "@phosphor/signaling" "^1.2.2" 327 | node-fetch "~2.2.0" 328 | ws "~6.0.0" 329 | 330 | "@jupyterlab/statusbar@^1.0.0-alpha.6": 331 | version "1.0.0-alpha.6" 332 | resolved "https://registry.yarnpkg.com/@jupyterlab/statusbar/-/statusbar-1.0.0-alpha.6.tgz#3ed41fa6d4dc1c8696c909c2998cdd906ea872fb" 333 | integrity sha512-ARKOMOS6F35z3zPlxwju/3eWIuivH9js3fOlzzM5Jbj0Gag9FO/2SzlPSIcHTVKXlqxBBYkzq05UaC0Na7h/uw== 334 | dependencies: 335 | "@jupyterlab/apputils" "^1.0.0-alpha.6" 336 | "@jupyterlab/codeeditor" "^1.0.0-alpha.6" 337 | "@jupyterlab/coreutils" "^3.0.0-alpha.6" 338 | "@jupyterlab/services" "^4.0.0-alpha.6" 339 | "@phosphor/algorithm" "^1.1.2" 340 | "@phosphor/coreutils" "^1.3.0" 341 | "@phosphor/disposable" "^1.1.2" 342 | "@phosphor/messaging" "^1.2.2" 343 | "@phosphor/signaling" "^1.2.2" 344 | "@phosphor/widgets" "^1.6.0" 345 | react "~16.8.4" 346 | typestyle "^2.0.1" 347 | 348 | "@jupyterlab/ui-components@^1.0.0-alpha.6": 349 | version "1.0.0-alpha.6" 350 | resolved "https://registry.yarnpkg.com/@jupyterlab/ui-components/-/ui-components-1.0.0-alpha.6.tgz#d44fc6689280d777acffdb73c8e54135fef88963" 351 | integrity sha512-XTrN8HcwPQHBE4PBkxPZ9GI8d528RQRWekXFippkBObqrf5GXnp2QBQ325jwIG/rFswePMGWpsDWZ1+ZQOEl+w== 352 | dependencies: 353 | "@blueprintjs/core" "^3.9.0" 354 | "@blueprintjs/icons" "^3.3.0" 355 | "@blueprintjs/select" "^3.3.0" 356 | react "~16.8.4" 357 | 358 | "@phosphor/algorithm@^1.1.2": 359 | version "1.1.2" 360 | resolved "https://registry.yarnpkg.com/@phosphor/algorithm/-/algorithm-1.1.2.tgz#fd1de9104c9a7f34e92864586ddf2e7f2e7779e8" 361 | 362 | "@phosphor/application@^1.6.0": 363 | version "1.6.0" 364 | resolved "https://registry.yarnpkg.com/@phosphor/application/-/application-1.6.0.tgz#e1f1bf300680f982881d222a77b24ba8589d3fa2" 365 | dependencies: 366 | "@phosphor/commands" "^1.5.0" 367 | "@phosphor/coreutils" "^1.3.0" 368 | "@phosphor/widgets" "^1.6.0" 369 | 370 | "@phosphor/collections@^1.1.2": 371 | version "1.1.2" 372 | resolved "https://registry.yarnpkg.com/@phosphor/collections/-/collections-1.1.2.tgz#c4c0b8b91129905fb36a9f243f2dbbde462dab8d" 373 | dependencies: 374 | "@phosphor/algorithm" "^1.1.2" 375 | 376 | "@phosphor/commands@^1.5.0", "@phosphor/commands@^1.6.1": 377 | version "1.6.1" 378 | resolved "https://registry.yarnpkg.com/@phosphor/commands/-/commands-1.6.1.tgz#6f60c2a3b759316cd1363b426df3b4036bb2c7fd" 379 | dependencies: 380 | "@phosphor/algorithm" "^1.1.2" 381 | "@phosphor/coreutils" "^1.3.0" 382 | "@phosphor/disposable" "^1.1.2" 383 | "@phosphor/domutils" "^1.1.2" 384 | "@phosphor/keyboard" "^1.1.2" 385 | "@phosphor/signaling" "^1.2.2" 386 | 387 | "@phosphor/coreutils@^1.3.0": 388 | version "1.3.0" 389 | resolved "https://registry.yarnpkg.com/@phosphor/coreutils/-/coreutils-1.3.0.tgz#63292d381c012c5ab0d0196e83ced829b7e04a42" 390 | 391 | "@phosphor/disposable@^1.1.2": 392 | version "1.1.2" 393 | resolved "https://registry.yarnpkg.com/@phosphor/disposable/-/disposable-1.1.2.tgz#a192dd6a2e6c69d5d09d39ecf334dab93778060e" 394 | dependencies: 395 | "@phosphor/algorithm" "^1.1.2" 396 | 397 | "@phosphor/domutils@^1.1.2": 398 | version "1.1.2" 399 | resolved "https://registry.yarnpkg.com/@phosphor/domutils/-/domutils-1.1.2.tgz#e2efeb052f398c42b93b89e9bab26af15cc00514" 400 | 401 | "@phosphor/dragdrop@^1.3.0": 402 | version "1.3.0" 403 | resolved "https://registry.yarnpkg.com/@phosphor/dragdrop/-/dragdrop-1.3.0.tgz#7ce6ad39d6ca216d62a56f78104d02a77ae67307" 404 | dependencies: 405 | "@phosphor/coreutils" "^1.3.0" 406 | "@phosphor/disposable" "^1.1.2" 407 | 408 | "@phosphor/keyboard@^1.1.2": 409 | version "1.1.2" 410 | resolved "https://registry.yarnpkg.com/@phosphor/keyboard/-/keyboard-1.1.2.tgz#3e32234451764240a98e148034d5a8797422dd1f" 411 | 412 | "@phosphor/messaging@^1.2.2": 413 | version "1.2.2" 414 | resolved "https://registry.yarnpkg.com/@phosphor/messaging/-/messaging-1.2.2.tgz#7d896ddd3797b94a347708ded13da5783db75c14" 415 | dependencies: 416 | "@phosphor/algorithm" "^1.1.2" 417 | "@phosphor/collections" "^1.1.2" 418 | 419 | "@phosphor/properties@^1.1.2": 420 | version "1.1.2" 421 | resolved "https://registry.yarnpkg.com/@phosphor/properties/-/properties-1.1.2.tgz#78cc77eff452839da02255de48e814946cc09a28" 422 | 423 | "@phosphor/signaling@^1.2.2": 424 | version "1.2.2" 425 | resolved "https://registry.yarnpkg.com/@phosphor/signaling/-/signaling-1.2.2.tgz#3fcf97ca88e38bfb357fe8fe6bf7513347a514a9" 426 | dependencies: 427 | "@phosphor/algorithm" "^1.1.2" 428 | 429 | "@phosphor/virtualdom@^1.1.2": 430 | version "1.1.2" 431 | resolved "https://registry.yarnpkg.com/@phosphor/virtualdom/-/virtualdom-1.1.2.tgz#ce55c86eef31e5d0e26b1dc96ea32bd684458f41" 432 | dependencies: 433 | "@phosphor/algorithm" "^1.1.2" 434 | 435 | "@phosphor/widgets@^1.6.0": 436 | version "1.6.0" 437 | resolved "https://registry.yarnpkg.com/@phosphor/widgets/-/widgets-1.6.0.tgz#ebba8008b6b13247d03e73e5f3872c90d2c9c78f" 438 | dependencies: 439 | "@phosphor/algorithm" "^1.1.2" 440 | "@phosphor/commands" "^1.5.0" 441 | "@phosphor/coreutils" "^1.3.0" 442 | "@phosphor/disposable" "^1.1.2" 443 | "@phosphor/domutils" "^1.1.2" 444 | "@phosphor/dragdrop" "^1.3.0" 445 | "@phosphor/keyboard" "^1.1.2" 446 | "@phosphor/messaging" "^1.2.2" 447 | "@phosphor/properties" "^1.1.2" 448 | "@phosphor/signaling" "^1.2.2" 449 | "@phosphor/virtualdom" "^1.1.2" 450 | 451 | "@samverschueren/stream-to-observable@^0.3.0": 452 | version "0.3.0" 453 | resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" 454 | dependencies: 455 | any-observable "^0.3.0" 456 | 457 | "@types/dom4@^2.0.0": 458 | version "2.0.1" 459 | resolved "https://registry.yarnpkg.com/@types/dom4/-/dom4-2.0.1.tgz#506d5781b9bcab81bd9a878b198aec7dee2a6033" 460 | 461 | "@types/node@*": 462 | version "10.11.4" 463 | resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.4.tgz#e8bd933c3f78795d580ae41d86590bfc1f4f389d" 464 | 465 | "@types/prop-types@*": 466 | version "15.5.6" 467 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.6.tgz#9c03d3fed70a8d517c191b7734da2879b50ca26c" 468 | 469 | "@types/react-dom@~16.0.5": 470 | version "16.0.8" 471 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.8.tgz#6e1366ed629cadf55860cbfcc25db533f5d2fa7d" 472 | dependencies: 473 | "@types/node" "*" 474 | "@types/react" "*" 475 | 476 | "@types/react@*", "@types/react@~16.4.13", "@types/react@~16.8.8": 477 | version "16.4.15" 478 | resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.15.tgz#1f24f1d03b1fc682d92f8485be99d59bf7981191" 479 | dependencies: 480 | "@types/prop-types" "*" 481 | csstype "^2.2.0" 482 | 483 | ajv@^6.5.5: 484 | version "6.8.1" 485 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.8.1.tgz#0890b93742985ebf8973cd365c5b23920ce3cb20" 486 | dependencies: 487 | fast-deep-equal "^2.0.1" 488 | fast-json-stable-stringify "^2.0.0" 489 | json-schema-traverse "^0.4.1" 490 | uri-js "^4.2.2" 491 | 492 | ansi-escapes@^1.0.0: 493 | version "1.4.0" 494 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 495 | 496 | ansi-regex@^2.0.0: 497 | version "2.1.1" 498 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 499 | 500 | ansi-regex@^3.0.0: 501 | version "3.0.0" 502 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 503 | 504 | ansi-styles@^2.2.1: 505 | version "2.2.1" 506 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 507 | 508 | ansi-styles@^3.2.0, ansi-styles@^3.2.1: 509 | version "3.2.1" 510 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 511 | dependencies: 512 | color-convert "^1.9.0" 513 | 514 | any-observable@^0.3.0: 515 | version "0.3.0" 516 | resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" 517 | 518 | argparse@^1.0.7: 519 | version "1.0.10" 520 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 521 | dependencies: 522 | sprintf-js "~1.0.2" 523 | 524 | arr-diff@^4.0.0: 525 | version "4.0.0" 526 | resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" 527 | 528 | arr-flatten@^1.1.0: 529 | version "1.1.0" 530 | resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" 531 | 532 | arr-union@^3.1.0: 533 | version "3.1.0" 534 | resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" 535 | 536 | array-uniq@^1.0.2: 537 | version "1.0.3" 538 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 539 | 540 | array-unique@^0.3.2: 541 | version "0.3.2" 542 | resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" 543 | 544 | asap@~2.0.3: 545 | version "2.0.6" 546 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 547 | 548 | assign-symbols@^1.0.0: 549 | version "1.0.0" 550 | resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" 551 | 552 | async-limiter@~1.0.0: 553 | version "1.0.0" 554 | resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" 555 | 556 | atob@^2.1.1: 557 | version "2.1.2" 558 | resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" 559 | 560 | babel-code-frame@^6.22.0: 561 | version "6.26.0" 562 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 563 | dependencies: 564 | chalk "^1.1.3" 565 | esutils "^2.0.2" 566 | js-tokens "^3.0.2" 567 | 568 | balanced-match@^1.0.0: 569 | version "1.0.0" 570 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 571 | 572 | base@^0.11.1: 573 | version "0.11.2" 574 | resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" 575 | dependencies: 576 | cache-base "^1.0.1" 577 | class-utils "^0.3.5" 578 | component-emitter "^1.2.1" 579 | define-property "^1.0.0" 580 | isobject "^3.0.1" 581 | mixin-deep "^1.2.0" 582 | pascalcase "^0.1.1" 583 | 584 | brace-expansion@^1.1.7: 585 | version "1.1.11" 586 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 587 | dependencies: 588 | balanced-match "^1.0.0" 589 | concat-map "0.0.1" 590 | 591 | braces@^2.3.1: 592 | version "2.3.2" 593 | resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" 594 | dependencies: 595 | arr-flatten "^1.1.0" 596 | array-unique "^0.3.2" 597 | extend-shallow "^2.0.1" 598 | fill-range "^4.0.0" 599 | isobject "^3.0.1" 600 | repeat-element "^1.1.2" 601 | snapdragon "^0.8.1" 602 | snapdragon-node "^2.0.1" 603 | split-string "^3.0.2" 604 | to-regex "^3.0.1" 605 | 606 | builtin-modules@^1.1.1: 607 | version "1.1.1" 608 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 609 | 610 | cache-base@^1.0.1: 611 | version "1.0.1" 612 | resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" 613 | dependencies: 614 | collection-visit "^1.0.0" 615 | component-emitter "^1.2.1" 616 | get-value "^2.0.6" 617 | has-value "^1.0.0" 618 | isobject "^3.0.1" 619 | set-value "^2.0.0" 620 | to-object-path "^0.3.0" 621 | union-value "^1.0.0" 622 | unset-value "^1.0.0" 623 | 624 | chalk@^1.0.0, chalk@^1.1.3: 625 | version "1.1.3" 626 | resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 627 | dependencies: 628 | ansi-styles "^2.2.1" 629 | escape-string-regexp "^1.0.2" 630 | has-ansi "^2.0.0" 631 | strip-ansi "^3.0.0" 632 | supports-color "^2.0.0" 633 | 634 | chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1: 635 | version "2.4.1" 636 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" 637 | dependencies: 638 | ansi-styles "^3.2.1" 639 | escape-string-regexp "^1.0.5" 640 | supports-color "^5.3.0" 641 | 642 | ci-info@^1.5.0: 643 | version "1.6.0" 644 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" 645 | 646 | class-utils@^0.3.5: 647 | version "0.3.6" 648 | resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" 649 | dependencies: 650 | arr-union "^3.1.0" 651 | define-property "^0.2.5" 652 | isobject "^3.0.0" 653 | static-extend "^0.1.1" 654 | 655 | classnames@^2.2: 656 | version "2.2.6" 657 | resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" 658 | 659 | cli-cursor@^1.0.2: 660 | version "1.0.2" 661 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 662 | dependencies: 663 | restore-cursor "^1.0.1" 664 | 665 | cli-truncate@^0.2.1: 666 | version "0.2.1" 667 | resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" 668 | dependencies: 669 | slice-ansi "0.0.4" 670 | string-width "^1.0.1" 671 | 672 | code-point-at@^1.0.0: 673 | version "1.1.0" 674 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 675 | 676 | codemirror@~5.42.0: 677 | version "5.42.2" 678 | resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.42.2.tgz#801ab715a7a7e1c7ed4162b78e9d8138b98de8f0" 679 | 680 | collection-visit@^1.0.0: 681 | version "1.0.0" 682 | resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" 683 | dependencies: 684 | map-visit "^1.0.0" 685 | object-visit "^1.0.0" 686 | 687 | color-convert@^1.9.0: 688 | version "1.9.3" 689 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 690 | dependencies: 691 | color-name "1.1.3" 692 | 693 | color-name@1.1.3: 694 | version "1.1.3" 695 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 696 | 697 | commander@^2.12.1, commander@^2.14.1, commander@^2.9.0: 698 | version "2.18.0" 699 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" 700 | 701 | comment-json@^1.1.3: 702 | version "1.1.3" 703 | resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-1.1.3.tgz#6986c3330fee0c4c9e00c2398cd61afa5d8f239e" 704 | dependencies: 705 | json-parser "^1.0.0" 706 | 707 | component-emitter@^1.2.1: 708 | version "1.2.1" 709 | resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" 710 | 711 | concat-map@0.0.1: 712 | version "0.0.1" 713 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 714 | 715 | copy-descriptor@^0.1.0: 716 | version "0.1.1" 717 | resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" 718 | 719 | core-js@^1.0.0: 720 | version "1.2.7" 721 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" 722 | 723 | core-util-is@~1.0.0: 724 | version "1.0.2" 725 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 726 | 727 | cosmiconfig@^5.0.2: 728 | version "5.0.6" 729 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" 730 | dependencies: 731 | is-directory "^0.3.1" 732 | js-yaml "^3.9.0" 733 | parse-json "^4.0.0" 734 | 735 | create-react-context@<=0.2.2: 736 | version "0.2.2" 737 | resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.2.tgz#9836542f9aaa22868cd7d4a6f82667df38019dca" 738 | dependencies: 739 | fbjs "^0.8.0" 740 | gud "^1.0.0" 741 | 742 | cross-spawn@^5.0.1: 743 | version "5.1.0" 744 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 745 | dependencies: 746 | lru-cache "^4.0.1" 747 | shebang-command "^1.2.0" 748 | which "^1.2.9" 749 | 750 | csstype@^2.2.0: 751 | version "2.5.7" 752 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.7.tgz#bf9235d5872141eccfb2d16d82993c6b149179ff" 753 | 754 | csstype@^2.4.0: 755 | version "2.6.2" 756 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.2.tgz#3043d5e065454579afc7478a18de41909c8a2f01" 757 | 758 | date-fns@^1.27.2: 759 | version "1.29.0" 760 | resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" 761 | 762 | debug@^2.2.0, debug@^2.3.3: 763 | version "2.6.9" 764 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 765 | dependencies: 766 | ms "2.0.0" 767 | 768 | debug@^3.1.0: 769 | version "3.2.5" 770 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.5.tgz#c2418fbfd7a29f4d4f70ff4cea604d4b64c46407" 771 | dependencies: 772 | ms "^2.1.1" 773 | 774 | decode-uri-component@^0.2.0: 775 | version "0.2.0" 776 | resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" 777 | 778 | dedent@^0.7.0: 779 | version "0.7.0" 780 | resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" 781 | 782 | define-property@^0.2.5: 783 | version "0.2.5" 784 | resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" 785 | dependencies: 786 | is-descriptor "^0.1.0" 787 | 788 | define-property@^1.0.0: 789 | version "1.0.0" 790 | resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" 791 | dependencies: 792 | is-descriptor "^1.0.0" 793 | 794 | define-property@^2.0.2: 795 | version "2.0.2" 796 | resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" 797 | dependencies: 798 | is-descriptor "^1.0.2" 799 | isobject "^3.0.1" 800 | 801 | diff@^3.2.0: 802 | version "3.5.0" 803 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 804 | 805 | dom-helpers@^3.3.1: 806 | version "3.4.0" 807 | resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" 808 | dependencies: 809 | "@babel/runtime" "^7.1.2" 810 | 811 | dom-serializer@0: 812 | version "0.1.0" 813 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" 814 | dependencies: 815 | domelementtype "~1.1.1" 816 | entities "~1.1.1" 817 | 818 | dom4@^2.0.1: 819 | version "2.1.4" 820 | resolved "https://registry.yarnpkg.com/dom4/-/dom4-2.1.4.tgz#400a42cba4719a3e2eced93eff7738831d2746f6" 821 | 822 | domelementtype@1, domelementtype@^1.3.0: 823 | version "1.3.0" 824 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" 825 | 826 | domelementtype@~1.1.1: 827 | version "1.1.3" 828 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" 829 | 830 | domhandler@^2.3.0: 831 | version "2.4.2" 832 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" 833 | dependencies: 834 | domelementtype "1" 835 | 836 | domutils@^1.5.1: 837 | version "1.7.0" 838 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" 839 | dependencies: 840 | dom-serializer "0" 841 | domelementtype "1" 842 | 843 | elegant-spinner@^1.0.1: 844 | version "1.0.1" 845 | resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" 846 | 847 | encoding@^0.1.11: 848 | version "0.1.12" 849 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 850 | dependencies: 851 | iconv-lite "~0.4.13" 852 | 853 | entities@^1.1.1, entities@~1.1.1: 854 | version "1.1.1" 855 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" 856 | 857 | error-ex@^1.3.1: 858 | version "1.3.2" 859 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 860 | dependencies: 861 | is-arrayish "^0.2.1" 862 | 863 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 864 | version "1.0.5" 865 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 866 | 867 | eslint-plugin-prettier@^2.2.0: 868 | version "2.7.0" 869 | resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz#b4312dcf2c1d965379d7f9d5b5f8aaadc6a45904" 870 | dependencies: 871 | fast-diff "^1.1.1" 872 | jest-docblock "^21.0.0" 873 | 874 | esprima@^2.7.0: 875 | version "2.7.3" 876 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" 877 | 878 | esprima@^4.0.0: 879 | version "4.0.1" 880 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 881 | 882 | esutils@^2.0.2: 883 | version "2.0.2" 884 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 885 | 886 | execa@^0.9.0: 887 | version "0.9.0" 888 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01" 889 | dependencies: 890 | cross-spawn "^5.0.1" 891 | get-stream "^3.0.0" 892 | is-stream "^1.1.0" 893 | npm-run-path "^2.0.0" 894 | p-finally "^1.0.0" 895 | signal-exit "^3.0.0" 896 | strip-eof "^1.0.0" 897 | 898 | exit-hook@^1.0.0: 899 | version "1.1.1" 900 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 901 | 902 | expand-brackets@^2.1.4: 903 | version "2.1.4" 904 | resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" 905 | dependencies: 906 | debug "^2.3.3" 907 | define-property "^0.2.5" 908 | extend-shallow "^2.0.1" 909 | posix-character-classes "^0.1.0" 910 | regex-not "^1.0.0" 911 | snapdragon "^0.8.1" 912 | to-regex "^3.0.1" 913 | 914 | extend-shallow@^2.0.1: 915 | version "2.0.1" 916 | resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" 917 | dependencies: 918 | is-extendable "^0.1.0" 919 | 920 | extend-shallow@^3.0.0, extend-shallow@^3.0.2: 921 | version "3.0.2" 922 | resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" 923 | dependencies: 924 | assign-symbols "^1.0.0" 925 | is-extendable "^1.0.1" 926 | 927 | extglob@^2.0.4: 928 | version "2.0.4" 929 | resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" 930 | dependencies: 931 | array-unique "^0.3.2" 932 | define-property "^1.0.0" 933 | expand-brackets "^2.1.4" 934 | extend-shallow "^2.0.1" 935 | fragment-cache "^0.2.1" 936 | regex-not "^1.0.0" 937 | snapdragon "^0.8.1" 938 | to-regex "^3.0.1" 939 | 940 | fast-deep-equal@^2.0.1: 941 | version "2.0.1" 942 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 943 | 944 | fast-diff@^1.1.1: 945 | version "1.1.2" 946 | resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" 947 | 948 | fast-json-stable-stringify@^2.0.0: 949 | version "2.0.0" 950 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 951 | 952 | fbjs@^0.8.0, fbjs@^0.8.16: 953 | version "0.8.17" 954 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" 955 | dependencies: 956 | core-js "^1.0.0" 957 | isomorphic-fetch "^2.1.1" 958 | loose-envify "^1.0.0" 959 | object-assign "^4.1.0" 960 | promise "^7.1.1" 961 | setimmediate "^1.0.5" 962 | ua-parser-js "^0.7.18" 963 | 964 | figures@^1.7.0: 965 | version "1.7.0" 966 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 967 | dependencies: 968 | escape-string-regexp "^1.0.5" 969 | object-assign "^4.1.0" 970 | 971 | fill-range@^4.0.0: 972 | version "4.0.0" 973 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" 974 | dependencies: 975 | extend-shallow "^2.0.1" 976 | is-number "^3.0.0" 977 | repeat-string "^1.6.1" 978 | to-regex-range "^2.1.0" 979 | 980 | find-parent-dir@^0.3.0: 981 | version "0.3.0" 982 | resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" 983 | 984 | font-awesome@~4.7.0: 985 | version "4.7.0" 986 | resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" 987 | 988 | for-in@^1.0.2: 989 | version "1.0.2" 990 | resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" 991 | 992 | fragment-cache@^0.2.1: 993 | version "0.2.1" 994 | resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" 995 | dependencies: 996 | map-cache "^0.2.2" 997 | 998 | free-style@2.5.1: 999 | version "2.5.1" 1000 | resolved "https://registry.yarnpkg.com/free-style/-/free-style-2.5.1.tgz#5e3f684c470d3bba7e4dbb43524e0a08917e873c" 1001 | 1002 | fs.realpath@^1.0.0: 1003 | version "1.0.0" 1004 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 1005 | 1006 | get-own-enumerable-property-symbols@^2.0.1: 1007 | version "2.0.1" 1008 | resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" 1009 | 1010 | get-stream@^3.0.0: 1011 | version "3.0.0" 1012 | resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 1013 | 1014 | get-value@^2.0.3, get-value@^2.0.6: 1015 | version "2.0.6" 1016 | resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" 1017 | 1018 | glob@^7.0.5, glob@^7.1.1: 1019 | version "7.1.3" 1020 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 1021 | dependencies: 1022 | fs.realpath "^1.0.0" 1023 | inflight "^1.0.4" 1024 | inherits "2" 1025 | minimatch "^3.0.4" 1026 | once "^1.3.0" 1027 | path-is-absolute "^1.0.0" 1028 | 1029 | gud@^1.0.0: 1030 | version "1.0.0" 1031 | resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" 1032 | 1033 | has-ansi@^2.0.0: 1034 | version "2.0.0" 1035 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 1036 | dependencies: 1037 | ansi-regex "^2.0.0" 1038 | 1039 | has-flag@^3.0.0: 1040 | version "3.0.0" 1041 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 1042 | 1043 | has-value@^0.3.1: 1044 | version "0.3.1" 1045 | resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" 1046 | dependencies: 1047 | get-value "^2.0.3" 1048 | has-values "^0.1.4" 1049 | isobject "^2.0.0" 1050 | 1051 | has-value@^1.0.0: 1052 | version "1.0.0" 1053 | resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" 1054 | dependencies: 1055 | get-value "^2.0.6" 1056 | has-values "^1.0.0" 1057 | isobject "^3.0.0" 1058 | 1059 | has-values@^0.1.4: 1060 | version "0.1.4" 1061 | resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" 1062 | 1063 | has-values@^1.0.0: 1064 | version "1.0.0" 1065 | resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" 1066 | dependencies: 1067 | is-number "^3.0.0" 1068 | kind-of "^4.0.0" 1069 | 1070 | htmlparser2@^3.9.0: 1071 | version "3.9.2" 1072 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" 1073 | dependencies: 1074 | domelementtype "^1.3.0" 1075 | domhandler "^2.3.0" 1076 | domutils "^1.5.1" 1077 | entities "^1.1.1" 1078 | inherits "^2.0.1" 1079 | readable-stream "^2.0.2" 1080 | 1081 | husky@^0.14.3: 1082 | version "0.14.3" 1083 | resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" 1084 | dependencies: 1085 | is-ci "^1.0.10" 1086 | normalize-path "^1.0.0" 1087 | strip-indent "^2.0.0" 1088 | 1089 | iconv-lite@~0.4.13: 1090 | version "0.4.24" 1091 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 1092 | dependencies: 1093 | safer-buffer ">= 2.1.2 < 3" 1094 | 1095 | indent-string@^3.0.0: 1096 | version "3.2.0" 1097 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" 1098 | 1099 | inflight@^1.0.4: 1100 | version "1.0.6" 1101 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 1102 | dependencies: 1103 | once "^1.3.0" 1104 | wrappy "1" 1105 | 1106 | inherits@2, inherits@^2.0.1, inherits@~2.0.3: 1107 | version "2.0.3" 1108 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 1109 | 1110 | is-accessor-descriptor@^0.1.6: 1111 | version "0.1.6" 1112 | resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" 1113 | dependencies: 1114 | kind-of "^3.0.2" 1115 | 1116 | is-accessor-descriptor@^1.0.0: 1117 | version "1.0.0" 1118 | resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" 1119 | dependencies: 1120 | kind-of "^6.0.0" 1121 | 1122 | is-arrayish@^0.2.1: 1123 | version "0.2.1" 1124 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 1125 | 1126 | is-buffer@^1.1.5: 1127 | version "1.1.6" 1128 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 1129 | 1130 | is-ci@^1.0.10: 1131 | version "1.2.1" 1132 | resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" 1133 | dependencies: 1134 | ci-info "^1.5.0" 1135 | 1136 | is-data-descriptor@^0.1.4: 1137 | version "0.1.4" 1138 | resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" 1139 | dependencies: 1140 | kind-of "^3.0.2" 1141 | 1142 | is-data-descriptor@^1.0.0: 1143 | version "1.0.0" 1144 | resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" 1145 | dependencies: 1146 | kind-of "^6.0.0" 1147 | 1148 | is-descriptor@^0.1.0: 1149 | version "0.1.6" 1150 | resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" 1151 | dependencies: 1152 | is-accessor-descriptor "^0.1.6" 1153 | is-data-descriptor "^0.1.4" 1154 | kind-of "^5.0.0" 1155 | 1156 | is-descriptor@^1.0.0, is-descriptor@^1.0.2: 1157 | version "1.0.2" 1158 | resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" 1159 | dependencies: 1160 | is-accessor-descriptor "^1.0.0" 1161 | is-data-descriptor "^1.0.0" 1162 | kind-of "^6.0.2" 1163 | 1164 | is-directory@^0.3.1: 1165 | version "0.3.1" 1166 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 1167 | 1168 | is-extendable@^0.1.0, is-extendable@^0.1.1: 1169 | version "0.1.1" 1170 | resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" 1171 | 1172 | is-extendable@^1.0.1: 1173 | version "1.0.1" 1174 | resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" 1175 | dependencies: 1176 | is-plain-object "^2.0.4" 1177 | 1178 | is-extglob@^2.1.1: 1179 | version "2.1.1" 1180 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 1181 | 1182 | is-fullwidth-code-point@^1.0.0: 1183 | version "1.0.0" 1184 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 1185 | dependencies: 1186 | number-is-nan "^1.0.0" 1187 | 1188 | is-glob@^4.0.0: 1189 | version "4.0.0" 1190 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" 1191 | dependencies: 1192 | is-extglob "^2.1.1" 1193 | 1194 | is-number@^3.0.0: 1195 | version "3.0.0" 1196 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" 1197 | dependencies: 1198 | kind-of "^3.0.2" 1199 | 1200 | is-obj@^1.0.1: 1201 | version "1.0.1" 1202 | resolved "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 1203 | 1204 | is-observable@^1.1.0: 1205 | version "1.1.0" 1206 | resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" 1207 | dependencies: 1208 | symbol-observable "^1.1.0" 1209 | 1210 | is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: 1211 | version "2.0.4" 1212 | resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" 1213 | dependencies: 1214 | isobject "^3.0.1" 1215 | 1216 | is-promise@^2.1.0: 1217 | version "2.1.0" 1218 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 1219 | 1220 | is-regexp@^1.0.0: 1221 | version "1.0.0" 1222 | resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" 1223 | 1224 | is-stream@^1.0.1, is-stream@^1.1.0: 1225 | version "1.1.0" 1226 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 1227 | 1228 | is-windows@^1.0.2: 1229 | version "1.0.2" 1230 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" 1231 | 1232 | isarray@1.0.0, isarray@~1.0.0: 1233 | version "1.0.0" 1234 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 1235 | 1236 | isexe@^2.0.0: 1237 | version "2.0.0" 1238 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 1239 | 1240 | isobject@^2.0.0: 1241 | version "2.1.0" 1242 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" 1243 | dependencies: 1244 | isarray "1.0.0" 1245 | 1246 | isobject@^3.0.0, isobject@^3.0.1: 1247 | version "3.0.1" 1248 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" 1249 | 1250 | isomorphic-fetch@^2.1.1: 1251 | version "2.2.1" 1252 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 1253 | dependencies: 1254 | node-fetch "^1.0.1" 1255 | whatwg-fetch ">=0.10.0" 1256 | 1257 | jest-docblock@^21.0.0: 1258 | version "21.2.0" 1259 | resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" 1260 | 1261 | jest-get-type@^22.1.0: 1262 | version "22.4.3" 1263 | resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" 1264 | 1265 | jest-validate@^23.5.0: 1266 | version "23.6.0" 1267 | resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" 1268 | dependencies: 1269 | chalk "^2.0.1" 1270 | jest-get-type "^22.1.0" 1271 | leven "^2.1.0" 1272 | pretty-format "^23.6.0" 1273 | 1274 | "js-tokens@^3.0.0 || ^4.0.0": 1275 | version "4.0.0" 1276 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 1277 | 1278 | js-tokens@^3.0.2: 1279 | version "3.0.2" 1280 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 1281 | 1282 | js-yaml@^3.7.0, js-yaml@^3.9.0: 1283 | version "3.12.0" 1284 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" 1285 | dependencies: 1286 | argparse "^1.0.7" 1287 | esprima "^4.0.0" 1288 | 1289 | json-parse-better-errors@^1.0.1: 1290 | version "1.0.2" 1291 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 1292 | 1293 | json-parser@^1.0.0: 1294 | version "1.1.5" 1295 | resolved "https://registry.yarnpkg.com/json-parser/-/json-parser-1.1.5.tgz#e62ec5261d1a6a5fc20e812a320740c6d9005677" 1296 | dependencies: 1297 | esprima "^2.7.0" 1298 | 1299 | json-schema-traverse@^0.4.1: 1300 | version "0.4.1" 1301 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 1302 | 1303 | kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: 1304 | version "3.2.2" 1305 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 1306 | dependencies: 1307 | is-buffer "^1.1.5" 1308 | 1309 | kind-of@^4.0.0: 1310 | version "4.0.0" 1311 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" 1312 | dependencies: 1313 | is-buffer "^1.1.5" 1314 | 1315 | kind-of@^5.0.0: 1316 | version "5.1.0" 1317 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" 1318 | 1319 | kind-of@^6.0.0, kind-of@^6.0.2: 1320 | version "6.0.2" 1321 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" 1322 | 1323 | leven@^2.1.0: 1324 | version "2.1.0" 1325 | resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" 1326 | 1327 | lint-staged@^7.2.0: 1328 | version "7.3.0" 1329 | resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-7.3.0.tgz#90ff33e5ca61ed3dbac35b6f6502dbefdc0db58d" 1330 | dependencies: 1331 | chalk "^2.3.1" 1332 | commander "^2.14.1" 1333 | cosmiconfig "^5.0.2" 1334 | debug "^3.1.0" 1335 | dedent "^0.7.0" 1336 | execa "^0.9.0" 1337 | find-parent-dir "^0.3.0" 1338 | is-glob "^4.0.0" 1339 | is-windows "^1.0.2" 1340 | jest-validate "^23.5.0" 1341 | listr "^0.14.1" 1342 | lodash "^4.17.5" 1343 | log-symbols "^2.2.0" 1344 | micromatch "^3.1.8" 1345 | npm-which "^3.0.1" 1346 | p-map "^1.1.1" 1347 | path-is-inside "^1.0.2" 1348 | pify "^3.0.0" 1349 | please-upgrade-node "^3.0.2" 1350 | staged-git-files "1.1.1" 1351 | string-argv "^0.0.2" 1352 | stringify-object "^3.2.2" 1353 | 1354 | listr-silent-renderer@^1.1.1: 1355 | version "1.1.1" 1356 | resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" 1357 | 1358 | listr-update-renderer@^0.4.0: 1359 | version "0.4.0" 1360 | resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7" 1361 | dependencies: 1362 | chalk "^1.1.3" 1363 | cli-truncate "^0.2.1" 1364 | elegant-spinner "^1.0.1" 1365 | figures "^1.7.0" 1366 | indent-string "^3.0.0" 1367 | log-symbols "^1.0.2" 1368 | log-update "^1.0.2" 1369 | strip-ansi "^3.0.1" 1370 | 1371 | listr-verbose-renderer@^0.4.0: 1372 | version "0.4.1" 1373 | resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" 1374 | dependencies: 1375 | chalk "^1.1.3" 1376 | cli-cursor "^1.0.2" 1377 | date-fns "^1.27.2" 1378 | figures "^1.7.0" 1379 | 1380 | listr@^0.14.1: 1381 | version "0.14.2" 1382 | resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.2.tgz#cbe44b021100a15376addfc2d79349ee430bfe14" 1383 | dependencies: 1384 | "@samverschueren/stream-to-observable" "^0.3.0" 1385 | is-observable "^1.1.0" 1386 | is-promise "^2.1.0" 1387 | is-stream "^1.1.0" 1388 | listr-silent-renderer "^1.1.1" 1389 | listr-update-renderer "^0.4.0" 1390 | listr-verbose-renderer "^0.4.0" 1391 | p-map "^1.1.1" 1392 | rxjs "^6.1.0" 1393 | 1394 | lodash.clonedeep@^4.5.0: 1395 | version "4.5.0" 1396 | resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" 1397 | 1398 | lodash.escape@^4.0.1: 1399 | version "4.0.1" 1400 | resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" 1401 | 1402 | lodash.escaperegexp@^4.1.2: 1403 | version "4.1.2" 1404 | resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" 1405 | 1406 | lodash.isplainobject@^4.0.6: 1407 | version "4.0.6" 1408 | resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" 1409 | 1410 | lodash.isstring@^4.0.1: 1411 | version "4.0.1" 1412 | resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" 1413 | 1414 | lodash.mergewith@^4.6.0: 1415 | version "4.6.1" 1416 | resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" 1417 | 1418 | lodash@^4.17.5: 1419 | version "4.17.11" 1420 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" 1421 | 1422 | log-symbols@^1.0.2: 1423 | version "1.0.2" 1424 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" 1425 | dependencies: 1426 | chalk "^1.0.0" 1427 | 1428 | log-symbols@^2.2.0: 1429 | version "2.2.0" 1430 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" 1431 | dependencies: 1432 | chalk "^2.0.1" 1433 | 1434 | log-update@^1.0.2: 1435 | version "1.0.2" 1436 | resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" 1437 | dependencies: 1438 | ansi-escapes "^1.0.0" 1439 | cli-cursor "^1.0.2" 1440 | 1441 | loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: 1442 | version "1.4.0" 1443 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 1444 | dependencies: 1445 | js-tokens "^3.0.0 || ^4.0.0" 1446 | 1447 | lru-cache@^4.0.1: 1448 | version "4.1.3" 1449 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" 1450 | dependencies: 1451 | pseudomap "^1.0.2" 1452 | yallist "^2.1.2" 1453 | 1454 | map-cache@^0.2.2: 1455 | version "0.2.2" 1456 | resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" 1457 | 1458 | map-visit@^1.0.0: 1459 | version "1.0.0" 1460 | resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" 1461 | dependencies: 1462 | object-visit "^1.0.0" 1463 | 1464 | marked@0.5.1: 1465 | version "0.5.1" 1466 | resolved "https://registry.yarnpkg.com/marked/-/marked-0.5.1.tgz#062f43b88b02ee80901e8e8d8e6a620ddb3aa752" 1467 | 1468 | micromatch@^3.1.8: 1469 | version "3.1.10" 1470 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" 1471 | dependencies: 1472 | arr-diff "^4.0.0" 1473 | array-unique "^0.3.2" 1474 | braces "^2.3.1" 1475 | define-property "^2.0.2" 1476 | extend-shallow "^3.0.2" 1477 | extglob "^2.0.4" 1478 | fragment-cache "^0.2.1" 1479 | kind-of "^6.0.2" 1480 | nanomatch "^1.2.9" 1481 | object.pick "^1.3.0" 1482 | regex-not "^1.0.0" 1483 | snapdragon "^0.8.1" 1484 | to-regex "^3.0.2" 1485 | 1486 | minimatch@^3.0.4: 1487 | version "3.0.4" 1488 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 1489 | dependencies: 1490 | brace-expansion "^1.1.7" 1491 | 1492 | minimist@~1.2.0: 1493 | version "1.2.0" 1494 | resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 1495 | 1496 | mixin-deep@^1.2.0: 1497 | version "1.3.1" 1498 | resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" 1499 | dependencies: 1500 | for-in "^1.0.2" 1501 | is-extendable "^1.0.1" 1502 | 1503 | moment@~2.21.0: 1504 | version "2.21.0" 1505 | resolved "http://registry.npmjs.org/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" 1506 | 1507 | ms@2.0.0: 1508 | version "2.0.0" 1509 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1510 | 1511 | ms@^2.1.1: 1512 | version "2.1.1" 1513 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" 1514 | 1515 | nanomatch@^1.2.9: 1516 | version "1.2.13" 1517 | resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" 1518 | dependencies: 1519 | arr-diff "^4.0.0" 1520 | array-unique "^0.3.2" 1521 | define-property "^2.0.2" 1522 | extend-shallow "^3.0.2" 1523 | fragment-cache "^0.2.1" 1524 | is-windows "^1.0.2" 1525 | kind-of "^6.0.2" 1526 | object.pick "^1.3.0" 1527 | regex-not "^1.0.0" 1528 | snapdragon "^0.8.1" 1529 | to-regex "^3.0.1" 1530 | 1531 | node-fetch@^1.0.1: 1532 | version "1.7.3" 1533 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" 1534 | dependencies: 1535 | encoding "^0.1.11" 1536 | is-stream "^1.0.1" 1537 | 1538 | node-fetch@~2.2.0: 1539 | version "2.2.1" 1540 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.2.1.tgz#1fe551e0ded6c45b3b3b937d0fb46f76df718d1e" 1541 | 1542 | normalize-path@^1.0.0: 1543 | version "1.0.0" 1544 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" 1545 | 1546 | normalize.css@^8.0.0: 1547 | version "8.0.1" 1548 | resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" 1549 | 1550 | npm-path@^2.0.2: 1551 | version "2.0.4" 1552 | resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" 1553 | dependencies: 1554 | which "^1.2.10" 1555 | 1556 | npm-run-path@^2.0.0: 1557 | version "2.0.2" 1558 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 1559 | dependencies: 1560 | path-key "^2.0.0" 1561 | 1562 | npm-which@^3.0.1: 1563 | version "3.0.1" 1564 | resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" 1565 | dependencies: 1566 | commander "^2.9.0" 1567 | npm-path "^2.0.2" 1568 | which "^1.2.10" 1569 | 1570 | number-is-nan@^1.0.0: 1571 | version "1.0.1" 1572 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 1573 | 1574 | object-assign@^4.1.0, object-assign@^4.1.1: 1575 | version "4.1.1" 1576 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1577 | 1578 | object-copy@^0.1.0: 1579 | version "0.1.0" 1580 | resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" 1581 | dependencies: 1582 | copy-descriptor "^0.1.0" 1583 | define-property "^0.2.5" 1584 | kind-of "^3.0.3" 1585 | 1586 | object-visit@^1.0.0: 1587 | version "1.0.1" 1588 | resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" 1589 | dependencies: 1590 | isobject "^3.0.0" 1591 | 1592 | object.pick@^1.3.0: 1593 | version "1.3.0" 1594 | resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" 1595 | dependencies: 1596 | isobject "^3.0.1" 1597 | 1598 | once@^1.3.0: 1599 | version "1.4.0" 1600 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1601 | dependencies: 1602 | wrappy "1" 1603 | 1604 | onetime@^1.0.0: 1605 | version "1.1.0" 1606 | resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 1607 | 1608 | p-finally@^1.0.0: 1609 | version "1.0.0" 1610 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 1611 | 1612 | p-map@^1.1.1: 1613 | version "1.2.0" 1614 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" 1615 | 1616 | parse-json@^4.0.0: 1617 | version "4.0.0" 1618 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 1619 | dependencies: 1620 | error-ex "^1.3.1" 1621 | json-parse-better-errors "^1.0.1" 1622 | 1623 | pascalcase@^0.1.1: 1624 | version "0.1.1" 1625 | resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" 1626 | 1627 | path-is-absolute@^1.0.0: 1628 | version "1.0.1" 1629 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1630 | 1631 | path-is-inside@^1.0.2: 1632 | version "1.0.2" 1633 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 1634 | 1635 | path-key@^2.0.0: 1636 | version "2.0.1" 1637 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 1638 | 1639 | path-parse@^1.0.5: 1640 | version "1.0.6" 1641 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 1642 | 1643 | path-posix@~1.0.0: 1644 | version "1.0.0" 1645 | resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" 1646 | 1647 | pify@^3.0.0: 1648 | version "3.0.0" 1649 | resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 1650 | 1651 | please-upgrade-node@^3.0.2: 1652 | version "3.1.1" 1653 | resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" 1654 | dependencies: 1655 | semver-compare "^1.0.0" 1656 | 1657 | popper.js@^1.14.1, popper.js@^1.14.4: 1658 | version "1.14.7" 1659 | resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.7.tgz#e31ec06cfac6a97a53280c3e55e4e0c860e7738e" 1660 | 1661 | posix-character-classes@^0.1.0: 1662 | version "0.1.1" 1663 | resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" 1664 | 1665 | postcss@^6.0.14: 1666 | version "6.0.23" 1667 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" 1668 | dependencies: 1669 | chalk "^2.4.1" 1670 | source-map "^0.6.1" 1671 | supports-color "^5.4.0" 1672 | 1673 | prettier@^1.13.7: 1674 | version "1.14.3" 1675 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" 1676 | 1677 | pretty-format@^23.6.0: 1678 | version "23.6.0" 1679 | resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" 1680 | dependencies: 1681 | ansi-regex "^3.0.0" 1682 | ansi-styles "^3.2.0" 1683 | 1684 | process-nextick-args@~2.0.0: 1685 | version "2.0.0" 1686 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" 1687 | 1688 | promise@^7.1.1: 1689 | version "7.3.1" 1690 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" 1691 | dependencies: 1692 | asap "~2.0.3" 1693 | 1694 | prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2: 1695 | version "15.6.2" 1696 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" 1697 | dependencies: 1698 | loose-envify "^1.3.1" 1699 | object-assign "^4.1.1" 1700 | 1701 | pseudomap@^1.0.2: 1702 | version "1.0.2" 1703 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 1704 | 1705 | punycode@^2.1.0: 1706 | version "2.1.1" 1707 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1708 | 1709 | querystringify@^2.0.0: 1710 | version "2.0.0" 1711 | resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.0.0.tgz#fa3ed6e68eb15159457c89b37bc6472833195755" 1712 | 1713 | react-dom@~16.4.2: 1714 | version "16.4.2" 1715 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.2.tgz#4afed569689f2c561d2b8da0b819669c38a0bda4" 1716 | dependencies: 1717 | fbjs "^0.8.16" 1718 | loose-envify "^1.1.0" 1719 | object-assign "^4.1.1" 1720 | prop-types "^15.6.0" 1721 | 1722 | react-dom@~16.8.4: 1723 | version "16.8.6" 1724 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" 1725 | integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== 1726 | dependencies: 1727 | loose-envify "^1.1.0" 1728 | object-assign "^4.1.1" 1729 | prop-types "^15.6.2" 1730 | scheduler "^0.13.6" 1731 | 1732 | react-lifecycles-compat@^3.0.4: 1733 | version "3.0.4" 1734 | resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" 1735 | 1736 | react-popper@^1.0.0: 1737 | version "1.3.3" 1738 | resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.3.tgz#2c6cef7515a991256b4f0536cd4bdcb58a7b6af6" 1739 | dependencies: 1740 | "@babel/runtime" "^7.1.2" 1741 | create-react-context "<=0.2.2" 1742 | popper.js "^1.14.4" 1743 | prop-types "^15.6.1" 1744 | typed-styles "^0.0.7" 1745 | warning "^4.0.2" 1746 | 1747 | react-transition-group@^2.2.1: 1748 | version "2.5.3" 1749 | resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.5.3.tgz#26de363cab19e5c88ae5dbae105c706cf953bb92" 1750 | dependencies: 1751 | dom-helpers "^3.3.1" 1752 | loose-envify "^1.4.0" 1753 | prop-types "^15.6.2" 1754 | react-lifecycles-compat "^3.0.4" 1755 | 1756 | react@~16.4.2: 1757 | version "16.4.2" 1758 | resolved "https://registry.yarnpkg.com/react/-/react-16.4.2.tgz#2cd90154e3a9d9dd8da2991149fdca3c260e129f" 1759 | dependencies: 1760 | fbjs "^0.8.16" 1761 | loose-envify "^1.1.0" 1762 | object-assign "^4.1.1" 1763 | prop-types "^15.6.0" 1764 | 1765 | react@~16.8.4: 1766 | version "16.8.6" 1767 | resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" 1768 | integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== 1769 | dependencies: 1770 | loose-envify "^1.1.0" 1771 | object-assign "^4.1.1" 1772 | prop-types "^15.6.2" 1773 | scheduler "^0.13.6" 1774 | 1775 | readable-stream@^2.0.2: 1776 | version "2.3.6" 1777 | resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" 1778 | dependencies: 1779 | core-util-is "~1.0.0" 1780 | inherits "~2.0.3" 1781 | isarray "~1.0.0" 1782 | process-nextick-args "~2.0.0" 1783 | safe-buffer "~5.1.1" 1784 | string_decoder "~1.1.1" 1785 | util-deprecate "~1.0.1" 1786 | 1787 | regenerator-runtime@^0.12.0: 1788 | version "0.12.1" 1789 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" 1790 | 1791 | regex-not@^1.0.0, regex-not@^1.0.2: 1792 | version "1.0.2" 1793 | resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" 1794 | dependencies: 1795 | extend-shallow "^3.0.2" 1796 | safe-regex "^1.1.0" 1797 | 1798 | repeat-element@^1.1.2: 1799 | version "1.1.3" 1800 | resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" 1801 | 1802 | repeat-string@^1.6.1: 1803 | version "1.6.1" 1804 | resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 1805 | 1806 | requires-port@^1.0.0: 1807 | version "1.0.0" 1808 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1809 | 1810 | resize-observer-polyfill@^1.5.0: 1811 | version "1.5.1" 1812 | resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" 1813 | 1814 | resolve-url@^0.2.1: 1815 | version "0.2.1" 1816 | resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" 1817 | 1818 | resolve@^1.3.2: 1819 | version "1.8.1" 1820 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" 1821 | dependencies: 1822 | path-parse "^1.0.5" 1823 | 1824 | restore-cursor@^1.0.1: 1825 | version "1.0.1" 1826 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 1827 | dependencies: 1828 | exit-hook "^1.0.0" 1829 | onetime "^1.0.0" 1830 | 1831 | ret@~0.1.10: 1832 | version "0.1.15" 1833 | resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" 1834 | 1835 | rimraf@^2.6.1: 1836 | version "2.6.2" 1837 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" 1838 | dependencies: 1839 | glob "^7.0.5" 1840 | 1841 | rxjs@^6.1.0: 1842 | version "6.3.3" 1843 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" 1844 | dependencies: 1845 | tslib "^1.9.0" 1846 | 1847 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1848 | version "5.1.2" 1849 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1850 | 1851 | safe-regex@^1.1.0: 1852 | version "1.1.0" 1853 | resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" 1854 | dependencies: 1855 | ret "~0.1.10" 1856 | 1857 | "safer-buffer@>= 2.1.2 < 3": 1858 | version "2.1.2" 1859 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1860 | 1861 | sanitize-html@~1.18.2: 1862 | version "1.18.5" 1863 | resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.5.tgz#350013d95d17f851ef8b178dfd9ca155acf2d7a0" 1864 | dependencies: 1865 | chalk "^2.3.0" 1866 | htmlparser2 "^3.9.0" 1867 | lodash.clonedeep "^4.5.0" 1868 | lodash.escaperegexp "^4.1.2" 1869 | lodash.isplainobject "^4.0.6" 1870 | lodash.isstring "^4.0.1" 1871 | lodash.mergewith "^4.6.0" 1872 | postcss "^6.0.14" 1873 | srcset "^1.0.0" 1874 | xtend "^4.0.0" 1875 | 1876 | scheduler@^0.13.6: 1877 | version "0.13.6" 1878 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" 1879 | integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== 1880 | dependencies: 1881 | loose-envify "^1.1.0" 1882 | object-assign "^4.1.1" 1883 | 1884 | semver-compare@^1.0.0: 1885 | version "1.0.0" 1886 | resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" 1887 | 1888 | semver@^5.3.0: 1889 | version "5.5.1" 1890 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" 1891 | 1892 | set-value@^0.4.3: 1893 | version "0.4.3" 1894 | resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" 1895 | dependencies: 1896 | extend-shallow "^2.0.1" 1897 | is-extendable "^0.1.1" 1898 | is-plain-object "^2.0.1" 1899 | to-object-path "^0.3.0" 1900 | 1901 | set-value@^2.0.0: 1902 | version "2.0.0" 1903 | resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" 1904 | dependencies: 1905 | extend-shallow "^2.0.1" 1906 | is-extendable "^0.1.1" 1907 | is-plain-object "^2.0.3" 1908 | split-string "^3.0.1" 1909 | 1910 | setimmediate@^1.0.5: 1911 | version "1.0.5" 1912 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 1913 | 1914 | shebang-command@^1.2.0: 1915 | version "1.2.0" 1916 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 1917 | dependencies: 1918 | shebang-regex "^1.0.0" 1919 | 1920 | shebang-regex@^1.0.0: 1921 | version "1.0.0" 1922 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 1923 | 1924 | signal-exit@^3.0.0: 1925 | version "3.0.2" 1926 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 1927 | 1928 | slice-ansi@0.0.4: 1929 | version "0.0.4" 1930 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" 1931 | 1932 | snapdragon-node@^2.0.1: 1933 | version "2.1.1" 1934 | resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" 1935 | dependencies: 1936 | define-property "^1.0.0" 1937 | isobject "^3.0.0" 1938 | snapdragon-util "^3.0.1" 1939 | 1940 | snapdragon-util@^3.0.1: 1941 | version "3.0.1" 1942 | resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" 1943 | dependencies: 1944 | kind-of "^3.2.0" 1945 | 1946 | snapdragon@^0.8.1: 1947 | version "0.8.2" 1948 | resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" 1949 | dependencies: 1950 | base "^0.11.1" 1951 | debug "^2.2.0" 1952 | define-property "^0.2.5" 1953 | extend-shallow "^2.0.1" 1954 | map-cache "^0.2.2" 1955 | source-map "^0.5.6" 1956 | source-map-resolve "^0.5.0" 1957 | use "^3.1.0" 1958 | 1959 | source-map-resolve@^0.5.0: 1960 | version "0.5.2" 1961 | resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" 1962 | dependencies: 1963 | atob "^2.1.1" 1964 | decode-uri-component "^0.2.0" 1965 | resolve-url "^0.2.1" 1966 | source-map-url "^0.4.0" 1967 | urix "^0.1.0" 1968 | 1969 | source-map-url@^0.4.0: 1970 | version "0.4.0" 1971 | resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" 1972 | 1973 | source-map@^0.5.6: 1974 | version "0.5.7" 1975 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1976 | 1977 | source-map@^0.6.1: 1978 | version "0.6.1" 1979 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1980 | 1981 | split-string@^3.0.1, split-string@^3.0.2: 1982 | version "3.1.0" 1983 | resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" 1984 | dependencies: 1985 | extend-shallow "^3.0.0" 1986 | 1987 | sprintf-js@~1.0.2: 1988 | version "1.0.3" 1989 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1990 | 1991 | srcset@^1.0.0: 1992 | version "1.0.0" 1993 | resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef" 1994 | dependencies: 1995 | array-uniq "^1.0.2" 1996 | number-is-nan "^1.0.0" 1997 | 1998 | staged-git-files@1.1.1: 1999 | version "1.1.1" 2000 | resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.1.tgz#37c2218ef0d6d26178b1310719309a16a59f8f7b" 2001 | 2002 | static-extend@^0.1.1: 2003 | version "0.1.2" 2004 | resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" 2005 | dependencies: 2006 | define-property "^0.2.5" 2007 | object-copy "^0.1.0" 2008 | 2009 | string-argv@^0.0.2: 2010 | version "0.0.2" 2011 | resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" 2012 | 2013 | string-width@^1.0.1: 2014 | version "1.0.2" 2015 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 2016 | dependencies: 2017 | code-point-at "^1.0.0" 2018 | is-fullwidth-code-point "^1.0.0" 2019 | strip-ansi "^3.0.0" 2020 | 2021 | string_decoder@~1.1.1: 2022 | version "1.1.1" 2023 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 2024 | dependencies: 2025 | safe-buffer "~5.1.0" 2026 | 2027 | stringify-object@^3.2.2: 2028 | version "3.2.2" 2029 | resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.2.tgz#9853052e5a88fb605a44cd27445aa257ad7ffbcd" 2030 | dependencies: 2031 | get-own-enumerable-property-symbols "^2.0.1" 2032 | is-obj "^1.0.1" 2033 | is-regexp "^1.0.0" 2034 | 2035 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 2036 | version "3.0.1" 2037 | resolved "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 2038 | dependencies: 2039 | ansi-regex "^2.0.0" 2040 | 2041 | strip-eof@^1.0.0: 2042 | version "1.0.0" 2043 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 2044 | 2045 | strip-indent@^2.0.0: 2046 | version "2.0.0" 2047 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" 2048 | 2049 | supports-color@^2.0.0: 2050 | version "2.0.0" 2051 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 2052 | 2053 | supports-color@^5.3.0, supports-color@^5.4.0: 2054 | version "5.5.0" 2055 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 2056 | dependencies: 2057 | has-flag "^3.0.0" 2058 | 2059 | symbol-observable@^1.1.0: 2060 | version "1.2.0" 2061 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" 2062 | 2063 | to-object-path@^0.3.0: 2064 | version "0.3.0" 2065 | resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" 2066 | dependencies: 2067 | kind-of "^3.0.2" 2068 | 2069 | to-regex-range@^2.1.0: 2070 | version "2.1.1" 2071 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" 2072 | dependencies: 2073 | is-number "^3.0.0" 2074 | repeat-string "^1.6.1" 2075 | 2076 | to-regex@^3.0.1, to-regex@^3.0.2: 2077 | version "3.0.2" 2078 | resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" 2079 | dependencies: 2080 | define-property "^2.0.2" 2081 | extend-shallow "^3.0.2" 2082 | regex-not "^1.0.2" 2083 | safe-regex "^1.1.0" 2084 | 2085 | tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: 2086 | version "1.9.3" 2087 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" 2088 | 2089 | tslint-config-prettier@^1.13.0: 2090 | version "1.15.0" 2091 | resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.15.0.tgz#76b9714399004ab6831fdcf76d89b73691c812cf" 2092 | 2093 | tslint-plugin-prettier@^1.3.0: 2094 | version "1.3.0" 2095 | resolved "https://registry.yarnpkg.com/tslint-plugin-prettier/-/tslint-plugin-prettier-1.3.0.tgz#7eb65d19ea786a859501a42491b78c5de2031a3f" 2096 | dependencies: 2097 | eslint-plugin-prettier "^2.2.0" 2098 | tslib "^1.7.1" 2099 | 2100 | tslint@^5.10.0: 2101 | version "5.11.0" 2102 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.11.0.tgz#98f30c02eae3cde7006201e4c33cb08b48581eed" 2103 | dependencies: 2104 | babel-code-frame "^6.22.0" 2105 | builtin-modules "^1.1.1" 2106 | chalk "^2.3.0" 2107 | commander "^2.12.1" 2108 | diff "^3.2.0" 2109 | glob "^7.1.1" 2110 | js-yaml "^3.7.0" 2111 | minimatch "^3.0.4" 2112 | resolve "^1.3.2" 2113 | semver "^5.3.0" 2114 | tslib "^1.8.0" 2115 | tsutils "^2.27.2" 2116 | 2117 | tsutils@^2.27.2: 2118 | version "2.29.0" 2119 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" 2120 | dependencies: 2121 | tslib "^1.8.1" 2122 | 2123 | typed-styles@^0.0.7: 2124 | version "0.0.7" 2125 | resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" 2126 | 2127 | typescript@~3.1.1: 2128 | version "3.1.1" 2129 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96" 2130 | 2131 | typestyle@^2.0.1: 2132 | version "2.0.1" 2133 | resolved "https://registry.yarnpkg.com/typestyle/-/typestyle-2.0.1.tgz#9593e6029ce5f23f1a5728ddd3ed6bf1ffa781f8" 2134 | dependencies: 2135 | csstype "^2.4.0" 2136 | free-style "2.5.1" 2137 | 2138 | ua-parser-js@^0.7.18: 2139 | version "0.7.18" 2140 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" 2141 | 2142 | union-value@^1.0.0: 2143 | version "1.0.0" 2144 | resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" 2145 | dependencies: 2146 | arr-union "^3.1.0" 2147 | get-value "^2.0.6" 2148 | is-extendable "^0.1.1" 2149 | set-value "^0.4.3" 2150 | 2151 | unset-value@^1.0.0: 2152 | version "1.0.0" 2153 | resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" 2154 | dependencies: 2155 | has-value "^0.3.1" 2156 | isobject "^3.0.0" 2157 | 2158 | uri-js@^4.2.2: 2159 | version "4.2.2" 2160 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 2161 | dependencies: 2162 | punycode "^2.1.0" 2163 | 2164 | urix@^0.1.0: 2165 | version "0.1.0" 2166 | resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" 2167 | 2168 | url-parse@~1.4.3: 2169 | version "1.4.3" 2170 | resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.3.tgz#bfaee455c889023219d757e045fa6a684ec36c15" 2171 | dependencies: 2172 | querystringify "^2.0.0" 2173 | requires-port "^1.0.0" 2174 | 2175 | use@^3.1.0: 2176 | version "3.1.1" 2177 | resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" 2178 | 2179 | util-deprecate@~1.0.1: 2180 | version "1.0.2" 2181 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 2182 | 2183 | warning@^4.0.2: 2184 | version "4.0.2" 2185 | resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.2.tgz#aa6876480872116fa3e11d434b0d0d8d91e44607" 2186 | dependencies: 2187 | loose-envify "^1.0.0" 2188 | 2189 | whatwg-fetch@>=0.10.0: 2190 | version "3.0.0" 2191 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" 2192 | 2193 | which@^1.2.10, which@^1.2.9: 2194 | version "1.3.1" 2195 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 2196 | dependencies: 2197 | isexe "^2.0.0" 2198 | 2199 | wrappy@1: 2200 | version "1.0.2" 2201 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 2202 | 2203 | ws@~6.0.0: 2204 | version "6.0.0" 2205 | resolved "https://registry.yarnpkg.com/ws/-/ws-6.0.0.tgz#eaa494aded00ac4289d455bac8d84c7c651cef35" 2206 | dependencies: 2207 | async-limiter "~1.0.0" 2208 | 2209 | xtend@^4.0.0: 2210 | version "4.0.1" 2211 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 2212 | 2213 | yallist@^2.1.2: 2214 | version "2.1.2" 2215 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 2216 | --------------------------------------------------------------------------------