bookish-press 0.4.45 → 0.4.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/.firebaserc +8 -0
- package/.prettierignore +8 -0
- package/.prettierrc.json +5 -0
- package/_update-notifier-last-checked +0 -0
- package/firebase.json +46 -0
- package/firestore.indexes.json +4 -0
- package/firestore.rules +59 -0
- package/functions/.eslintrc.js +28 -0
- package/functions/package-lock.json +12595 -0
- package/functions/package.json +43 -0
- package/functions/src/index.ts +345 -0
- package/functions/tsconfig.dev.json +3 -0
- package/functions/tsconfig.json +15 -0
- package/package.json +53 -270
- package/scripts/claims.cjs +99 -0
- package/src/app.d.ts +9 -0
- package/src/app.html +24 -0
- package/src/lib/components/Auth.svelte +65 -0
- package/{components/Authentication.d.ts → src/lib/components/Authentication.ts} +2 -0
- package/{components → src/lib/components}/BookPreview.svelte +27 -22
- package/{components → src/lib/components}/External.svelte +2 -1
- package/src/lib/components/Link.svelte +58 -0
- package/{components → src/lib/components}/app/BookList.svelte +6 -3
- package/{components → src/lib/components}/app/Button.svelte +5 -4
- package/{components → src/lib/components}/app/Feedback.svelte +11 -7
- package/{components → src/lib/components}/app/Head.svelte +2 -1
- package/{components → src/lib/components}/app/Large.svelte +0 -0
- package/{components → src/lib/components}/app/Lead.svelte +0 -0
- package/{components → src/lib/components}/app/Link.svelte +4 -3
- package/{components → src/lib/components}/app/Options.svelte +5 -4
- package/{components → src/lib/components}/app/Paragraph.svelte +2 -1
- package/{components → src/lib/components}/app/Section.svelte +0 -0
- package/{components → src/lib/components}/app/Table.svelte +0 -0
- package/{components → src/lib/components}/app/TextInput.svelte +12 -9
- package/{components → src/lib/components}/chapter/Atom.svelte +18 -12
- package/src/lib/components/chapter/Block.svelte +42 -0
- package/{components → src/lib/components}/chapter/Callout.svelte +6 -3
- package/{components → src/lib/components}/chapter/CaptionedCode.svelte +21 -13
- package/{components → src/lib/components}/chapter/ChapterBody.svelte +13 -9
- package/{components → src/lib/components}/chapter/Citations.svelte +34 -33
- package/{components → src/lib/components}/chapter/Code.svelte +63 -58
- package/{components → src/lib/components}/chapter/Comment.svelte +30 -18
- package/{components → src/lib/components}/chapter/Definition.svelte +23 -17
- package/{components → src/lib/components}/chapter/Embed.svelte +97 -77
- package/src/lib/components/chapter/ErrorMessage.svelte +12 -0
- package/{components → src/lib/components}/chapter/ExtendedPrism.js +0 -0
- package/{components → src/lib/components}/chapter/Figure.svelte +34 -26
- package/{components → src/lib/components}/chapter/Footnote.svelte +32 -20
- package/{components → src/lib/components}/chapter/Format.svelte +39 -34
- package/{components → src/lib/components}/chapter/InlineCode.svelte +9 -5
- package/{components → src/lib/components}/chapter/Label.svelte +23 -14
- package/{components → src/lib/components}/chapter/Link.svelte +27 -21
- package/{components → src/lib/components}/chapter/List.svelte +5 -3
- package/{components → src/lib/components}/chapter/Marginal.svelte +54 -41
- package/{components → src/lib/components}/chapter/Paragraph.svelte +25 -20
- package/{components → src/lib/components}/chapter/Positioned.svelte +4 -1
- package/{components → src/lib/components}/chapter/Problem.svelte +0 -0
- package/src/lib/components/chapter/Python.svelte +144 -0
- package/{components → src/lib/components}/chapter/Quote.svelte +9 -5
- package/{components → src/lib/components}/chapter/Rule.svelte +4 -1
- package/{components → src/lib/components}/chapter/Table.svelte +11 -7
- package/src/lib/components/chapter/Text.svelte +109 -0
- package/src/lib/components/editor/BookishEditor.svelte +1101 -0
- package/src/lib/components/editor/CalloutEditor.svelte +14 -0
- package/{components → src/lib/components}/editor/CaptionedCodeEditor.svelte +10 -6
- package/src/lib/components/editor/CaretContext.ts +55 -0
- package/{components/editor/CaretState.d.ts → src/lib/components/editor/CaretState.ts} +6 -7
- package/{components/editor/CaretUtilities.d.ts → src/lib/components/editor/CaretUtilities.ts} +1 -0
- package/{components → src/lib/components}/editor/CaretView.svelte +25 -20
- package/src/lib/components/editor/CitationsEditor.svelte +64 -0
- package/{components/editor/Clipboard.d.ts → src/lib/components/editor/Clipboard.ts} +2 -1
- package/{components/editor/Command.d.ts → src/lib/components/editor/Command.ts} +8 -2
- package/{components/editor/Commands.js → src/lib/components/editor/Commands.ts} +730 -315
- package/src/lib/components/editor/ConfirmButton.svelte +51 -0
- package/src/lib/components/editor/DefinitionEditor.svelte +44 -0
- package/src/lib/components/editor/EmbedEditor.svelte +152 -0
- package/{components → src/lib/components}/editor/Icon.svelte +2 -1
- package/{components → src/lib/components}/editor/ImageChooser.svelte +24 -19
- package/src/lib/components/editor/InlineCodeEditor.svelte +16 -0
- package/{components → src/lib/components}/editor/LabelEditor.svelte +14 -9
- package/{components → src/lib/components}/editor/LanguageEditor.svelte +8 -5
- package/src/lib/components/editor/LinkEditor.svelte +110 -0
- package/{components → src/lib/components}/editor/Note.svelte +0 -0
- package/{components → src/lib/components}/editor/Permissions.svelte +43 -36
- package/src/lib/components/editor/PositionEditor.svelte +21 -0
- package/src/lib/components/editor/QuoteEditor.svelte +14 -0
- package/{components → src/lib/components}/editor/Switch.svelte +14 -11
- package/src/lib/components/editor/TableEditor.svelte +14 -0
- package/{components → src/lib/components}/editor/TextEditor.svelte +101 -89
- package/src/lib/components/editor/Toggle.svelte +47 -0
- package/src/lib/components/editor/Toolbar.svelte +297 -0
- package/{components → src/lib/components}/editor/ToolbarGroup.svelte +5 -3
- package/{components → src/lib/components}/editor/ToolbarSpacer.svelte +0 -0
- package/src/lib/components/editor/URLEditor.svelte +15 -0
- package/{components/editor/UndoState.d.ts → src/lib/components/editor/UndoState.ts} +3 -2
- package/{components → src/lib/components}/editor/icons/annotate.svg +0 -0
- package/{components → src/lib/components}/editor/icons/block.svg +0 -0
- package/{components → src/lib/components}/editor/icons/bold.svg +0 -0
- package/{components → src/lib/components}/editor/icons/bullets.svg +0 -0
- package/{components → src/lib/components}/editor/icons/callout.svg +0 -0
- package/{components → src/lib/components}/editor/icons/citation.svg +0 -0
- package/{components → src/lib/components}/editor/icons/clear.svg +0 -0
- package/{components → src/lib/components}/editor/icons/clipboard.svg +0 -0
- package/{components → src/lib/components}/editor/icons/code.svg +0 -0
- package/{components → src/lib/components}/editor/icons/columnafter.svg +0 -0
- package/{components → src/lib/components}/editor/icons/columnbefore.svg +0 -0
- package/{components → src/lib/components}/editor/icons/comment.svg +0 -0
- package/{components → src/lib/components}/editor/icons/copy.svg +0 -0
- package/{components → src/lib/components}/editor/icons/cut.svg +0 -0
- package/{components → src/lib/components}/editor/icons/define.svg +0 -0
- package/{components → src/lib/components}/editor/icons/deletecolumn.svg +0 -0
- package/{components → src/lib/components}/editor/icons/deleterow.svg +0 -0
- package/{components → src/lib/components}/editor/icons/footnote.svg +0 -0
- package/{components → src/lib/components}/editor/icons/header1.svg +0 -0
- package/{components → src/lib/components}/editor/icons/header2.svg +0 -0
- package/{components → src/lib/components}/editor/icons/header3.svg +0 -0
- package/{components → src/lib/components}/editor/icons/home.svg +0 -0
- package/{components → src/lib/components}/editor/icons/indent.svg +0 -0
- package/{components → src/lib/components}/editor/icons/italic.svg +0 -0
- package/{components → src/lib/components}/editor/icons/label.svg +0 -0
- package/{components → src/lib/components}/editor/icons/left.svg +0 -0
- package/{components → src/lib/components}/editor/icons/level.svg +0 -0
- package/{components → src/lib/components}/editor/icons/link.svg +0 -0
- package/{components → src/lib/components}/editor/icons/list.svg +0 -0
- package/{components → src/lib/components}/editor/icons/media.svg +0 -0
- package/{components → src/lib/components}/editor/icons/middle.svg +0 -0
- package/{components → src/lib/components}/editor/icons/numbers.svg +0 -0
- package/{components → src/lib/components}/editor/icons/paragraph.svg +0 -0
- package/{components → src/lib/components}/editor/icons/paste.svg +0 -0
- package/{components → src/lib/components}/editor/icons/quote.svg +0 -0
- package/{components → src/lib/components}/editor/icons/redo.svg +0 -0
- package/{components → src/lib/components}/editor/icons/right.svg +0 -0
- package/{components → src/lib/components}/editor/icons/rowabove.svg +0 -0
- package/{components → src/lib/components}/editor/icons/rowbelow.svg +0 -0
- package/{components → src/lib/components}/editor/icons/rule.svg +0 -0
- package/{components → src/lib/components}/editor/icons/sub.svg +0 -0
- package/{components → src/lib/components}/editor/icons/super.svg +0 -0
- package/{components → src/lib/components}/editor/icons/table.svg +0 -0
- package/{components → src/lib/components}/editor/icons/text.svg +0 -0
- package/{components → src/lib/components}/editor/icons/time.svg +0 -0
- package/{components → src/lib/components}/editor/icons/undo.svg +0 -0
- package/{components → src/lib/components}/editor/icons/unindent.svg +0 -0
- package/{components → src/lib/components}/editor/icons/unlink.svg +0 -0
- package/{components → src/lib/components}/page/Acknowledgements.svelte +19 -10
- package/src/lib/components/page/Authors.svelte +92 -0
- package/src/lib/components/page/BookLoader.svelte +77 -0
- package/src/lib/components/page/BulkReferenceEditor.svelte +86 -0
- package/src/lib/components/page/Chapter.svelte +449 -0
- package/src/lib/components/page/ChapterContext.ts +13 -0
- package/{components → src/lib/components}/page/ChapterNumber.svelte +0 -0
- package/{components → src/lib/components}/page/ChapterTitle.svelte +4 -2
- package/src/lib/components/page/Contexts.ts +176 -0
- package/{components → src/lib/components}/page/DefinitionView.svelte +52 -37
- package/{components → src/lib/components}/page/Description.svelte +15 -7
- package/src/lib/components/page/Edition.svelte +189 -0
- package/src/lib/components/page/EditionLoader.svelte +123 -0
- package/{components → src/lib/components}/page/Editions.svelte +22 -18
- package/{components → src/lib/components}/page/Glossary.svelte +33 -28
- package/{components → src/lib/components}/page/Header.svelte +59 -52
- package/{components → src/lib/components}/page/Index.svelte +48 -41
- package/{components → src/lib/components}/page/Instructions.svelte +2 -1
- package/{components → src/lib/components}/page/License.svelte +17 -9
- package/{components → src/lib/components}/page/Loading.svelte +0 -0
- package/{components → src/lib/components}/page/Media.svelte +44 -27
- package/{components → src/lib/components}/page/MediaPreview.svelte +3 -2
- package/{components → src/lib/components}/page/Muted.svelte +0 -0
- package/{components → src/lib/components}/page/Outline.svelte +140 -110
- package/src/lib/components/page/Page.svelte +94 -0
- package/{components → src/lib/components}/page/PageHeader.svelte +2 -1
- package/{components → src/lib/components}/page/PageParagraph.svelte +0 -0
- package/src/lib/components/page/PossibleChapter.svelte +16 -0
- package/src/lib/components/page/PossibleReference.svelte +14 -0
- package/{components → src/lib/components}/page/Print.svelte +5 -3
- package/{components → src/lib/components}/page/Publish.svelte +59 -52
- package/{components → src/lib/components}/page/Reference.svelte +39 -30
- package/{components → src/lib/components}/page/References.svelte +18 -14
- package/{components → src/lib/components}/page/Rows.svelte +0 -0
- package/src/lib/components/page/Search.svelte +153 -0
- package/{components → src/lib/components}/page/Status.svelte +5 -3
- package/{components → src/lib/components}/page/SubdomainEditor.svelte +16 -13
- package/{components → src/lib/components}/page/TableOfContents.svelte +79 -68
- package/src/lib/components/page/TableOfContentsImage.svelte +22 -0
- package/{components → src/lib/components}/page/TableOfContentsRow.svelte +34 -24
- package/{components → src/lib/components}/page/ThemeEditor.svelte +44 -33
- package/{components → src/lib/components}/page/ThemeEditorPreview.svelte +21 -12
- package/src/lib/components/page/ThemeSetEditor.svelte +21 -0
- package/{components → src/lib/components}/page/ThemeVariableEditor.svelte +18 -14
- package/{components → src/lib/components}/page/Title.svelte +0 -0
- package/{components → src/lib/components}/page/Unknown.svelte +10 -8
- package/{components/page/margins.js → src/lib/components/page/margins.ts} +79 -46
- package/{index.js → src/lib/index.js} +0 -0
- package/src/lib/models/CRUD.ts +469 -0
- package/{models/Firebase.js → src/lib/models/Firebase.ts} +26 -16
- package/src/lib/models/book/Book.ts +283 -0
- package/src/lib/models/book/BookMedia.ts +182 -0
- package/src/lib/models/book/BookSaveStatus.ts +8 -0
- package/src/lib/models/book/Chapter.ts +462 -0
- package/{models/book/ChapterID.js → src/lib/models/book/ChapterID.ts} +1 -0
- package/src/lib/models/book/Definition.ts +2 -0
- package/src/lib/models/book/Edition.ts +1216 -0
- package/src/lib/models/book/Reference.ts +171 -0
- package/{models/book/Schema.js → src/lib/models/book/Schema.ts} +1 -0
- package/{models/book/Theme.js → src/lib/models/book/Theme.ts} +111 -6
- package/{models/book/ThemeColors.d.ts → src/lib/models/book/ThemeColors.ts} +6 -0
- package/{models/book/Words.js → src/lib/models/book/Words.ts} +1 -0
- package/{models/chapter/AtomNode.js → src/lib/models/chapter/AtomNode.ts} +30 -10
- package/{models/chapter/BlockNode.js → src/lib/models/chapter/BlockNode.ts} +80 -47
- package/src/lib/models/chapter/BlocksNode.test.ts +867 -0
- package/{models/chapter/BlocksNode.js → src/lib/models/chapter/BlocksNode.ts} +571 -359
- package/{models/chapter/Bookkeeping.d.ts → src/lib/models/chapter/Bookkeeping.ts} +0 -0
- package/src/lib/models/chapter/CalloutNode.ts +79 -0
- package/{models/chapter/Caret.js → src/lib/models/chapter/Caret.ts} +50 -26
- package/src/lib/models/chapter/ChapterNode.ts +169 -0
- package/{models/chapter/CitationsNode.js → src/lib/models/chapter/CitationsNode.ts} +17 -10
- package/{models/chapter/CodeNode.js → src/lib/models/chapter/CodeNode.ts} +125 -62
- package/src/lib/models/chapter/CommentNode.ts +61 -0
- package/{models/chapter/DefinitionNode.js → src/lib/models/chapter/DefinitionNode.ts} +14 -8
- package/src/lib/models/chapter/Edit.ts +6 -0
- package/src/lib/models/chapter/EmbedNode.ts +257 -0
- package/{models/chapter/ErrorNode.js → src/lib/models/chapter/ErrorNode.ts} +15 -8
- package/src/lib/models/chapter/FootnoteNode.ts +59 -0
- package/src/lib/models/chapter/FormatNode.test.ts +137 -0
- package/{models/chapter/FormatNode.js → src/lib/models/chapter/FormatNode.ts} +443 -262
- package/{models/chapter/InlineCodeNode.js → src/lib/models/chapter/InlineCodeNode.ts} +17 -9
- package/{models/chapter/LabelNode.js → src/lib/models/chapter/LabelNode.ts} +26 -10
- package/{models/chapter/LinkNode.js → src/lib/models/chapter/LinkNode.ts} +12 -7
- package/{models/chapter/ListNode.test.js → src/lib/models/chapter/ListNode.test.ts} +57 -20
- package/{models/chapter/ListNode.js → src/lib/models/chapter/ListNode.ts} +277 -200
- package/src/lib/models/chapter/MetadataNode.ts +44 -0
- package/{models → src/lib/models}/chapter/Node.test.js +0 -0
- package/{models/chapter/Node.js → src/lib/models/chapter/Node.ts} +155 -71
- package/src/lib/models/chapter/ParagraphNode.test.ts +54 -0
- package/{models/chapter/ParagraphNode.js → src/lib/models/chapter/ParagraphNode.ts} +95 -58
- package/{models/chapter/Parser.test.js → src/lib/models/chapter/Parser.test.ts} +7 -0
- package/{models/chapter/Parser.js → src/lib/models/chapter/Parser.ts} +369 -184
- package/{models/chapter/Position.d.ts → src/lib/models/chapter/Position.ts} +0 -0
- package/src/lib/models/chapter/QuoteNode.ts +135 -0
- package/{models/chapter/RootNode.d.ts → src/lib/models/chapter/RootNode.ts} +2 -0
- package/{models/chapter/RuleNode.js → src/lib/models/chapter/RuleNode.ts} +9 -6
- package/{models/chapter/TableNode.test.js → src/lib/models/chapter/TableNode.test.ts} +27 -10
- package/{models/chapter/TableNode.js → src/lib/models/chapter/TableNode.ts} +141 -82
- package/{models/chapter/TextNode.test.js → src/lib/models/chapter/TextNode.test.ts} +2 -0
- package/{models/chapter/TextNode.js → src/lib/models/chapter/TextNode.ts} +117 -65
- package/{util/getSubdomain.js → src/lib/util/getSubdomain.ts} +14 -8
- package/{util/isMobile.js → src/lib/util/isMobile.ts} +1 -0
- package/{util/mineReference.js → src/lib/util/mineReference.ts} +45 -25
- package/{util/scrollToEyeLevel.js → src/lib/util/scrollToEyeLevel.ts} +4 -2
- package/src/params/edition.ts +3 -0
- package/src/routes/+error.svelte +12 -0
- package/src/routes/+layout.svelte +241 -0
- package/src/routes/+page.svelte +43 -0
- package/src/routes/Footer.svelte +0 -0
- package/src/routes/Header.svelte +112 -0
- package/src/routes/[bookid]/+layout.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/+error.svelte +14 -0
- package/src/routes/[bookid]/[[editionid=edition]]/+layout.svelte +7 -0
- package/src/routes/[bookid]/[[editionid=edition]]/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/[chapterid]/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/glossary/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/index/[[letter]]/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/media/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/print/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/references/+page.svelte +5 -0
- package/src/routes/[bookid]/[[editionid=edition]]/search/+page.svelte +5 -0
- package/src/routes/[bookid]/editions/+page.svelte +20 -0
- package/src/routes/about/+page.svelte +102 -0
- package/src/routes/confirm/+page.svelte +62 -0
- package/src/routes/email/+page.svelte +99 -0
- package/src/routes/login/+page.svelte +66 -0
- package/src/routes/read/+page.svelte +38 -0
- package/src/routes/write/+error.svelte +10 -0
- package/src/routes/write/+layout.svelte +11 -0
- package/src/routes/write/+page.svelte +114 -0
- package/src/routes/write/[bookid]/+layout.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/+layout.svelte +7 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/[chapterid]/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/glossary/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/index/[[letter]]/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/media/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/print/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/references/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/search/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/theme/+page.svelte +5 -0
- package/src/routes/write/[bookid]/[[editionid=edition]]/unknown/+page.svelte +5 -0
- package/src/routes/write/[bookid]/editions/+page.svelte +20 -0
- package/src/vite-env.d.ts +1 -0
- package/static/icons/favicon.png +0 -0
- package/static/icons/icon.png +0 -0
- package/static/icons/ios-icon.png +0 -0
- package/storage.rules +9 -0
- package/svelte.config.js +19 -0
- package/tsconfig.json +18 -0
- package/tsconfig.node.json +9 -0
- package/vite.config.ts +8 -0
- package/vite.reader.config.ts +32 -0
- package/components/Auth.svelte +0 -55
- package/components/Auth.svelte.d.ts +0 -16
- package/components/Authentication.js +0 -1
- package/components/BookPreview.svelte.d.ts +0 -18
- package/components/External.svelte.d.ts +0 -18
- package/components/Link.svelte +0 -51
- package/components/Link.svelte.d.ts +0 -18
- package/components/app/BookList.svelte.d.ts +0 -18
- package/components/app/Button.svelte.d.ts +0 -22
- package/components/app/Feedback.svelte.d.ts +0 -18
- package/components/app/Head.svelte.d.ts +0 -18
- package/components/app/Large.svelte.d.ts +0 -27
- package/components/app/Lead.svelte.d.ts +0 -27
- package/components/app/Link.svelte.d.ts +0 -20
- package/components/app/Options.svelte.d.ts +0 -19
- package/components/app/Paragraph.svelte.d.ts +0 -18
- package/components/app/Section.svelte.d.ts +0 -27
- package/components/app/Table.svelte.d.ts +0 -27
- package/components/app/TextInput.svelte.d.ts +0 -22
- package/components/chapter/Atom.svelte.d.ts +0 -19
- package/components/chapter/Block.svelte +0 -37
- package/components/chapter/Block.svelte.d.ts +0 -17
- package/components/chapter/Callout.svelte.d.ts +0 -17
- package/components/chapter/CaptionedCode.svelte.d.ts +0 -17
- package/components/chapter/ChapterBody.svelte.d.ts +0 -19
- package/components/chapter/Citations.svelte.d.ts +0 -17
- package/components/chapter/Code.svelte.d.ts +0 -22
- package/components/chapter/Comment.svelte.d.ts +0 -17
- package/components/chapter/Definition.svelte.d.ts +0 -17
- package/components/chapter/Embed.svelte.d.ts +0 -20
- package/components/chapter/ErrorMessage.svelte +0 -9
- package/components/chapter/ErrorMessage.svelte.d.ts +0 -17
- package/components/chapter/ExtendedPrism.d.ts +0 -2
- package/components/chapter/Figure.svelte.d.ts +0 -24
- package/components/chapter/Footnote.svelte.d.ts +0 -19
- package/components/chapter/Format.svelte.d.ts +0 -19
- package/components/chapter/InlineCode.svelte.d.ts +0 -17
- package/components/chapter/Label.svelte.d.ts +0 -17
- package/components/chapter/Link.svelte.d.ts +0 -17
- package/components/chapter/List.svelte.d.ts +0 -17
- package/components/chapter/Marginal.svelte.d.ts +0 -22
- package/components/chapter/Paragraph.svelte.d.ts +0 -18
- package/components/chapter/Positioned.svelte.d.ts +0 -19
- package/components/chapter/Problem.svelte.d.ts +0 -27
- package/components/chapter/Python.svelte +0 -128
- package/components/chapter/Python.svelte.d.ts +0 -18
- package/components/chapter/Quote.svelte.d.ts +0 -17
- package/components/chapter/Rule.svelte.d.ts +0 -17
- package/components/chapter/Table.svelte.d.ts +0 -17
- package/components/chapter/Text.svelte +0 -87
- package/components/chapter/Text.svelte.d.ts +0 -18
- package/components/editor/BookishEditor.svelte +0 -884
- package/components/editor/BookishEditor.svelte.d.ts +0 -25
- package/components/editor/CalloutEditor.svelte +0 -10
- package/components/editor/CalloutEditor.svelte.d.ts +0 -17
- package/components/editor/CaptionedCodeEditor.svelte.d.ts +0 -17
- package/components/editor/CaretContext.d.ts +0 -50
- package/components/editor/CaretContext.js +0 -1
- package/components/editor/CaretState.js +0 -1
- package/components/editor/CaretUtilities.js +0 -1
- package/components/editor/CaretView.svelte.d.ts +0 -25
- package/components/editor/CitationsEditor.svelte +0 -53
- package/components/editor/CitationsEditor.svelte.d.ts +0 -17
- package/components/editor/Clipboard.js +0 -1
- package/components/editor/Command.js +0 -1
- package/components/editor/Commands.d.ts +0 -3
- package/components/editor/ConfirmButton.svelte +0 -49
- package/components/editor/ConfirmButton.svelte.d.ts +0 -19
- package/components/editor/DefinitionEditor.svelte +0 -36
- package/components/editor/DefinitionEditor.svelte.d.ts +0 -17
- package/components/editor/EmbedEditor.svelte +0 -137
- package/components/editor/EmbedEditor.svelte.d.ts +0 -17
- package/components/editor/Icon.svelte.d.ts +0 -16
- package/components/editor/ImageChooser.svelte.d.ts +0 -18
- package/components/editor/InlineCodeEditor.svelte +0 -12
- package/components/editor/InlineCodeEditor.svelte.d.ts +0 -17
- package/components/editor/LabelEditor.svelte.d.ts +0 -17
- package/components/editor/LanguageEditor.svelte.d.ts +0 -17
- package/components/editor/LinkEditor.svelte +0 -100
- package/components/editor/LinkEditor.svelte.d.ts +0 -17
- package/components/editor/Note.svelte.d.ts +0 -27
- package/components/editor/Permissions.svelte.d.ts +0 -20
- package/components/editor/PositionEditor.svelte +0 -17
- package/components/editor/PositionEditor.svelte.d.ts +0 -18
- package/components/editor/QuoteEditor.svelte +0 -10
- package/components/editor/QuoteEditor.svelte.d.ts +0 -17
- package/components/editor/Switch.svelte.d.ts +0 -20
- package/components/editor/TableEditor.svelte +0 -10
- package/components/editor/TableEditor.svelte.d.ts +0 -17
- package/components/editor/TextEditor.svelte.d.ts +0 -24
- package/components/editor/Toggle.svelte +0 -41
- package/components/editor/Toggle.svelte.d.ts +0 -19
- package/components/editor/Toolbar.svelte +0 -249
- package/components/editor/Toolbar.svelte.d.ts +0 -17
- package/components/editor/ToolbarGroup.svelte.d.ts +0 -18
- package/components/editor/ToolbarSpacer.svelte.d.ts +0 -23
- package/components/editor/URLEditor.svelte +0 -13
- package/components/editor/URLEditor.svelte.d.ts +0 -18
- package/components/editor/UndoState.js +0 -1
- package/components/page/Acknowledgements.svelte.d.ts +0 -14
- package/components/page/Authors.svelte +0 -85
- package/components/page/Authors.svelte.d.ts +0 -21
- package/components/page/BookLoader.svelte +0 -59
- package/components/page/BookLoader.svelte.d.ts +0 -16
- package/components/page/BulkReferenceEditor.svelte +0 -63
- package/components/page/BulkReferenceEditor.svelte.d.ts +0 -14
- package/components/page/Chapter.svelte +0 -392
- package/components/page/Chapter.svelte.d.ts +0 -18
- package/components/page/ChapterContext.d.ts +0 -10
- package/components/page/ChapterContext.js +0 -1
- package/components/page/ChapterNumber.svelte.d.ts +0 -27
- package/components/page/ChapterTitle.svelte.d.ts +0 -18
- package/components/page/Contexts.d.ts +0 -47
- package/components/page/Contexts.js +0 -133
- package/components/page/DefinitionView.svelte.d.ts +0 -18
- package/components/page/Description.svelte.d.ts +0 -14
- package/components/page/Edition.svelte +0 -161
- package/components/page/Edition.svelte.d.ts +0 -20
- package/components/page/EditionLoader.svelte +0 -99
- package/components/page/EditionLoader.svelte.d.ts +0 -18
- package/components/page/Editions.svelte.d.ts +0 -14
- package/components/page/Glossary.svelte.d.ts +0 -14
- package/components/page/Header.svelte.d.ts +0 -29
- package/components/page/Index.svelte.d.ts +0 -14
- package/components/page/Instructions.svelte.d.ts +0 -18
- package/components/page/License.svelte.d.ts +0 -14
- package/components/page/Loading.svelte.d.ts +0 -23
- package/components/page/Media.svelte.d.ts +0 -14
- package/components/page/MediaPreview.svelte.d.ts +0 -19
- package/components/page/Muted.svelte.d.ts +0 -27
- package/components/page/Outline.svelte.d.ts +0 -19
- package/components/page/Page.svelte +0 -84
- package/components/page/Page.svelte.d.ts +0 -19
- package/components/page/PageHeader.svelte.d.ts +0 -18
- package/components/page/PageParagraph.svelte.d.ts +0 -27
- package/components/page/PossibleChapter.svelte +0 -14
- package/components/page/PossibleChapter.svelte.d.ts +0 -14
- package/components/page/PossibleReference.svelte +0 -11
- package/components/page/PossibleReference.svelte.d.ts +0 -18
- package/components/page/Print.svelte.d.ts +0 -14
- package/components/page/Publish.svelte.d.ts +0 -14
- package/components/page/Reference.svelte.d.ts +0 -17
- package/components/page/References.svelte.d.ts +0 -14
- package/components/page/Rows.svelte.d.ts +0 -27
- package/components/page/Search.svelte +0 -133
- package/components/page/Search.svelte.d.ts +0 -14
- package/components/page/Status.svelte.d.ts +0 -14
- package/components/page/SubdomainEditor.svelte.d.ts +0 -14
- package/components/page/TableOfContents.svelte.d.ts +0 -14
- package/components/page/TableOfContentsImage.svelte +0 -18
- package/components/page/TableOfContentsImage.svelte.d.ts +0 -16
- package/components/page/TableOfContentsRow.svelte.d.ts +0 -24
- package/components/page/ThemeEditor.svelte.d.ts +0 -14
- package/components/page/ThemeEditorPreview.svelte.d.ts +0 -17
- package/components/page/ThemeSetEditor.svelte +0 -19
- package/components/page/ThemeSetEditor.svelte.d.ts +0 -18
- package/components/page/ThemeVariableEditor.svelte.d.ts +0 -18
- package/components/page/Title.svelte.d.ts +0 -27
- package/components/page/Unknown.svelte.d.ts +0 -16
- package/components/page/margins.d.ts +0 -2
- package/index.d.ts +0 -15
- package/models/CRUD.d.ts +0 -27
- package/models/CRUD.js +0 -262
- package/models/Firebase.d.ts +0 -5
- package/models/book/Book.d.ts +0 -61
- package/models/book/Book.js +0 -135
- package/models/book/BookMedia.d.ts +0 -23
- package/models/book/BookMedia.js +0 -108
- package/models/book/BookSaveStatus.d.ts +0 -7
- package/models/book/BookSaveStatus.js +0 -8
- package/models/book/Chapter.d.ts +0 -81
- package/models/book/Chapter.js +0 -212
- package/models/book/ChapterID.d.ts +0 -10
- package/models/book/Definition.d.ts +0 -6
- package/models/book/Definition.js +0 -1
- package/models/book/Edition.d.ts +0 -139
- package/models/book/Edition.js +0 -620
- package/models/book/Reference.d.ts +0 -24
- package/models/book/Reference.js +0 -78
- package/models/book/Schema.d.ts +0 -174
- package/models/book/Theme.d.ts +0 -113
- package/models/book/ThemeColors.js +0 -1
- package/models/book/Words.d.ts +0 -2
- package/models/chapter/AtomNode.d.ts +0 -18
- package/models/chapter/BlockNode.d.ts +0 -20
- package/models/chapter/BlocksNode.d.ts +0 -50
- package/models/chapter/BlocksNode.test.d.ts +0 -1
- package/models/chapter/BlocksNode.test.js +0 -568
- package/models/chapter/Bookkeeping.js +0 -1
- package/models/chapter/CalloutNode.d.ts +0 -17
- package/models/chapter/CalloutNode.js +0 -58
- package/models/chapter/Caret.d.ts +0 -23
- package/models/chapter/ChapterNode.d.ts +0 -34
- package/models/chapter/ChapterNode.js +0 -117
- package/models/chapter/CitationsNode.d.ts +0 -16
- package/models/chapter/CodeNode.d.ts +0 -35
- package/models/chapter/CommentNode.d.ts +0 -18
- package/models/chapter/CommentNode.js +0 -48
- package/models/chapter/DefinitionNode.d.ts +0 -12
- package/models/chapter/Edit.d.ts +0 -7
- package/models/chapter/Edit.js +0 -1
- package/models/chapter/EmbedNode.d.ts +0 -45
- package/models/chapter/EmbedNode.js +0 -168
- package/models/chapter/ErrorNode.d.ts +0 -17
- package/models/chapter/FootnoteNode.d.ts +0 -18
- package/models/chapter/FootnoteNode.js +0 -47
- package/models/chapter/FormatNode.d.ts +0 -60
- package/models/chapter/FormatNode.test.d.ts +0 -1
- package/models/chapter/FormatNode.test.js +0 -96
- package/models/chapter/InlineCodeNode.d.ts +0 -12
- package/models/chapter/LabelNode.d.ts +0 -17
- package/models/chapter/LinkNode.d.ts +0 -12
- package/models/chapter/ListNode.d.ts +0 -51
- package/models/chapter/ListNode.test.d.ts +0 -1
- package/models/chapter/MetadataNode.d.ts +0 -17
- package/models/chapter/MetadataNode.js +0 -32
- package/models/chapter/Node.d.ts +0 -38
- package/models/chapter/Node.test.d.ts +0 -1
- package/models/chapter/ParagraphNode.d.ts +0 -33
- package/models/chapter/ParagraphNode.test.d.ts +0 -1
- package/models/chapter/ParagraphNode.test.js +0 -30
- package/models/chapter/Parser.d.ts +0 -75
- package/models/chapter/Parser.test.d.ts +0 -1
- package/models/chapter/Position.js +0 -1
- package/models/chapter/QuoteNode.d.ts +0 -25
- package/models/chapter/QuoteNode.js +0 -99
- package/models/chapter/RootNode.js +0 -1
- package/models/chapter/RuleNode.d.ts +0 -15
- package/models/chapter/TableNode.d.ts +0 -37
- package/models/chapter/TableNode.test.d.ts +0 -1
- package/models/chapter/TextNode.d.ts +0 -36
- package/models/chapter/TextNode.test.d.ts +0 -1
- package/util/getSubdomain.d.ts +0 -3
- package/util/isMobile.d.ts +0 -2
- package/util/mineReference.d.ts +0 -4
- package/util/scrollToEyeLevel.d.ts +0 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type Edition from '../book/Edition';
|
|
1
2
|
import CalloutNode from './CalloutNode';
|
|
2
3
|
import ChapterNode from './ChapterNode';
|
|
3
4
|
import CitationsNode from './CitationsNode';
|
|
@@ -8,6 +9,7 @@ import EmbedNode from './EmbedNode';
|
|
|
8
9
|
import ErrorNode from './ErrorNode';
|
|
9
10
|
import FootnoteNode from './FootnoteNode';
|
|
10
11
|
import FormatNode from './FormatNode';
|
|
12
|
+
import type { Format, FormatNodeSegmentType } from './FormatNode';
|
|
11
13
|
import InlineCodeNode from './InlineCodeNode';
|
|
12
14
|
import LabelNode from './LabelNode';
|
|
13
15
|
import LinkNode from './LinkNode';
|
|
@@ -18,8 +20,13 @@ import Reference from '../book/Reference';
|
|
|
18
20
|
import RuleNode from './RuleNode';
|
|
19
21
|
import TableNode from './TableNode';
|
|
20
22
|
import TextNode from './TextNode';
|
|
23
|
+
import type Position from './Position';
|
|
24
|
+
import type BlockNode from './BlockNode';
|
|
25
|
+
import type Bookkeeping from './Bookkeeping';
|
|
26
|
+
|
|
21
27
|
const numberedRE = /^[0-9]+\.+/;
|
|
22
28
|
const bulletRE = /^\*+\s+/;
|
|
29
|
+
|
|
23
30
|
// TODO This grammar is slightly out of date.
|
|
24
31
|
// A simple recursive descent parser for this grammar.
|
|
25
32
|
// Embeds a tokenizer, since the lexical grammar is simple.
|
|
@@ -45,16 +52,19 @@ const bulletRE = /^\*+\s+/;
|
|
|
45
52
|
// LINK :: [CONTENT|TEXT]
|
|
46
53
|
// FOOTNOTE :: {TEXT}
|
|
47
54
|
// TEXT :: (.+)
|
|
55
|
+
|
|
48
56
|
export default class Parser {
|
|
49
|
-
book;
|
|
50
|
-
text;
|
|
51
|
-
index;
|
|
52
|
-
openedDoubleQuote;
|
|
57
|
+
book: Edition | undefined;
|
|
58
|
+
text: string;
|
|
59
|
+
index: number;
|
|
60
|
+
openedDoubleQuote: boolean;
|
|
53
61
|
// We pass this to all parsing functions to gather information strewn about the document.
|
|
54
|
-
metadata;
|
|
55
|
-
|
|
62
|
+
metadata: Bookkeeping;
|
|
63
|
+
|
|
64
|
+
constructor(book: Edition | undefined, text: string) {
|
|
56
65
|
if (typeof text !== 'string')
|
|
57
66
|
throw 'Parser expected a string but received ' + typeof text;
|
|
67
|
+
|
|
58
68
|
this.book = book;
|
|
59
69
|
this.text = text;
|
|
60
70
|
this.index = 0; // Start at the first character.
|
|
@@ -63,65 +73,91 @@ export default class Parser {
|
|
|
63
73
|
symbols: {},
|
|
64
74
|
};
|
|
65
75
|
}
|
|
66
|
-
|
|
76
|
+
|
|
77
|
+
static preprocessSymbols(book: Edition, text: string) {
|
|
67
78
|
// Replace any remaining symbols with any definitions given.
|
|
68
79
|
if (book && book.getSymbols()) {
|
|
69
|
-
for (const [symbol, definition] of Object.entries(
|
|
80
|
+
for (const [symbol, definition] of Object.entries(
|
|
81
|
+
book.getSymbols()
|
|
82
|
+
)) {
|
|
70
83
|
// Don't replace escaped at symbols. Otherwise, be liberal in replacing any matching symbol that starts with the symbol
|
|
71
84
|
// name and ends with a word boundary.
|
|
72
|
-
text = text.replace(
|
|
85
|
+
text = text.replace(
|
|
86
|
+
new RegExp('([^\\\\])@' + symbol + '\\b', 'g'),
|
|
87
|
+
'$1' + definition
|
|
88
|
+
);
|
|
73
89
|
}
|
|
74
90
|
}
|
|
75
91
|
return text;
|
|
76
92
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
93
|
+
|
|
94
|
+
static parseChapter(book: Edition | undefined, text: string) {
|
|
95
|
+
return new Parser(
|
|
96
|
+
book,
|
|
97
|
+
book === undefined ? text : Parser.preprocessSymbols(book, text)
|
|
98
|
+
).parseChapter();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static parseFormat(book: Edition | undefined, text: string) {
|
|
102
|
+
return new Parser(
|
|
103
|
+
book,
|
|
104
|
+
book === undefined ? text : Parser.preprocessSymbols(book, text)
|
|
105
|
+
).parseFormat();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static parseEmbed(book: Edition | undefined, text: string) {
|
|
109
|
+
return new Parser(
|
|
110
|
+
book,
|
|
111
|
+
book === undefined ? text : Parser.preprocessSymbols(book, text)
|
|
112
|
+
).parseEmbed();
|
|
113
|
+
}
|
|
114
|
+
|
|
86
115
|
// Get the next character, if there is one, null otherwise.
|
|
87
|
-
peek() {
|
|
116
|
+
peek(): string | null {
|
|
88
117
|
return this.more() ? this.text.charAt(this.index) : null;
|
|
89
118
|
}
|
|
119
|
+
|
|
90
120
|
// True if there are more characters to parse.
|
|
91
|
-
more() {
|
|
121
|
+
more(): boolean {
|
|
92
122
|
return this.index < this.text.length;
|
|
93
123
|
}
|
|
124
|
+
|
|
94
125
|
nextIsEmptyParagraph() {
|
|
95
|
-
return (
|
|
126
|
+
return (
|
|
127
|
+
this.text.charAt(this.index) === '\n' &&
|
|
96
128
|
this.text.charAt(this.index + 1) === '\n' &&
|
|
97
|
-
this.text.charAt(this.index + 2) === '\n'
|
|
129
|
+
this.text.charAt(this.index + 2) === '\n'
|
|
130
|
+
);
|
|
98
131
|
}
|
|
132
|
+
|
|
99
133
|
nextIsWhitespace() {
|
|
100
|
-
return (
|
|
101
|
-
this.peek() === '
|
|
102
|
-
|
|
103
|
-
|
|
134
|
+
return (
|
|
135
|
+
(this.peek() === ' ' ||
|
|
136
|
+
this.peek() === '\t' ||
|
|
137
|
+
this.peek() === '\n') &&
|
|
138
|
+
!this.nextIsEmptyParagraph()
|
|
139
|
+
);
|
|
104
140
|
}
|
|
141
|
+
|
|
105
142
|
// Return the current character--if there is one-- and increment the index.
|
|
106
|
-
read(smarten = true) {
|
|
107
|
-
if (!this.more())
|
|
108
|
-
|
|
143
|
+
read(smarten = true): string | null {
|
|
144
|
+
if (!this.more()) return null;
|
|
145
|
+
|
|
109
146
|
let char = this.text.charAt(this.index);
|
|
147
|
+
|
|
110
148
|
if (smarten) {
|
|
111
|
-
if (char === '\n')
|
|
112
|
-
|
|
149
|
+
if (char === '\n') this.openedDoubleQuote = false;
|
|
150
|
+
|
|
113
151
|
// As we read, replace straight quotes with smart quotes.
|
|
114
152
|
if (char === '"') {
|
|
115
153
|
// Replace left quotes after whitespace.
|
|
116
154
|
if (this.openedDoubleQuote) {
|
|
117
155
|
char = '\u201d';
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
156
|
+
} else {
|
|
120
157
|
char = '\u201c';
|
|
121
158
|
}
|
|
122
159
|
this.openedDoubleQuote = !this.openedDoubleQuote;
|
|
123
|
-
}
|
|
124
|
-
else if (char === "'") {
|
|
160
|
+
} else if (char === "'") {
|
|
125
161
|
// If there's whitespace before this, it's a left single quote.
|
|
126
162
|
if (/\s/.test(this.text.charAt(this.index - 1)))
|
|
127
163
|
char = '\u2018';
|
|
@@ -130,53 +166,70 @@ export default class Parser {
|
|
|
130
166
|
char = '\u2019';
|
|
131
167
|
}
|
|
132
168
|
}
|
|
133
|
-
|
|
169
|
+
|
|
170
|
+
if (
|
|
171
|
+
char === '-' &&
|
|
134
172
|
this.text.charAt(this.index + 1) === '-' &&
|
|
135
|
-
this.text.charAt(this.index) !== '\n'
|
|
173
|
+
this.text.charAt(this.index) !== '\n'
|
|
174
|
+
) {
|
|
136
175
|
this.index++;
|
|
137
176
|
char = '\u2014';
|
|
138
177
|
}
|
|
139
178
|
}
|
|
179
|
+
|
|
140
180
|
// Advance to the next character in the document.
|
|
141
181
|
this.index++;
|
|
182
|
+
|
|
142
183
|
return char;
|
|
143
184
|
}
|
|
144
|
-
|
|
185
|
+
|
|
186
|
+
unread(): void {
|
|
145
187
|
this.index--;
|
|
146
188
|
}
|
|
189
|
+
|
|
147
190
|
// All of the text including and after the current index.
|
|
148
|
-
rest() {
|
|
191
|
+
rest(): string {
|
|
149
192
|
return this.text.substring(this.index);
|
|
150
193
|
}
|
|
194
|
+
|
|
151
195
|
// The character before
|
|
152
|
-
charBeforeNext() {
|
|
196
|
+
charBeforeNext(): string | null {
|
|
153
197
|
return this.index === 0 ? null : this.text.charAt(this.index - 1);
|
|
154
198
|
}
|
|
199
|
+
|
|
155
200
|
// The character after
|
|
156
|
-
charAfterNext() {
|
|
201
|
+
charAfterNext(): string | null {
|
|
157
202
|
return this.index === this.text.length - 1
|
|
158
203
|
? null
|
|
159
204
|
: this.text.charAt(this.index + 1);
|
|
160
205
|
}
|
|
206
|
+
|
|
161
207
|
// All the text until the next newline
|
|
162
|
-
restOfLine() {
|
|
163
|
-
const nextNewline =
|
|
164
|
-
|
|
165
|
-
|
|
208
|
+
restOfLine(): string {
|
|
209
|
+
const nextNewline =
|
|
210
|
+
this.text.substring(this.index).indexOf('\n') + this.index;
|
|
211
|
+
if (nextNewline < 0) return this.text.substring(this.index);
|
|
166
212
|
else
|
|
167
|
-
return this.text.substring(
|
|
213
|
+
return this.text.substring(
|
|
214
|
+
this.index,
|
|
215
|
+
Math.max(this.index, nextNewline)
|
|
216
|
+
);
|
|
168
217
|
}
|
|
218
|
+
|
|
169
219
|
// True if the given string is occurs next in the text.
|
|
170
|
-
nextIs(text) {
|
|
171
|
-
if (!this.more())
|
|
172
|
-
|
|
173
|
-
|
|
220
|
+
nextIs(text: string) {
|
|
221
|
+
if (!this.more()) return false;
|
|
222
|
+
return (
|
|
223
|
+
this.text.substring(this.index, this.index + text.length) === text
|
|
224
|
+
);
|
|
174
225
|
}
|
|
226
|
+
|
|
175
227
|
// A critical list that tells inline formatting parsers to stop being greedy.
|
|
176
|
-
nextIsContentDelimiter() {
|
|
228
|
+
nextIsContentDelimiter(): boolean {
|
|
177
229
|
const next = this.peek();
|
|
178
230
|
const charAfterNext = this.charAfterNext();
|
|
179
|
-
return (
|
|
231
|
+
return (
|
|
232
|
+
next === '\n' ||
|
|
180
233
|
next === '_' ||
|
|
181
234
|
next === '*' ||
|
|
182
235
|
next === '`' ||
|
|
@@ -190,56 +243,69 @@ export default class Parser {
|
|
|
190
243
|
next === '{' ||
|
|
191
244
|
(this.charBeforeNext() === ' ' && next === '%') ||
|
|
192
245
|
next === '[' ||
|
|
193
|
-
next === '\\'
|
|
246
|
+
next === '\\'
|
|
247
|
+
);
|
|
194
248
|
}
|
|
249
|
+
|
|
195
250
|
// True if the next part of this string matches the given regular expression.
|
|
196
|
-
nextMatches(regex) {
|
|
197
|
-
if (!this.more())
|
|
198
|
-
return false;
|
|
251
|
+
nextMatches(regex: RegExp): boolean {
|
|
252
|
+
if (!this.more()) return false;
|
|
199
253
|
return regex.test(this.rest());
|
|
200
254
|
}
|
|
255
|
+
|
|
201
256
|
// Returns true if all of the text between the current character and the next newline is whitespace.
|
|
202
|
-
isBlankLine() {
|
|
257
|
+
isBlankLine(): boolean {
|
|
203
258
|
return this.restOfLine().trim() === '';
|
|
204
259
|
}
|
|
260
|
+
|
|
205
261
|
// Read until encountering something other than a tab or a space.
|
|
206
|
-
readWhitespace() {
|
|
262
|
+
readWhitespace(): void {
|
|
207
263
|
let peek = this.peek();
|
|
208
264
|
while (peek !== null && /^[ \t]/.test(peek)) {
|
|
209
265
|
this.read();
|
|
210
266
|
peek = this.peek();
|
|
211
267
|
}
|
|
212
268
|
}
|
|
269
|
+
|
|
213
270
|
// Read until the end of the line.
|
|
214
|
-
readUntilNewLine() {
|
|
271
|
+
readUntilNewLine(): string {
|
|
215
272
|
let text = '';
|
|
216
|
-
while (this.more() && this.peek() !== '\n')
|
|
217
|
-
text = text + this.read();
|
|
273
|
+
while (this.more() && this.peek() !== '\n') text = text + this.read();
|
|
218
274
|
return text;
|
|
219
275
|
}
|
|
276
|
+
|
|
220
277
|
// Read until encountering the given string and return the read text.
|
|
221
|
-
readUntilNewlineOr(string) {
|
|
278
|
+
readUntilNewlineOr(string: string): string {
|
|
222
279
|
let text = '';
|
|
223
280
|
while (this.more() && !this.nextIs('\n') && !this.nextIs(string))
|
|
224
281
|
text = text + this.read();
|
|
225
282
|
return text;
|
|
226
283
|
}
|
|
227
|
-
|
|
228
|
-
|
|
284
|
+
|
|
285
|
+
parseChapter(): ChapterNode {
|
|
286
|
+
let blocks: BlockNode[] = [];
|
|
287
|
+
|
|
229
288
|
// Read any symbols declared for this chapter.
|
|
230
289
|
this.parseSymbols();
|
|
290
|
+
|
|
231
291
|
// Get the remaining text.
|
|
232
292
|
let declarations = this.text.substring(0, this.index);
|
|
233
293
|
let rest = this.rest();
|
|
294
|
+
|
|
234
295
|
// First, replace any occurrences of the symbol with the symbol's text.
|
|
235
296
|
for (const [symbol, text] of Object.entries(this.metadata.symbols)) {
|
|
236
|
-
rest = rest.replace(
|
|
297
|
+
rest = rest.replace(
|
|
298
|
+
new RegExp('([^\\\\])@' + symbol + '\\b', 'g'),
|
|
299
|
+
'$1' + text
|
|
300
|
+
);
|
|
237
301
|
}
|
|
302
|
+
|
|
238
303
|
// Replace all of the remaining symbols using book symbol definitions.
|
|
239
|
-
if (this.book)
|
|
240
|
-
|
|
304
|
+
if (this.book) rest = Parser.preprocessSymbols(this.book, rest);
|
|
305
|
+
|
|
241
306
|
// Replace the text with the pre-processed text.
|
|
242
307
|
this.text = declarations + rest;
|
|
308
|
+
|
|
243
309
|
// While there's more text, parse a line.
|
|
244
310
|
let trailingNewlines = 0;
|
|
245
311
|
while (this.more()) {
|
|
@@ -248,73 +314,90 @@ export default class Parser {
|
|
|
248
314
|
blocks.push(this.parseBlock());
|
|
249
315
|
// Read whitespace until we find the next thing.
|
|
250
316
|
while (this.nextIsWhitespace()) {
|
|
251
|
-
if (this.peek() === '\n')
|
|
252
|
-
trailingNewlines++;
|
|
317
|
+
if (this.peek() === '\n') trailingNewlines++;
|
|
253
318
|
this.read();
|
|
254
319
|
}
|
|
255
320
|
}
|
|
321
|
+
|
|
256
322
|
// If there are no blocks, or the chapter ended with two newlines, append an empty paragraph with an empty format node and an empty text node.
|
|
257
323
|
if (blocks.length === 0 || trailingNewlines > 1)
|
|
258
324
|
blocks.push(new ParagraphNode());
|
|
325
|
+
|
|
259
326
|
// Make the chapter node so we can pass it around.
|
|
260
327
|
return new ChapterNode(blocks, this.metadata);
|
|
261
328
|
}
|
|
329
|
+
|
|
262
330
|
parseSymbols() {
|
|
263
331
|
// Read whitespace before the symbols
|
|
264
332
|
this.readWhitespace();
|
|
333
|
+
|
|
265
334
|
// Keep reading symbols
|
|
266
335
|
while (this.nextIs('@')) {
|
|
267
336
|
// Read the @
|
|
268
337
|
this.read();
|
|
338
|
+
|
|
269
339
|
// Read the name.
|
|
270
340
|
let name = this.readUntilNewlineOr(':');
|
|
341
|
+
|
|
271
342
|
// Names need to be letter and numbers only.
|
|
272
343
|
if (!/^[a-zA-Z0-9]+$/.test(name)) {
|
|
273
|
-
new ErrorNode(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
name
|
|
277
|
-
"'
|
|
344
|
+
new ErrorNode(
|
|
345
|
+
this.readUntilNewLine(),
|
|
346
|
+
name.trim() === ''
|
|
347
|
+
? 'Did you mean to declare a symbol? Use an @ symbol, then a name of only numbers and letters, then a colon, then whatever content you want it to represent.'
|
|
348
|
+
: "'" +
|
|
349
|
+
name +
|
|
350
|
+
"' isn't a valid name for a symbol; letters and numbers only"
|
|
351
|
+
);
|
|
278
352
|
return;
|
|
279
353
|
}
|
|
354
|
+
|
|
280
355
|
// Read any whitespace until the colon.
|
|
281
356
|
this.readWhitespace();
|
|
357
|
+
|
|
282
358
|
// Name declarations need to be terminated with a colon before the block starts.
|
|
283
359
|
if (!this.nextIs(':')) {
|
|
284
|
-
new ErrorNode(
|
|
360
|
+
new ErrorNode(
|
|
361
|
+
this.readUntilNewLine(),
|
|
362
|
+
"Symbol names are to be followed by a ':'"
|
|
363
|
+
);
|
|
285
364
|
return;
|
|
286
365
|
}
|
|
366
|
+
|
|
287
367
|
// Read the colon
|
|
288
368
|
this.read();
|
|
369
|
+
|
|
289
370
|
// Read any whitespace after the colon.
|
|
290
371
|
this.readWhitespace();
|
|
372
|
+
|
|
291
373
|
// Remember where the text starts
|
|
292
374
|
let startIndex = this.index;
|
|
375
|
+
|
|
293
376
|
// Parse a block, any block.
|
|
294
377
|
this.parseBlock();
|
|
378
|
+
|
|
295
379
|
// Remember the text we parsed.
|
|
296
380
|
this.metadata.symbols[name] = this.text
|
|
297
381
|
.substring(startIndex, this.index)
|
|
298
382
|
.trim();
|
|
383
|
+
|
|
299
384
|
// Read whitespace until we find the next non-whitespace thing.
|
|
300
|
-
while (this.nextIsWhitespace())
|
|
301
|
-
this.read();
|
|
385
|
+
while (this.nextIsWhitespace()) this.read();
|
|
302
386
|
}
|
|
303
387
|
}
|
|
304
|
-
|
|
388
|
+
|
|
389
|
+
parseBlock(): BlockNode {
|
|
305
390
|
// Read comment lines
|
|
306
391
|
while (this.nextIs('%')) {
|
|
307
392
|
this.readUntilNewLine();
|
|
308
393
|
}
|
|
394
|
+
|
|
309
395
|
// Parse and return a header if it starts with a hash
|
|
310
|
-
if (this.nextIs('#'))
|
|
311
|
-
return this.parseHeader();
|
|
396
|
+
if (this.nextIs('#')) return this.parseHeader();
|
|
312
397
|
// Parse and return a horizontal rule if it starts with a dash
|
|
313
|
-
else if (this.nextIs('-'))
|
|
314
|
-
return this.parseRule();
|
|
398
|
+
else if (this.nextIs('-')) return this.parseRule();
|
|
315
399
|
// Parse and return an embed if it starts with a bar
|
|
316
|
-
else if (this.nextIs('|'))
|
|
317
|
-
return this.parseEmbed();
|
|
400
|
+
else if (this.nextIs('|')) return this.parseEmbed();
|
|
318
401
|
// Parse and return a bulleted or numbered list
|
|
319
402
|
else if (this.nextMatches(bulletRE) || this.nextMatches(numberedRE))
|
|
320
403
|
return this.parseList();
|
|
@@ -322,69 +405,75 @@ export default class Parser {
|
|
|
322
405
|
else if (this.nextMatches(/^`[a-zA-Z!]*[ \t]*\n/))
|
|
323
406
|
return this.parseCode();
|
|
324
407
|
// Parse and return a quote block if it starts with "
|
|
325
|
-
else if (this.nextMatches(/^"[ \t]*\n/))
|
|
326
|
-
return this.parseQuote();
|
|
408
|
+
else if (this.nextMatches(/^"[ \t]*\n/)) return this.parseQuote();
|
|
327
409
|
// Parse and return a callout if the line starts with =
|
|
328
|
-
else if (this.nextMatches(/^=[ \t]*\n/))
|
|
329
|
-
return this.parseCallout();
|
|
410
|
+
else if (this.nextMatches(/^=[ \t]*\n/)) return this.parseCallout();
|
|
330
411
|
// Parse and return a table if the line starts with a ,
|
|
331
|
-
else if (this.nextIs(','))
|
|
332
|
-
return this.parseTable();
|
|
412
|
+
else if (this.nextIs(',')) return this.parseTable();
|
|
333
413
|
// Parse the text as paragraph;
|
|
334
|
-
else
|
|
335
|
-
return this.parseParagraph();
|
|
414
|
+
else return this.parseParagraph();
|
|
336
415
|
}
|
|
337
|
-
|
|
416
|
+
|
|
417
|
+
parseParagraph(): ParagraphNode {
|
|
338
418
|
if (this.nextIsEmptyParagraph()) {
|
|
339
419
|
this.read();
|
|
340
420
|
this.read();
|
|
341
421
|
return new ParagraphNode(0, new FormatNode('', [new TextNode()]));
|
|
342
|
-
}
|
|
343
|
-
else
|
|
344
|
-
return new ParagraphNode(0, this.parseFormat());
|
|
422
|
+
} else return new ParagraphNode(0, this.parseFormat());
|
|
345
423
|
}
|
|
346
|
-
|
|
424
|
+
|
|
425
|
+
parseHeader(): ParagraphNode {
|
|
347
426
|
// Read a sequence of hashes
|
|
348
427
|
let count = 0;
|
|
349
428
|
while (this.nextIs('#')) {
|
|
350
429
|
this.read();
|
|
351
430
|
count++;
|
|
352
431
|
}
|
|
432
|
+
|
|
353
433
|
// Read any whitespace after the hashes.
|
|
354
434
|
this.readWhitespace();
|
|
435
|
+
|
|
355
436
|
// Parse some content.
|
|
356
437
|
return new ParagraphNode(Math.min(3, count), this.parseFormat());
|
|
357
438
|
}
|
|
358
|
-
|
|
439
|
+
|
|
440
|
+
parseRule(): RuleNode {
|
|
359
441
|
// Read until the end of the line. Ignore all text that follows.
|
|
360
442
|
this.readUntilNewLine();
|
|
443
|
+
|
|
361
444
|
return new RuleNode();
|
|
362
445
|
}
|
|
363
|
-
|
|
446
|
+
|
|
447
|
+
parseList(): ListNode {
|
|
364
448
|
let numbered = this.nextMatches(numberedRE);
|
|
365
|
-
|
|
449
|
+
|
|
450
|
+
const items: (FormatNode | ListNode)[] = [];
|
|
366
451
|
let lastLevel = undefined;
|
|
367
452
|
let currentLevel = undefined;
|
|
453
|
+
|
|
368
454
|
// Keep parsing bullets until there aren't any. They must be of the same type, otherwise we stop.
|
|
369
455
|
while (this.nextMatches(numberedRE) || this.nextMatches(bulletRE)) {
|
|
370
456
|
numbered = this.nextMatches(numberedRE);
|
|
457
|
+
|
|
371
458
|
// Remember the last level
|
|
372
459
|
lastLevel = currentLevel;
|
|
460
|
+
|
|
373
461
|
// Start the current level at 0
|
|
374
462
|
currentLevel = 0;
|
|
463
|
+
|
|
375
464
|
let digits = undefined;
|
|
376
465
|
if (numbered) {
|
|
377
466
|
// Read the digits and remember how many there were so we can backtrack.
|
|
378
467
|
digits = this.index;
|
|
379
468
|
this.readUntilNewlineOr('.');
|
|
380
469
|
digits = this.index - digits;
|
|
470
|
+
|
|
381
471
|
// Figure out this level.
|
|
382
472
|
while (this.nextIs('.')) {
|
|
383
473
|
this.read();
|
|
384
474
|
currentLevel++;
|
|
385
475
|
}
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
476
|
+
} else {
|
|
388
477
|
// Figure out this level.
|
|
389
478
|
currentLevel = 0;
|
|
390
479
|
while (this.nextIs('*')) {
|
|
@@ -392,15 +481,18 @@ export default class Parser {
|
|
|
392
481
|
currentLevel++;
|
|
393
482
|
}
|
|
394
483
|
}
|
|
484
|
+
|
|
395
485
|
// If this is the first bullet, or its the same level, just parse another bullet.
|
|
396
486
|
if (lastLevel === undefined || lastLevel === currentLevel) {
|
|
397
487
|
// Read the whitespace after the bullet.
|
|
398
488
|
this.readWhitespace();
|
|
399
489
|
// Parse content after the bullet.
|
|
400
490
|
const format = this.parseFormat();
|
|
401
|
-
items.push(
|
|
402
|
-
|
|
403
|
-
|
|
491
|
+
items.push(
|
|
492
|
+
format.isEmpty()
|
|
493
|
+
? format.withSegmentAppended(new TextNode())
|
|
494
|
+
: format
|
|
495
|
+
);
|
|
404
496
|
}
|
|
405
497
|
// Otherwise, unread the stars, then either stop parsing or parse nested list.
|
|
406
498
|
else {
|
|
@@ -410,6 +502,7 @@ export default class Parser {
|
|
|
410
502
|
this.unread();
|
|
411
503
|
count--;
|
|
412
504
|
}
|
|
505
|
+
|
|
413
506
|
// Unread the digits if there are any
|
|
414
507
|
if (digits !== undefined) {
|
|
415
508
|
while (digits > 0) {
|
|
@@ -417,9 +510,9 @@ export default class Parser {
|
|
|
417
510
|
digits--;
|
|
418
511
|
}
|
|
419
512
|
}
|
|
513
|
+
|
|
420
514
|
// If this new bullet is a lower level, then stop reading bullets.
|
|
421
|
-
if (currentLevel < lastLevel)
|
|
422
|
-
break;
|
|
515
|
+
if (currentLevel < lastLevel) break;
|
|
423
516
|
// Otherwise, it's greater, and we should read another list.
|
|
424
517
|
else {
|
|
425
518
|
items.push(this.parseList());
|
|
@@ -427,6 +520,7 @@ export default class Parser {
|
|
|
427
520
|
currentLevel = lastLevel;
|
|
428
521
|
}
|
|
429
522
|
}
|
|
523
|
+
|
|
430
524
|
// Read trailing whitespace and newlines.
|
|
431
525
|
this.readWhitespace();
|
|
432
526
|
while (this.nextIsWhitespace()) {
|
|
@@ -435,19 +529,23 @@ export default class Parser {
|
|
|
435
529
|
// Read whitespace before the next block.
|
|
436
530
|
this.readWhitespace();
|
|
437
531
|
}
|
|
532
|
+
|
|
438
533
|
// Stop if we reach an empty paragraph.
|
|
439
|
-
if (this.nextIsEmptyParagraph())
|
|
440
|
-
break;
|
|
534
|
+
if (this.nextIsEmptyParagraph()) break;
|
|
441
535
|
}
|
|
442
536
|
return new ListNode(items, numbered);
|
|
443
537
|
}
|
|
444
|
-
|
|
538
|
+
|
|
539
|
+
parseCode(): CodeNode {
|
|
445
540
|
// Parse the back tick
|
|
446
541
|
this.read();
|
|
542
|
+
|
|
447
543
|
// Parse through the next new line
|
|
448
544
|
let language = this.readUntilNewLine();
|
|
545
|
+
|
|
449
546
|
// Read the newline
|
|
450
547
|
this.read();
|
|
548
|
+
|
|
451
549
|
// Read until we encounter a closing back tick.
|
|
452
550
|
let code = '';
|
|
453
551
|
while (this.more() && !this.nextIs('`')) {
|
|
@@ -460,142 +558,172 @@ export default class Parser {
|
|
|
460
558
|
}
|
|
461
559
|
code = code + next;
|
|
462
560
|
}
|
|
561
|
+
|
|
463
562
|
// Trim the code.
|
|
464
563
|
code = code.trim();
|
|
564
|
+
|
|
465
565
|
// Read the backtick.
|
|
466
|
-
if (this.nextIs('`'))
|
|
467
|
-
|
|
566
|
+
if (this.nextIs('`')) this.read();
|
|
567
|
+
|
|
468
568
|
let position = this.parsePosition();
|
|
569
|
+
|
|
469
570
|
// Read the caption. Note that parsing inline content stops at a newline,
|
|
470
571
|
// so if there's a line break after the last row, there won't be a caption.
|
|
471
572
|
const caption = this.parseFormat();
|
|
573
|
+
|
|
472
574
|
return new CodeNode(new TextNode(code), language, position, caption);
|
|
473
575
|
}
|
|
474
|
-
|
|
475
|
-
|
|
576
|
+
|
|
577
|
+
parsePosition(): Position {
|
|
578
|
+
let position: Position = '|';
|
|
476
579
|
// Is there a position indicator?
|
|
477
580
|
if (this.nextIs('<')) {
|
|
478
581
|
position = '<';
|
|
479
582
|
this.read();
|
|
480
|
-
}
|
|
481
|
-
else if (this.nextIs('>')) {
|
|
583
|
+
} else if (this.nextIs('>')) {
|
|
482
584
|
position = '>';
|
|
483
585
|
this.read();
|
|
484
586
|
}
|
|
587
|
+
|
|
485
588
|
return position;
|
|
486
589
|
}
|
|
487
|
-
|
|
488
|
-
|
|
590
|
+
|
|
591
|
+
parseQuote(): QuoteNode {
|
|
592
|
+
const blocks: BlockNode[] = [];
|
|
593
|
+
|
|
489
594
|
// Parse the ", then any whitespace, then the newline
|
|
490
595
|
this.read();
|
|
596
|
+
|
|
491
597
|
// Then read any whitespace after the quote
|
|
492
598
|
this.readWhitespace();
|
|
599
|
+
|
|
493
600
|
// Then read the newline.
|
|
494
601
|
this.read();
|
|
602
|
+
|
|
495
603
|
while (this.more() && !this.nextIs('"')) {
|
|
496
604
|
// Read a block
|
|
497
605
|
const block = this.parseBlock();
|
|
498
606
|
// Add it to the list if we parsed something.
|
|
499
|
-
if (block !== null)
|
|
500
|
-
blocks.push(block);
|
|
607
|
+
if (block !== null) blocks.push(block);
|
|
501
608
|
// Read whitespace until we find the next thing.
|
|
502
|
-
while (this.nextIsWhitespace())
|
|
503
|
-
this.read();
|
|
609
|
+
while (this.nextIsWhitespace()) this.read();
|
|
504
610
|
}
|
|
611
|
+
|
|
505
612
|
// Read the closing " and the whitespace that follows.
|
|
506
613
|
this.read();
|
|
614
|
+
|
|
507
615
|
// Is there a position indicator?
|
|
508
616
|
const position = this.parsePosition();
|
|
617
|
+
|
|
509
618
|
// Read any whitespace after the position indicator.
|
|
510
619
|
this.readWhitespace();
|
|
620
|
+
|
|
511
621
|
// Read the credit.
|
|
512
622
|
const credit = this.nextIs('\n') ? undefined : this.parseFormat();
|
|
623
|
+
|
|
513
624
|
return new QuoteNode(blocks, credit, position);
|
|
514
625
|
}
|
|
515
|
-
|
|
516
|
-
|
|
626
|
+
|
|
627
|
+
parseCallout(): CalloutNode {
|
|
628
|
+
const blocks: BlockNode[] = [];
|
|
629
|
+
|
|
517
630
|
// Parse the = ...
|
|
518
631
|
this.read();
|
|
632
|
+
|
|
519
633
|
// ...then any whitespace
|
|
520
634
|
this.readWhitespace();
|
|
635
|
+
|
|
521
636
|
// ...then read the newline.
|
|
522
637
|
this.read();
|
|
638
|
+
|
|
523
639
|
// Then, read until we find a closing _
|
|
524
640
|
while (this.more() && !this.nextIs('=')) {
|
|
525
641
|
// Read a block
|
|
526
642
|
const block = this.parseBlock();
|
|
527
643
|
// Add it to the list if we parsed something.
|
|
528
|
-
if (block !== null)
|
|
529
|
-
blocks.push(block);
|
|
644
|
+
if (block !== null) blocks.push(block);
|
|
530
645
|
// Read whitespace until we find the next thing.
|
|
531
|
-
while (
|
|
646
|
+
while (
|
|
647
|
+
this.peek() === ' ' ||
|
|
532
648
|
this.peek() === '\t' ||
|
|
533
|
-
this.peek() === '\n'
|
|
649
|
+
this.peek() === '\n'
|
|
650
|
+
)
|
|
534
651
|
this.read();
|
|
535
652
|
}
|
|
653
|
+
|
|
536
654
|
// Read the closing =
|
|
537
655
|
this.read();
|
|
656
|
+
|
|
538
657
|
// Is there a position indicator?
|
|
539
658
|
const position = this.parsePosition();
|
|
659
|
+
|
|
540
660
|
// Read whitespace that follows.
|
|
541
661
|
this.readWhitespace();
|
|
662
|
+
|
|
542
663
|
return new CalloutNode(blocks, position);
|
|
543
664
|
}
|
|
544
|
-
|
|
545
|
-
|
|
665
|
+
|
|
666
|
+
parseTable(): TableNode {
|
|
667
|
+
const rows: FormatNode[][] = [];
|
|
668
|
+
|
|
546
669
|
// Parse rows until the lines stop starting with ,
|
|
547
670
|
while (this.more() && this.nextIs(',')) {
|
|
548
671
|
let row = [];
|
|
672
|
+
|
|
549
673
|
while (this.more() && !this.nextIs('\n')) {
|
|
550
674
|
// Read the starting , or next |
|
|
551
675
|
this.read();
|
|
676
|
+
|
|
552
677
|
// Read whitespace that follows.
|
|
553
678
|
this.readWhitespace();
|
|
679
|
+
|
|
554
680
|
// Read content until reaching another | or the end of the line.
|
|
555
681
|
row.push(this.parseFormat('|'));
|
|
556
682
|
}
|
|
683
|
+
|
|
557
684
|
// Add the row.
|
|
558
685
|
rows.push(row);
|
|
686
|
+
|
|
559
687
|
// Read the newline
|
|
560
688
|
this.read();
|
|
561
689
|
}
|
|
690
|
+
|
|
562
691
|
// Read the position indicator if there is one.
|
|
563
692
|
const position = this.parsePosition();
|
|
693
|
+
|
|
564
694
|
// Read the caption. Note that parsing inline content stops at a newline,
|
|
565
695
|
// so if there's a line break after the last row, there won't be a caption.
|
|
566
696
|
const caption = this.parseFormat();
|
|
697
|
+
|
|
567
698
|
// Return the new table.
|
|
568
699
|
return new TableNode(rows, position, caption);
|
|
569
700
|
}
|
|
701
|
+
|
|
570
702
|
// The "awaiting" argument keeps track of upstream formatting. We don't need a stack here
|
|
571
703
|
// because we don't allow infinite nesting of the same formatting type.
|
|
572
|
-
parseFormat(awaiting) {
|
|
573
|
-
const segments = [];
|
|
704
|
+
parseFormat(awaiting?: string): FormatNode {
|
|
705
|
+
const segments: FormatNodeSegmentType[] = [];
|
|
706
|
+
|
|
574
707
|
// Read until hitting a delimiter.
|
|
575
708
|
while (this.more() && !this.nextIs('\n')) {
|
|
576
709
|
const next = this.peek();
|
|
577
710
|
const charAfterNext = this.charAfterNext();
|
|
711
|
+
|
|
578
712
|
// Parse some bold, italic, subscript, superscript
|
|
579
713
|
if (next === '_' || next === '*' || next === '^')
|
|
580
714
|
segments.push(this.parseStyle(next));
|
|
581
715
|
// Parse unformatted text
|
|
582
|
-
else if (this.nextIs('`'))
|
|
583
|
-
segments.push(this.parseInlineCode());
|
|
716
|
+
else if (this.nextIs('`')) segments.push(this.parseInlineCode());
|
|
584
717
|
// Parse a citation list
|
|
585
|
-
else if (this.nextIs('<'))
|
|
586
|
-
segments.push(this.parseCitations());
|
|
718
|
+
else if (this.nextIs('<')) segments.push(this.parseCitations());
|
|
587
719
|
// Parse a footnote
|
|
588
|
-
else if (this.nextIs('{'))
|
|
589
|
-
segments.push(this.parseFootnote());
|
|
720
|
+
else if (this.nextIs('{')) segments.push(this.parseFootnote());
|
|
590
721
|
// Parse a definition
|
|
591
|
-
else if (this.nextIs('~'))
|
|
592
|
-
segments.push(this.parseDefinition());
|
|
722
|
+
else if (this.nextIs('~')) segments.push(this.parseDefinition());
|
|
593
723
|
// Parse an escaped character
|
|
594
|
-
else if (this.nextIs('\\'))
|
|
595
|
-
segments.push(this.parseEscaped());
|
|
724
|
+
else if (this.nextIs('\\')) segments.push(this.parseEscaped());
|
|
596
725
|
// Parse a link
|
|
597
|
-
else if (this.nextIs('['))
|
|
598
|
-
segments.push(this.parseLink());
|
|
726
|
+
else if (this.nextIs('[')) segments.push(this.parseLink());
|
|
599
727
|
// Parse inline comments
|
|
600
728
|
else if (this.charBeforeNext() === ' ' && this.nextIs('%'))
|
|
601
729
|
segments.push(this.parseComment());
|
|
@@ -610,53 +738,70 @@ export default class Parser {
|
|
|
610
738
|
symbol = symbol + this.read();
|
|
611
739
|
next = this.peek();
|
|
612
740
|
}
|
|
613
|
-
segments.push(
|
|
741
|
+
segments.push(
|
|
742
|
+
new ErrorNode(undefined, "Couldn't find symbol @" + symbol)
|
|
743
|
+
);
|
|
614
744
|
}
|
|
615
745
|
// Parse a label
|
|
616
|
-
else if (
|
|
746
|
+
else if (
|
|
747
|
+
next === ':' &&
|
|
617
748
|
charAfterNext !== null &&
|
|
618
|
-
charAfterNext.match(/[a-z]/i)
|
|
749
|
+
charAfterNext.match(/[a-z]/i)
|
|
750
|
+
) {
|
|
619
751
|
segments.push(this.parseLabel());
|
|
620
752
|
}
|
|
621
753
|
// Keep reading text until finding a delimiter.
|
|
622
754
|
else {
|
|
623
755
|
let text = '';
|
|
624
|
-
while (
|
|
756
|
+
while (
|
|
757
|
+
this.more() &&
|
|
625
758
|
(!awaiting || !this.nextIs(awaiting)) &&
|
|
626
759
|
!this.nextIsContentDelimiter() &&
|
|
627
|
-
!this.nextIs('\n')
|
|
760
|
+
!this.nextIs('\n')
|
|
761
|
+
)
|
|
628
762
|
text = text + this.read();
|
|
629
763
|
segments.push(new TextNode(text));
|
|
630
764
|
}
|
|
765
|
+
|
|
631
766
|
// If we've reached a delimiter we're waiting for, then stop parsing, so it can handle it. Otherwise, we'll keep reading.
|
|
632
|
-
if (this.peek() === awaiting)
|
|
633
|
-
break;
|
|
767
|
+
if (this.peek() === awaiting) break;
|
|
634
768
|
}
|
|
769
|
+
|
|
635
770
|
return new FormatNode('', segments);
|
|
636
771
|
}
|
|
637
|
-
|
|
772
|
+
|
|
773
|
+
parseEmbed(): EmbedNode {
|
|
638
774
|
// Read |
|
|
639
775
|
this.read();
|
|
776
|
+
|
|
640
777
|
// Read the URL
|
|
641
778
|
const url = this.readUntilNewlineOr('|');
|
|
779
|
+
|
|
642
780
|
let description;
|
|
643
781
|
let caption;
|
|
644
782
|
let credit;
|
|
783
|
+
|
|
645
784
|
if (this.peek() === '|') {
|
|
646
785
|
// Read a |
|
|
647
786
|
this.read();
|
|
787
|
+
|
|
648
788
|
// Read the description
|
|
649
789
|
description = this.readUntilNewlineOr('|');
|
|
790
|
+
|
|
650
791
|
if (this.peek() === '|') {
|
|
651
792
|
// Read a |
|
|
652
793
|
this.read();
|
|
794
|
+
|
|
653
795
|
// Parse the caption
|
|
654
796
|
caption = this.parseFormat('|');
|
|
797
|
+
|
|
655
798
|
if (this.peek() === '|') {
|
|
656
799
|
// Read a |
|
|
657
800
|
this.read();
|
|
801
|
+
|
|
658
802
|
// Parse the credit
|
|
659
803
|
credit = this.parseFormat('|');
|
|
804
|
+
|
|
660
805
|
// Check for the closing delimeter
|
|
661
806
|
if (this.peek() === '|')
|
|
662
807
|
// Read a |
|
|
@@ -664,23 +809,30 @@ export default class Parser {
|
|
|
664
809
|
}
|
|
665
810
|
}
|
|
666
811
|
}
|
|
812
|
+
|
|
667
813
|
// Is there a position indicator?
|
|
668
814
|
const position = this.parsePosition();
|
|
815
|
+
|
|
669
816
|
return new EmbedNode(url, description ?? '', caption, credit, position);
|
|
670
817
|
}
|
|
671
|
-
|
|
818
|
+
|
|
819
|
+
parseComment(): CommentNode {
|
|
672
820
|
// Consume the opening %
|
|
673
821
|
this.read();
|
|
822
|
+
|
|
674
823
|
// Consume everything until the next %.
|
|
675
824
|
const comment = this.parseFormat('%');
|
|
825
|
+
|
|
676
826
|
// Consume the closing %, if we didn't reach the end of input or a newline.
|
|
677
|
-
if (this.peek() === '%')
|
|
678
|
-
|
|
827
|
+
if (this.peek() === '%') this.read();
|
|
828
|
+
|
|
679
829
|
return new CommentNode(comment);
|
|
680
830
|
}
|
|
681
|
-
|
|
831
|
+
|
|
832
|
+
parseLabel(): LabelNode | ErrorNode {
|
|
682
833
|
// Consume the :
|
|
683
834
|
this.read();
|
|
835
|
+
|
|
684
836
|
// Consume everything until it's not a letter.
|
|
685
837
|
let id = '';
|
|
686
838
|
let next = this.peek();
|
|
@@ -688,29 +840,36 @@ export default class Parser {
|
|
|
688
840
|
id = id + this.read();
|
|
689
841
|
next = this.peek();
|
|
690
842
|
}
|
|
843
|
+
|
|
691
844
|
return new LabelNode(id);
|
|
692
845
|
}
|
|
693
|
-
|
|
846
|
+
|
|
847
|
+
parseStyle(awaiting: string): FormatNode | ErrorNode {
|
|
694
848
|
// Remember what we're matching.
|
|
695
849
|
const delimeter = this.read();
|
|
696
850
|
let subscript = false;
|
|
697
|
-
const segments = [];
|
|
851
|
+
const segments: Array<FormatNode | TextNode | ErrorNode> = [];
|
|
698
852
|
let text = '';
|
|
853
|
+
|
|
699
854
|
// Special case subscript, which has an extra delimeter.
|
|
700
855
|
if (delimeter === '^' && this.peek() === 'v') {
|
|
701
856
|
this.read();
|
|
702
857
|
subscript = true;
|
|
703
858
|
}
|
|
859
|
+
|
|
704
860
|
if (delimeter === null)
|
|
705
|
-
return new ErrorNode(
|
|
861
|
+
return new ErrorNode(
|
|
862
|
+
undefined,
|
|
863
|
+
'Somehow parsing formatted text at end of file.'
|
|
864
|
+
);
|
|
865
|
+
|
|
706
866
|
// Read some content until reaching the delimiter or the end of the line
|
|
707
867
|
while (this.more() && this.peek() !== delimeter && !this.nextIs('\n')) {
|
|
708
868
|
// If this is more formatted text, make a text node with whatever we've accumulated so far,
|
|
709
869
|
// then parse the formatted text, then reset the accumulator.
|
|
710
870
|
if (this.nextIsContentDelimiter()) {
|
|
711
871
|
// If the text is a non-empty string, make a text node with what we've accumulated.
|
|
712
|
-
if (text !== '')
|
|
713
|
-
segments.push(new TextNode(text));
|
|
872
|
+
if (text !== '') segments.push(new TextNode(text));
|
|
714
873
|
// Parse the formatted content.
|
|
715
874
|
segments.push(this.parseFormat(awaiting));
|
|
716
875
|
// Reset the accumulator.
|
|
@@ -721,20 +880,25 @@ export default class Parser {
|
|
|
721
880
|
text = text + this.read();
|
|
722
881
|
}
|
|
723
882
|
}
|
|
883
|
+
|
|
724
884
|
// If there's more text, save it!
|
|
725
|
-
if (text !== '')
|
|
726
|
-
|
|
885
|
+
if (text !== '') segments.push(new TextNode(text));
|
|
886
|
+
|
|
727
887
|
// Read the closing delimeter
|
|
728
|
-
if (this.nextIs(delimeter))
|
|
729
|
-
this.read();
|
|
888
|
+
if (this.nextIs(delimeter)) this.read();
|
|
730
889
|
// If it wasn't closed, add an error
|
|
731
|
-
else
|
|
732
|
-
|
|
733
|
-
return new FormatNode(
|
|
734
|
-
|
|
735
|
-
|
|
890
|
+
else segments.push(new ErrorNode(undefined, 'Unclosed ' + delimeter));
|
|
891
|
+
|
|
892
|
+
return new FormatNode(
|
|
893
|
+
subscript ? 'v' : (delimeter as Format),
|
|
894
|
+
segments
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
parseInlineCode(): InlineCodeNode {
|
|
736
899
|
// Parse the back tick
|
|
737
900
|
this.read();
|
|
901
|
+
|
|
738
902
|
// Read until we encounter a closing back tick.
|
|
739
903
|
let code = '';
|
|
740
904
|
while (this.more() && !this.nextIs('`')) {
|
|
@@ -747,9 +911,10 @@ export default class Parser {
|
|
|
747
911
|
}
|
|
748
912
|
code = code + next;
|
|
749
913
|
}
|
|
914
|
+
|
|
750
915
|
// Read the backtick.
|
|
751
|
-
if (this.nextIs('`'))
|
|
752
|
-
|
|
916
|
+
if (this.nextIs('`')) this.read();
|
|
917
|
+
|
|
753
918
|
// If there's a letter immediately after a backtick, it's a language for an inline code name
|
|
754
919
|
let language = '';
|
|
755
920
|
let next = this.peek();
|
|
@@ -758,42 +923,52 @@ export default class Parser {
|
|
|
758
923
|
language = language + this.read();
|
|
759
924
|
next = this.peek();
|
|
760
925
|
} while (next !== null && /^[a-z]$/.test(next));
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
language = 'plaintext';
|
|
926
|
+
} else language = 'plaintext';
|
|
927
|
+
|
|
764
928
|
return new InlineCodeNode(new TextNode(code), language);
|
|
765
929
|
}
|
|
766
|
-
|
|
930
|
+
|
|
931
|
+
parseCitations(): CitationsNode {
|
|
767
932
|
let citations = '';
|
|
933
|
+
|
|
768
934
|
// Read the <
|
|
769
935
|
this.read();
|
|
770
936
|
// Read the citations.
|
|
771
937
|
citations = this.readUntilNewlineOr('>');
|
|
772
|
-
if (this.peek() === '>')
|
|
773
|
-
|
|
938
|
+
if (this.peek() === '>') this.read();
|
|
939
|
+
|
|
774
940
|
// Trim any whitespace, then split by commas, then remove any empty IDs.
|
|
775
941
|
const citationList = citations
|
|
776
942
|
.split(',')
|
|
777
943
|
.map((citation) => citation.trim())
|
|
778
944
|
.filter((citationID) => citationID.length > 0);
|
|
945
|
+
|
|
779
946
|
return new CitationsNode(citationList);
|
|
780
947
|
}
|
|
781
|
-
|
|
948
|
+
|
|
949
|
+
parseFootnote(): FootnoteNode {
|
|
782
950
|
// Read the {
|
|
783
951
|
this.read();
|
|
952
|
+
|
|
784
953
|
// Read the footnote content.
|
|
785
954
|
const footnote = this.parseFormat('}');
|
|
955
|
+
|
|
786
956
|
// Read the closing }
|
|
787
957
|
this.read();
|
|
958
|
+
|
|
788
959
|
return new FootnoteNode(footnote);
|
|
789
960
|
}
|
|
790
|
-
|
|
961
|
+
|
|
962
|
+
parseDefinition(): DefinitionNode {
|
|
791
963
|
// Read the ~
|
|
792
964
|
this.read();
|
|
965
|
+
|
|
793
966
|
// Read the phrase
|
|
794
967
|
const text = this.readUntilNewlineOr('~');
|
|
968
|
+
|
|
795
969
|
// Read the closing ~
|
|
796
970
|
this.read();
|
|
971
|
+
|
|
797
972
|
// Read the glossary entry ID
|
|
798
973
|
let glossaryID = '';
|
|
799
974
|
// Stop at the end of the name or file.
|
|
@@ -802,37 +977,47 @@ export default class Parser {
|
|
|
802
977
|
glossaryID = glossaryID + this.read();
|
|
803
978
|
next = this.peek();
|
|
804
979
|
}
|
|
980
|
+
|
|
805
981
|
return new DefinitionNode(new TextNode(text), glossaryID);
|
|
806
982
|
}
|
|
807
|
-
|
|
983
|
+
|
|
984
|
+
parseEscaped(): TextNode | ErrorNode {
|
|
808
985
|
// Skip the scape and just add the next character.
|
|
809
986
|
this.read();
|
|
810
987
|
const char = this.read();
|
|
811
|
-
if (char)
|
|
812
|
-
|
|
988
|
+
if (char) return new TextNode(char);
|
|
989
|
+
|
|
813
990
|
return new ErrorNode(undefined, 'Unterminated escape.');
|
|
814
991
|
}
|
|
815
|
-
|
|
992
|
+
|
|
993
|
+
parseLink(): LinkNode | ErrorNode {
|
|
816
994
|
// Read the [
|
|
817
995
|
this.read();
|
|
996
|
+
|
|
818
997
|
// Read pure text until funding |
|
|
819
998
|
const text = this.readUntilNewlineOr('|');
|
|
999
|
+
|
|
820
1000
|
// Catch missing bars
|
|
821
1001
|
if (this.peek() !== '|') {
|
|
822
1002
|
this.readUntilNewLine();
|
|
823
1003
|
return new ErrorNode(undefined, "Missing '|' in link");
|
|
824
1004
|
}
|
|
1005
|
+
|
|
825
1006
|
// Read the |
|
|
826
1007
|
this.read();
|
|
1008
|
+
|
|
827
1009
|
// Read the link
|
|
828
1010
|
let url = this.readUntilNewlineOr(']');
|
|
1011
|
+
|
|
829
1012
|
// Catch missing closing
|
|
830
1013
|
if (this.peek() !== ']') {
|
|
831
1014
|
this.readUntilNewLine();
|
|
832
1015
|
return new ErrorNode(undefined, 'Missing ] in link');
|
|
833
1016
|
}
|
|
1017
|
+
|
|
834
1018
|
// Read the ]
|
|
835
1019
|
this.read();
|
|
1020
|
+
|
|
836
1021
|
return new LinkNode(new TextNode(text), url);
|
|
837
1022
|
}
|
|
838
1023
|
}
|