bookish-press 0.4.1 → 0.4.16
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/README.md +3 -1
- package/components/Auth.svelte +19 -14
- package/components/Auth.svelte.d.ts +4 -4
- package/components/Authentication.d.ts +2 -2
- package/components/BookPreview.svelte +77 -59
- package/components/BookPreview.svelte.d.ts +5 -5
- package/components/External.svelte +1 -1
- package/components/External.svelte.d.ts +3 -3
- package/components/Link.svelte +49 -3
- package/components/Link.svelte.d.ts +3 -4
- package/components/app/BookList.svelte +19 -0
- package/components/app/BookList.svelte.d.ts +18 -0
- package/components/app/Button.svelte +49 -0
- package/components/app/Button.svelte.d.ts +22 -0
- package/components/app/Feedback.svelte +45 -0
- package/components/app/Feedback.svelte.d.ts +18 -0
- package/components/app/Head.svelte +12 -0
- package/components/app/Head.svelte.d.ts +27 -0
- package/components/app/Large.svelte +8 -0
- package/components/app/Large.svelte.d.ts +27 -0
- package/components/app/Lead.svelte +12 -0
- package/components/app/Lead.svelte.d.ts +27 -0
- package/components/app/Link.svelte +24 -0
- package/components/app/Link.svelte.d.ts +20 -0
- package/components/app/Options.svelte +24 -0
- package/components/app/Options.svelte.d.ts +19 -0
- package/components/app/Paragraph.svelte +19 -0
- package/components/app/Paragraph.svelte.d.ts +18 -0
- package/components/app/Table.svelte +32 -0
- package/components/app/Table.svelte.d.ts +27 -0
- package/components/app/TextInput.svelte +37 -0
- package/components/app/TextInput.svelte.d.ts +22 -0
- package/components/app/Writing.svelte +13 -0
- package/components/app/Writing.svelte.d.ts +27 -0
- package/components/chapter/Atom.svelte +20 -6
- package/components/chapter/Atom.svelte.d.ts +3 -3
- package/components/chapter/Block.svelte +23 -20
- package/components/chapter/Block.svelte.d.ts +4 -4
- package/components/chapter/Callout.svelte +38 -7
- package/components/chapter/Callout.svelte.d.ts +4 -4
- package/components/chapter/CaptionedCode.svelte +66 -23
- package/components/chapter/CaptionedCode.svelte.d.ts +4 -4
- package/components/chapter/ChapterBody.svelte +61 -9
- package/components/chapter/ChapterBody.svelte.d.ts +4 -4
- package/components/chapter/Citations.svelte +86 -20
- package/components/chapter/Citations.svelte.d.ts +4 -4
- package/components/chapter/Code.svelte +152 -21
- package/components/chapter/Code.svelte.d.ts +3 -3
- package/components/chapter/Comment.svelte +38 -16
- package/components/chapter/Comment.svelte.d.ts +3 -3
- package/components/chapter/Definition.svelte +52 -18
- package/components/chapter/Definition.svelte.d.ts +5 -8
- package/components/chapter/Embed.svelte +154 -66
- package/components/chapter/Embed.svelte.d.ts +5 -4
- package/components/chapter/ErrorMessage.svelte +7 -2
- package/components/chapter/ErrorMessage.svelte.d.ts +4 -4
- package/components/chapter/ExtendedPrism.d.ts +2 -0
- package/components/chapter/ExtendedPrism.js +69 -0
- package/components/chapter/Figure.svelte +90 -0
- package/components/chapter/Figure.svelte.d.ts +24 -0
- package/components/chapter/Footnote.svelte +75 -12
- package/components/chapter/Footnote.svelte.d.ts +4 -4
- package/components/chapter/Format.svelte +60 -37
- package/components/chapter/Format.svelte.d.ts +4 -4
- package/components/chapter/InlineCode.svelte +15 -5
- package/components/chapter/InlineCode.svelte.d.ts +4 -4
- package/components/chapter/Label.svelte +37 -8
- package/components/chapter/Label.svelte.d.ts +4 -4
- package/components/chapter/Link.svelte +23 -18
- package/components/chapter/Link.svelte.d.ts +4 -4
- package/components/chapter/List.svelte +75 -8
- package/components/chapter/List.svelte.d.ts +4 -4
- package/components/chapter/Marginal.svelte +169 -27
- package/components/chapter/Marginal.svelte.d.ts +6 -3
- package/components/chapter/Paragraph.svelte +74 -6
- package/components/chapter/Paragraph.svelte.d.ts +4 -4
- package/components/chapter/Positioned.svelte +33 -0
- package/components/chapter/Positioned.svelte.d.ts +19 -0
- package/components/chapter/Problem.svelte +15 -0
- package/components/chapter/Problem.svelte.d.ts +27 -0
- package/components/chapter/Python.svelte +68 -21
- package/components/chapter/Python.svelte.d.ts +4 -4
- package/components/chapter/Quote.svelte +64 -11
- package/components/chapter/Quote.svelte.d.ts +4 -4
- package/components/chapter/Rule.svelte +12 -1
- package/components/chapter/Rule.svelte.d.ts +4 -4
- package/components/chapter/Table.svelte +36 -25
- package/components/chapter/Table.svelte.d.ts +4 -4
- package/components/chapter/Text.svelte +61 -36
- package/components/chapter/Text.svelte.d.ts +5 -4
- package/components/editor/BookishEditor.svelte +343 -237
- package/components/editor/BookishEditor.svelte.d.ts +5 -5
- package/components/editor/CalloutEditor.svelte +5 -5
- package/components/editor/CalloutEditor.svelte.d.ts +4 -4
- package/components/editor/CaptionedCodeEditor.svelte +16 -12
- package/components/editor/CaptionedCodeEditor.svelte.d.ts +4 -4
- package/components/editor/CaretContext.d.ts +48 -16
- package/components/editor/CaretState.d.ts +16 -44
- package/components/editor/CaretUtilities.d.ts +2 -2
- package/components/editor/CaretView.svelte +80 -0
- package/components/editor/CaretView.svelte.d.ts +24 -0
- package/components/editor/CitationsEditor.svelte +36 -25
- package/components/editor/CitationsEditor.svelte.d.ts +4 -4
- package/components/editor/Clipboard.d.ts +2 -2
- package/components/editor/Command.d.ts +13 -12
- package/components/editor/Commands.d.ts +1 -1
- package/components/editor/Commands.js +1114 -571
- package/components/editor/ConfirmButton.svelte +18 -12
- package/components/editor/ConfirmButton.svelte.d.ts +5 -4
- package/components/editor/DefinitionEditor.svelte +29 -21
- package/components/editor/DefinitionEditor.svelte.d.ts +4 -4
- package/components/editor/EmbedEditor.svelte +93 -43
- package/components/editor/EmbedEditor.svelte.d.ts +3 -3
- package/components/editor/Icon.svelte +17 -0
- package/components/editor/Icon.svelte.d.ts +16 -0
- package/components/editor/ImageChooser.svelte +53 -34
- package/components/editor/ImageChooser.svelte.d.ts +3 -3
- package/components/editor/InlineCodeEditor.svelte +7 -4
- package/components/editor/InlineCodeEditor.svelte.d.ts +4 -4
- package/components/editor/LabelEditor.svelte +20 -11
- package/components/editor/LabelEditor.svelte.d.ts +4 -4
- package/components/editor/LanguageEditor.svelte +10 -7
- package/components/editor/LanguageEditor.svelte.d.ts +3 -3
- package/components/editor/LinkEditor.svelte +64 -39
- package/components/editor/LinkEditor.svelte.d.ts +4 -4
- package/components/editor/Note.svelte +3 -3
- package/components/editor/Note.svelte.d.ts +6 -2
- package/components/editor/PositionEditor.svelte +9 -6
- package/components/editor/PositionEditor.svelte.d.ts +4 -4
- package/components/editor/QuoteEditor.svelte +7 -2
- package/components/editor/QuoteEditor.svelte.d.ts +4 -4
- package/components/editor/Switch.svelte +55 -28
- package/components/editor/Switch.svelte.d.ts +4 -4
- package/components/editor/TableEditor.svelte +10 -0
- package/components/editor/TableEditor.svelte.d.ts +17 -0
- package/components/editor/TextEditor.svelte +83 -45
- package/components/editor/TextEditor.svelte.d.ts +5 -4
- package/components/editor/Toggle.svelte +11 -8
- package/components/editor/Toggle.svelte.d.ts +4 -4
- package/components/editor/Toolbar.svelte +192 -144
- package/components/editor/Toolbar.svelte.d.ts +5 -8
- package/components/editor/ToolbarGroup.svelte +18 -23
- package/components/editor/ToolbarGroup.svelte.d.ts +3 -4
- package/components/editor/ToolbarSpacer.svelte +8 -1
- package/components/editor/ToolbarSpacer.svelte.d.ts +6 -2
- package/components/editor/URLEditor.svelte +6 -8
- package/components/editor/URLEditor.svelte.d.ts +3 -3
- package/components/editor/UndoState.d.ts +3 -3
- package/components/editor/icons/annotate.svg +1 -0
- package/components/editor/icons/block.svg +1 -0
- package/components/editor/icons/bold.svg +1 -0
- package/components/editor/icons/bullets.svg +1 -0
- package/components/editor/icons/callout.svg +1 -0
- package/components/editor/icons/citation.svg +8 -0
- package/components/editor/icons/clear.svg +1 -0
- package/components/editor/icons/clipboard.svg +1 -0
- package/components/editor/icons/code.svg +1 -0
- package/components/editor/icons/columnafter.svg +1 -0
- package/components/editor/icons/columnbefore.svg +1 -0
- package/components/editor/icons/comment.svg +1 -0
- package/components/editor/icons/copy.svg +1 -0
- package/components/editor/icons/cut.svg +1 -0
- package/components/editor/icons/define.svg +7 -0
- package/components/editor/icons/deletecolumn.svg +1 -0
- package/components/editor/icons/deleterow.svg +1 -0
- package/components/editor/icons/footnote.svg +8 -0
- package/components/editor/icons/header1.svg +7 -0
- package/components/editor/icons/header2.svg +7 -0
- package/components/editor/icons/header3.svg +7 -0
- package/components/editor/icons/home.svg +1 -0
- package/components/editor/icons/indent.svg +1 -0
- package/components/editor/icons/italic.svg +1 -0
- package/components/editor/icons/label.svg +1 -0
- package/components/editor/icons/left.svg +1 -0
- package/components/editor/icons/level.svg +1 -0
- package/components/editor/icons/link.svg +1 -0
- package/components/editor/icons/list.svg +1 -0
- package/components/editor/icons/media.svg +1 -0
- package/components/editor/icons/middle.svg +1 -0
- package/components/editor/icons/numbers.svg +10 -0
- package/components/editor/icons/paragraph.svg +1 -0
- package/components/editor/icons/paste.svg +10 -0
- package/components/editor/icons/quote.svg +1 -0
- package/components/editor/icons/redo.svg +1 -0
- package/components/editor/icons/right.svg +1 -0
- package/components/editor/icons/rowabove.svg +1 -0
- package/components/editor/icons/rowbelow.svg +1 -0
- package/components/editor/icons/rule.svg +1 -0
- package/components/editor/icons/sub.svg +1 -0
- package/components/editor/icons/super.svg +1 -0
- package/components/editor/icons/table.svg +1 -0
- package/components/editor/icons/text.svg +1 -0
- package/components/editor/icons/time.svg +1 -0
- package/components/editor/icons/undo.svg +1 -0
- package/components/editor/icons/unindent.svg +1 -0
- package/components/editor/icons/unlink.svg +1 -0
- package/components/page/Acknowledgements.svelte +31 -22
- package/components/page/Acknowledgements.svelte.d.ts +4 -4
- package/components/page/Authors.svelte +34 -14
- package/components/page/Authors.svelte.d.ts +6 -6
- package/components/page/BulkReferenceEditor.svelte +53 -22
- package/components/page/BulkReferenceEditor.svelte.d.ts +4 -4
- package/components/page/Chapter.svelte +196 -141
- package/components/page/Chapter.svelte.d.ts +3 -3
- package/components/page/ChapterContext.d.ts +4 -4
- package/components/page/ChapterNumber.svelte +9 -0
- package/components/page/ChapterNumber.svelte.d.ts +27 -0
- package/components/page/ChapterTitle.svelte +16 -0
- package/components/page/ChapterTitle.svelte.d.ts +18 -0
- package/components/page/Contexts.d.ts +31 -20
- package/components/page/Contexts.js +47 -17
- package/components/page/DefinitionView.svelte +115 -86
- package/components/page/DefinitionView.svelte.d.ts +3 -3
- package/components/page/Description.svelte +27 -18
- package/components/page/Description.svelte.d.ts +4 -4
- package/components/page/Edition.svelte +127 -75
- package/components/page/Edition.svelte.d.ts +4 -4
- package/components/page/Editions.svelte +144 -0
- package/components/page/Editions.svelte.d.ts +14 -0
- package/components/page/Glossary.svelte +57 -48
- package/components/page/Glossary.svelte.d.ts +4 -4
- package/components/page/Header.svelte +129 -44
- package/components/page/Header.svelte.d.ts +6 -6
- package/components/page/Index.svelte +114 -80
- package/components/page/Index.svelte.d.ts +4 -4
- package/components/page/Instructions.svelte +18 -16
- package/components/page/Instructions.svelte.d.ts +4 -4
- package/components/page/License.svelte +29 -21
- package/components/page/License.svelte.d.ts +4 -4
- package/components/page/Loading.svelte +102 -12
- package/components/page/Loading.svelte.d.ts +6 -2
- package/components/page/Media.svelte +77 -51
- package/components/page/Media.svelte.d.ts +4 -4
- package/components/page/MediaPreview.svelte +26 -8
- package/components/page/MediaPreview.svelte.d.ts +3 -3
- package/components/page/Muted.svelte +10 -0
- package/components/page/Muted.svelte.d.ts +27 -0
- package/components/page/Outline.svelte +279 -59
- package/components/page/Outline.svelte.d.ts +3 -3
- package/components/page/Page.svelte +40 -9
- package/components/page/Page.svelte.d.ts +3 -3
- package/components/page/PageHeader.svelte +14 -0
- package/components/page/PageHeader.svelte.d.ts +18 -0
- package/components/page/PageParagraph.svelte +18 -0
- package/components/page/PageParagraph.svelte.d.ts +27 -0
- package/components/page/PossibleChapter.svelte +7 -7
- package/components/page/PossibleChapter.svelte.d.ts +4 -4
- package/components/page/PossibleReference.svelte +6 -11
- package/components/page/PossibleReference.svelte.d.ts +6 -7
- package/components/page/Print.svelte +27 -3
- package/components/page/Print.svelte.d.ts +4 -4
- package/components/page/Reference.svelte +256 -113
- package/components/page/Reference.svelte.d.ts +5 -5
- package/components/page/References.svelte +39 -47
- package/components/page/References.svelte.d.ts +4 -4
- package/components/page/Rows.svelte +54 -0
- package/components/page/Rows.svelte.d.ts +27 -0
- package/components/page/Search.svelte +86 -63
- package/components/page/Search.svelte.d.ts +4 -4
- package/components/page/Status.svelte +43 -35
- package/components/page/Status.svelte.d.ts +4 -9
- package/components/page/SubdomainEditor.svelte +40 -27
- package/components/page/SubdomainEditor.svelte.d.ts +4 -4
- package/components/page/TableOfContents.svelte +225 -190
- package/components/page/TableOfContents.svelte.d.ts +4 -4
- package/components/page/TableOfContentsImage.svelte +8 -8
- package/components/page/TableOfContentsImage.svelte.d.ts +3 -3
- package/components/page/TableOfContentsRow.svelte +96 -33
- package/components/page/TableOfContentsRow.svelte.d.ts +4 -4
- package/components/page/ThemeEditor.svelte +174 -39
- package/components/page/ThemeEditor.svelte.d.ts +4 -4
- package/components/page/ThemeEditorPreview.svelte +35 -23
- package/components/page/ThemeEditorPreview.svelte.d.ts +5 -5
- package/components/page/ThemeSetEditor.svelte +15 -13
- package/components/page/ThemeSetEditor.svelte.d.ts +4 -4
- package/components/page/ThemeVariableEditor.svelte +24 -15
- package/components/page/ThemeVariableEditor.svelte.d.ts +3 -3
- package/components/page/Title.svelte +12 -0
- package/components/page/Title.svelte.d.ts +27 -0
- package/components/page/Unknown.svelte +25 -21
- package/components/page/Unknown.svelte.d.ts +4 -4
- package/components/page/margins.js +50 -33
- package/index.d.ts +14 -0
- package/index.js +14 -0
- package/models/CRUD.d.ts +17 -0
- package/models/CRUD.js +194 -0
- package/models/Firebase.js +17 -15
- package/models/book/Book.d.ts +24 -28
- package/models/book/Book.js +120 -113
- package/models/book/BookMedia.d.ts +3 -3
- package/models/book/BookMedia.js +22 -16
- package/models/book/BookSaveStatus.d.ts +7 -0
- package/models/book/BookSaveStatus.js +8 -0
- package/models/book/Chapter.d.ts +46 -39
- package/models/book/Chapter.js +180 -198
- package/models/book/ChapterID.js +7 -7
- package/models/book/Definition.d.ts +1 -1
- package/models/book/Edition.d.ts +62 -60
- package/models/book/Edition.js +385 -303
- package/models/book/Reference.d.ts +24 -0
- package/models/book/Reference.js +78 -0
- package/models/book/Schema.d.ts +169 -0
- package/models/book/Schema.js +114 -0
- package/models/book/Theme.d.ts +44 -37
- package/models/book/Theme.js +452 -52
- package/models/book/ThemeColors.d.ts +1 -1
- package/models/book/Words.d.ts +2 -0
- package/models/book/Words.js +110 -0
- package/models/chapter/AtomNode.d.ts +4 -4
- package/models/chapter/AtomNode.js +20 -13
- package/models/chapter/BlockNode.d.ts +9 -10
- package/models/chapter/BlockNode.js +32 -13
- package/models/chapter/BlocksNode.d.ts +10 -10
- package/models/chapter/BlocksNode.js +315 -120
- package/models/chapter/BlocksNode.test.js +494 -228
- package/models/chapter/Bookkeeping.d.ts +1 -1
- package/models/chapter/CalloutNode.d.ts +3 -3
- package/models/chapter/CalloutNode.js +34 -12
- package/models/chapter/Caret.d.ts +9 -7
- package/models/chapter/Caret.js +11 -6
- package/models/chapter/ChapterNode.d.ts +11 -11
- package/models/chapter/ChapterNode.js +70 -33
- package/models/chapter/CitationsNode.d.ts +3 -3
- package/models/chapter/CitationsNode.js +31 -12
- package/models/chapter/CodeNode.d.ts +11 -6
- package/models/chapter/CodeNode.js +143 -34
- package/models/chapter/CommentNode.d.ts +5 -5
- package/models/chapter/CommentNode.js +29 -13
- package/models/chapter/DefinitionNode.d.ts +2 -2
- package/models/chapter/DefinitionNode.js +15 -7
- package/models/chapter/Edit.d.ts +3 -3
- package/models/chapter/EmbedNode.d.ts +9 -5
- package/models/chapter/EmbedNode.js +108 -35
- package/models/chapter/ErrorNode.d.ts +2 -2
- package/models/chapter/ErrorNode.js +34 -12
- package/models/chapter/FootnoteNode.d.ts +5 -5
- package/models/chapter/FootnoteNode.js +34 -16
- package/models/chapter/FormatNode.d.ts +10 -10
- package/models/chapter/FormatNode.js +237 -106
- package/models/chapter/FormatNode.test.js +87 -45
- package/models/chapter/InlineCodeNode.d.ts +2 -2
- package/models/chapter/InlineCodeNode.js +22 -9
- package/models/chapter/LabelNode.d.ts +4 -4
- package/models/chapter/LabelNode.js +31 -13
- package/models/chapter/LinkNode.d.ts +2 -2
- package/models/chapter/LinkNode.js +21 -9
- package/models/chapter/ListNode.d.ts +8 -8
- package/models/chapter/ListNode.js +99 -38
- package/models/chapter/ListNode.test.js +29 -24
- package/models/chapter/MetadataNode.d.ts +3 -3
- package/models/chapter/MetadataNode.js +13 -5
- package/models/chapter/Node.d.ts +5 -3
- package/models/chapter/Node.js +76 -29
- package/models/chapter/Node.test.js +20 -18
- package/models/chapter/ParagraphNode.d.ts +6 -6
- package/models/chapter/ParagraphNode.js +84 -29
- package/models/chapter/ParagraphNode.test.js +22 -13
- package/models/chapter/Parser.d.ts +25 -25
- package/models/chapter/Parser.js +201 -189
- package/models/chapter/Parser.test.js +16 -16
- package/models/chapter/Position.d.ts +1 -1
- package/models/chapter/QuoteNode.d.ts +6 -6
- package/models/chapter/QuoteNode.js +61 -23
- package/models/chapter/RootNode.d.ts +4 -4
- package/models/chapter/RuleNode.d.ts +2 -2
- package/models/chapter/RuleNode.js +31 -11
- package/models/chapter/TableNode.d.ts +8 -6
- package/models/chapter/TableNode.js +89 -34
- package/models/chapter/TableNode.test.js +22 -24
- package/models/chapter/TextNode.d.ts +6 -6
- package/models/chapter/TextNode.js +72 -32
- package/models/chapter/TextNode.test.js +4 -4
- package/models/loadEdition.d.ts +1 -1
- package/models/loadEdition.js +10 -6
- package/package.json +104 -25
- package/util/getSubdomain.js +8 -6
- package/util/isMobile.js +1 -1
- package/util/mineReference.d.ts +3 -2
- package/util/mineReference.js +67 -29
- package/util/scrollToEyeLevel.js +6 -1
- package/components/chapter/renderPosition.d.ts +0 -3
- package/components/chapter/renderPosition.js +0 -4
- package/components/editor/ToolbarIcon.svelte +0 -22
- package/components/editor/ToolbarIcon.svelte.d.ts +0 -16
- package/components/page/Alert.svelte +0 -11
- package/components/page/Alert.svelte.d.ts +0 -23
- package/components/page/Revisions.svelte +0 -124
- package/components/page/Revisions.svelte.d.ts +0 -14
- package/models/BookLoader.d.ts +0 -2
- package/models/BookLoader.js +0 -67
- package/models/Firestore.d.ts +0 -22
- package/models/Firestore.js +0 -194
- package/models/chapter/ReferenceNode.d.ts +0 -29
- package/models/chapter/ReferenceNode.js +0 -48
package/models/chapter/Parser.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import CalloutNode from
|
|
2
|
-
import ChapterNode from
|
|
3
|
-
import CitationsNode from
|
|
4
|
-
import CodeNode from
|
|
5
|
-
import CommentNode from
|
|
6
|
-
import DefinitionNode from
|
|
7
|
-
import EmbedNode from
|
|
8
|
-
import ErrorNode from
|
|
9
|
-
import FootnoteNode from
|
|
10
|
-
import FormatNode from
|
|
11
|
-
import InlineCodeNode from
|
|
12
|
-
import LabelNode from
|
|
13
|
-
import LinkNode from
|
|
14
|
-
import ListNode from
|
|
15
|
-
import ParagraphNode from
|
|
16
|
-
import QuoteNode from
|
|
17
|
-
import
|
|
18
|
-
import RuleNode from
|
|
19
|
-
import TableNode from
|
|
20
|
-
import TextNode from
|
|
1
|
+
import CalloutNode from './CalloutNode';
|
|
2
|
+
import ChapterNode from './ChapterNode';
|
|
3
|
+
import CitationsNode from './CitationsNode';
|
|
4
|
+
import CodeNode from './CodeNode';
|
|
5
|
+
import CommentNode from './CommentNode';
|
|
6
|
+
import DefinitionNode from './DefinitionNode';
|
|
7
|
+
import EmbedNode from './EmbedNode';
|
|
8
|
+
import ErrorNode from './ErrorNode';
|
|
9
|
+
import FootnoteNode from './FootnoteNode';
|
|
10
|
+
import FormatNode from './FormatNode';
|
|
11
|
+
import InlineCodeNode from './InlineCodeNode';
|
|
12
|
+
import LabelNode from './LabelNode';
|
|
13
|
+
import LinkNode from './LinkNode';
|
|
14
|
+
import ListNode from './ListNode';
|
|
15
|
+
import ParagraphNode from './ParagraphNode';
|
|
16
|
+
import QuoteNode from './QuoteNode';
|
|
17
|
+
import Reference from '../book/Reference';
|
|
18
|
+
import RuleNode from './RuleNode';
|
|
19
|
+
import TableNode from './TableNode';
|
|
20
|
+
import TextNode from './TextNode';
|
|
21
21
|
const numberedRE = /^[0-9]+\.+/;
|
|
22
22
|
const bulletRE = /^\*+\s+/;
|
|
23
23
|
// TODO This grammar is slightly out of date.
|
|
@@ -53,14 +53,14 @@ export default class Parser {
|
|
|
53
53
|
// We pass this to all parsing functions to gather information strewn about the document.
|
|
54
54
|
metadata;
|
|
55
55
|
constructor(book, text) {
|
|
56
|
-
if (typeof text !==
|
|
57
|
-
throw
|
|
56
|
+
if (typeof text !== 'string')
|
|
57
|
+
throw 'Parser expected a string but received ' + typeof text;
|
|
58
58
|
this.book = book;
|
|
59
59
|
this.text = text;
|
|
60
60
|
this.index = 0; // Start at the first character.
|
|
61
61
|
this.openedDoubleQuote = false; // Track most recently observed quotes.
|
|
62
62
|
this.metadata = {
|
|
63
|
-
symbols: {}
|
|
63
|
+
symbols: {},
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
static preprocessSymbols(book, text) {
|
|
@@ -69,46 +69,19 @@ export default class Parser {
|
|
|
69
69
|
for (const [symbol, definition] of Object.entries(book.getSymbols())) {
|
|
70
70
|
// Don't replace escaped at symbols. Otherwise, be liberal in replacing any matching symbol that starts with the symbol
|
|
71
71
|
// name and ends with a word boundary.
|
|
72
|
-
text = text.replace(new RegExp(
|
|
72
|
+
text = text.replace(new RegExp('([^\\\\])@' + symbol + '\\b', 'g'), '$1' + definition);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
return text;
|
|
76
76
|
}
|
|
77
77
|
static parseChapter(book, text) {
|
|
78
|
-
return
|
|
78
|
+
return new Parser(book, book === undefined ? text : Parser.preprocessSymbols(book, text)).parseChapter();
|
|
79
79
|
}
|
|
80
80
|
static parseFormat(book, text) {
|
|
81
|
-
return
|
|
81
|
+
return new Parser(book, book === undefined ? text : Parser.preprocessSymbols(book, text)).parseFormat();
|
|
82
82
|
}
|
|
83
83
|
static parseEmbed(book, text) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
static parseReference(citationID, ref, edition, short = false) {
|
|
87
|
-
if (typeof ref === "string")
|
|
88
|
-
return Parser.parseFormat(edition, ref);
|
|
89
|
-
else if (Array.isArray(ref)) {
|
|
90
|
-
// APA Format. Could eventually support multiple formats.
|
|
91
|
-
if (ref.length >= 4) {
|
|
92
|
-
let authors = ref[0];
|
|
93
|
-
let year = ref[1];
|
|
94
|
-
let title = ref[2];
|
|
95
|
-
let source = ref[3];
|
|
96
|
-
let url = ref.length === 5 ? ref[4] : "";
|
|
97
|
-
let summary = ref.length === 6 ? ref[5] : "";
|
|
98
|
-
if (source.charAt(0) === "#") {
|
|
99
|
-
let src = edition.getSource(source);
|
|
100
|
-
if (src === null)
|
|
101
|
-
return new ErrorNode(undefined, "Unknown source " + source);
|
|
102
|
-
else
|
|
103
|
-
source = src;
|
|
104
|
-
}
|
|
105
|
-
return new ReferenceNode(citationID, authors, year, title, source, url, summary, short);
|
|
106
|
-
}
|
|
107
|
-
else
|
|
108
|
-
return new ErrorNode(undefined, "Expected at least 4 items in the reference array, but found " + ref.length + ": " + ref.toString());
|
|
109
|
-
}
|
|
110
|
-
else
|
|
111
|
-
return new ErrorNode(undefined, "Invalid reference: " + ref);
|
|
84
|
+
return new Parser(book, book === undefined ? text : Parser.preprocessSymbols(book, text)).parseEmbed();
|
|
112
85
|
}
|
|
113
86
|
// Get the next character, if there is one, null otherwise.
|
|
114
87
|
peek() {
|
|
@@ -118,37 +91,50 @@ export default class Parser {
|
|
|
118
91
|
more() {
|
|
119
92
|
return this.index < this.text.length;
|
|
120
93
|
}
|
|
94
|
+
nextIsEmptyParagraph() {
|
|
95
|
+
return (this.text.charAt(this.index) === '\n' &&
|
|
96
|
+
this.text.charAt(this.index + 1) === '\n' &&
|
|
97
|
+
this.text.charAt(this.index + 2) === '\n');
|
|
98
|
+
}
|
|
99
|
+
nextIsWhitespace() {
|
|
100
|
+
return ((this.peek() === ' ' ||
|
|
101
|
+
this.peek() === '\t' ||
|
|
102
|
+
this.peek() === '\n') &&
|
|
103
|
+
!this.nextIsEmptyParagraph());
|
|
104
|
+
}
|
|
121
105
|
// Return the current character--if there is one-- and increment the index.
|
|
122
106
|
read(smarten = true) {
|
|
123
107
|
if (!this.more())
|
|
124
108
|
return null;
|
|
125
109
|
let char = this.text.charAt(this.index);
|
|
126
110
|
if (smarten) {
|
|
127
|
-
if (char ===
|
|
111
|
+
if (char === '\n')
|
|
128
112
|
this.openedDoubleQuote = false;
|
|
129
113
|
// As we read, replace straight quotes with smart quotes.
|
|
130
114
|
if (char === '"') {
|
|
131
115
|
// Replace left quotes after whitespace.
|
|
132
116
|
if (this.openedDoubleQuote) {
|
|
133
|
-
char =
|
|
117
|
+
char = '\u201d';
|
|
134
118
|
}
|
|
135
119
|
else {
|
|
136
|
-
char =
|
|
120
|
+
char = '\u201c';
|
|
137
121
|
}
|
|
138
122
|
this.openedDoubleQuote = !this.openedDoubleQuote;
|
|
139
123
|
}
|
|
140
124
|
else if (char === "'") {
|
|
141
125
|
// If there's whitespace before this, it's a left single quote.
|
|
142
126
|
if (/\s/.test(this.text.charAt(this.index - 1)))
|
|
143
|
-
char =
|
|
127
|
+
char = '\u2018';
|
|
144
128
|
// Otherwise, it's a right single quote.
|
|
145
129
|
else {
|
|
146
|
-
char =
|
|
130
|
+
char = '\u2019';
|
|
147
131
|
}
|
|
148
132
|
}
|
|
149
|
-
if (char === '-' &&
|
|
133
|
+
if (char === '-' &&
|
|
134
|
+
this.text.charAt(this.index + 1) === '-' &&
|
|
135
|
+
this.text.charAt(this.index) !== '\n') {
|
|
150
136
|
this.index++;
|
|
151
|
-
char =
|
|
137
|
+
char = '\u2014';
|
|
152
138
|
}
|
|
153
139
|
}
|
|
154
140
|
// Advance to the next character in the document.
|
|
@@ -168,11 +154,13 @@ export default class Parser {
|
|
|
168
154
|
}
|
|
169
155
|
// The character after
|
|
170
156
|
charAfterNext() {
|
|
171
|
-
return this.index === this.text.length - 1
|
|
157
|
+
return this.index === this.text.length - 1
|
|
158
|
+
? null
|
|
159
|
+
: this.text.charAt(this.index + 1);
|
|
172
160
|
}
|
|
173
161
|
// All the text until the next newline
|
|
174
162
|
restOfLine() {
|
|
175
|
-
const nextNewline = this.text.substring(this.index).indexOf(
|
|
163
|
+
const nextNewline = this.text.substring(this.index).indexOf('\n') + this.index;
|
|
176
164
|
if (nextNewline < 0)
|
|
177
165
|
return this.text.substring(this.index);
|
|
178
166
|
else
|
|
@@ -182,25 +170,27 @@ export default class Parser {
|
|
|
182
170
|
nextIs(text) {
|
|
183
171
|
if (!this.more())
|
|
184
172
|
return false;
|
|
185
|
-
return this.text.substring(this.index, this.index + text.length) === text;
|
|
173
|
+
return (this.text.substring(this.index, this.index + text.length) === text);
|
|
186
174
|
}
|
|
187
175
|
// A critical list that tells inline formatting parsers to stop being greedy.
|
|
188
176
|
nextIsContentDelimiter() {
|
|
189
177
|
const next = this.peek();
|
|
190
178
|
const charAfterNext = this.charAfterNext();
|
|
191
|
-
return next ===
|
|
192
|
-
next ===
|
|
193
|
-
next ===
|
|
194
|
-
next ===
|
|
195
|
-
next ===
|
|
196
|
-
next ===
|
|
197
|
-
(next ===
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
next ===
|
|
201
|
-
|
|
202
|
-
next ===
|
|
203
|
-
next ===
|
|
179
|
+
return (next === '\n' ||
|
|
180
|
+
next === '_' ||
|
|
181
|
+
next === '*' ||
|
|
182
|
+
next === '`' ||
|
|
183
|
+
next === '@' ||
|
|
184
|
+
next === '~' ||
|
|
185
|
+
(next === ':' &&
|
|
186
|
+
charAfterNext !== null &&
|
|
187
|
+
charAfterNext.match(/[a-z]/i) !== null) ||
|
|
188
|
+
next === '^' ||
|
|
189
|
+
next === '<' ||
|
|
190
|
+
next === '{' ||
|
|
191
|
+
(this.charBeforeNext() === ' ' && next === '%') ||
|
|
192
|
+
next === '[' ||
|
|
193
|
+
next === '\\');
|
|
204
194
|
}
|
|
205
195
|
// True if the next part of this string matches the given regular expression.
|
|
206
196
|
nextMatches(regex) {
|
|
@@ -210,7 +200,7 @@ export default class Parser {
|
|
|
210
200
|
}
|
|
211
201
|
// Returns true if all of the text between the current character and the next newline is whitespace.
|
|
212
202
|
isBlankLine() {
|
|
213
|
-
return this.restOfLine().trim() ===
|
|
203
|
+
return this.restOfLine().trim() === '';
|
|
214
204
|
}
|
|
215
205
|
// Read until encountering something other than a tab or a space.
|
|
216
206
|
readWhitespace() {
|
|
@@ -222,15 +212,15 @@ export default class Parser {
|
|
|
222
212
|
}
|
|
223
213
|
// Read until the end of the line.
|
|
224
214
|
readUntilNewLine() {
|
|
225
|
-
let text =
|
|
226
|
-
while (this.more() && this.peek() !==
|
|
215
|
+
let text = '';
|
|
216
|
+
while (this.more() && this.peek() !== '\n')
|
|
227
217
|
text = text + this.read();
|
|
228
218
|
return text;
|
|
229
219
|
}
|
|
230
220
|
// Read until encountering the given string and return the read text.
|
|
231
221
|
readUntilNewlineOr(string) {
|
|
232
|
-
let text =
|
|
233
|
-
while (this.more() && !this.nextIs(
|
|
222
|
+
let text = '';
|
|
223
|
+
while (this.more() && !this.nextIs('\n') && !this.nextIs(string))
|
|
234
224
|
text = text + this.read();
|
|
235
225
|
return text;
|
|
236
226
|
}
|
|
@@ -243,7 +233,7 @@ export default class Parser {
|
|
|
243
233
|
let rest = this.rest();
|
|
244
234
|
// First, replace any occurrences of the symbol with the symbol's text.
|
|
245
235
|
for (const [symbol, text] of Object.entries(this.metadata.symbols)) {
|
|
246
|
-
rest = rest.replace(new RegExp(
|
|
236
|
+
rest = rest.replace(new RegExp('([^\\\\])@' + symbol + '\\b', 'g'), '$1' + text);
|
|
247
237
|
}
|
|
248
238
|
// Replace all of the remaining symbols using book symbol definitions.
|
|
249
239
|
if (this.book)
|
|
@@ -254,11 +244,11 @@ export default class Parser {
|
|
|
254
244
|
let trailingNewlines = 0;
|
|
255
245
|
while (this.more()) {
|
|
256
246
|
trailingNewlines = 0;
|
|
257
|
-
// Read a
|
|
247
|
+
// Read a block and add it to the list if we parsed something.
|
|
258
248
|
blocks.push(this.parseBlock());
|
|
259
249
|
// Read whitespace until we find the next thing.
|
|
260
|
-
while (this.
|
|
261
|
-
if (this.peek() ===
|
|
250
|
+
while (this.nextIsWhitespace()) {
|
|
251
|
+
if (this.peek() === '\n')
|
|
262
252
|
trailingNewlines++;
|
|
263
253
|
this.read();
|
|
264
254
|
}
|
|
@@ -273,22 +263,24 @@ export default class Parser {
|
|
|
273
263
|
// Read whitespace before the symbols
|
|
274
264
|
this.readWhitespace();
|
|
275
265
|
// Keep reading symbols
|
|
276
|
-
while (this.nextIs(
|
|
266
|
+
while (this.nextIs('@')) {
|
|
277
267
|
// Read the @
|
|
278
268
|
this.read();
|
|
279
269
|
// Read the name.
|
|
280
|
-
let name = this.readUntilNewlineOr(
|
|
270
|
+
let name = this.readUntilNewlineOr(':');
|
|
281
271
|
// Names need to be letter and numbers only.
|
|
282
272
|
if (!/^[a-zA-Z0-9]+$/.test(name)) {
|
|
283
|
-
new ErrorNode(this.readUntilNewLine(), name.trim() ===
|
|
284
|
-
|
|
285
|
-
"'" +
|
|
273
|
+
new ErrorNode(this.readUntilNewLine(), name.trim() === ''
|
|
274
|
+
? '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.'
|
|
275
|
+
: "'" +
|
|
276
|
+
name +
|
|
277
|
+
"' isn't a valid name for a symbol; letters and numbers only");
|
|
286
278
|
return;
|
|
287
279
|
}
|
|
288
280
|
// Read any whitespace until the colon.
|
|
289
281
|
this.readWhitespace();
|
|
290
282
|
// Name declarations need to be terminated with a colon before the block starts.
|
|
291
|
-
if (!this.nextIs(
|
|
283
|
+
if (!this.nextIs(':')) {
|
|
292
284
|
new ErrorNode(this.readUntilNewLine(), "Symbol names are to be followed by a ':'");
|
|
293
285
|
return;
|
|
294
286
|
}
|
|
@@ -301,27 +293,27 @@ export default class Parser {
|
|
|
301
293
|
// Parse a block, any block.
|
|
302
294
|
this.parseBlock();
|
|
303
295
|
// Remember the text we parsed.
|
|
304
|
-
this.metadata.symbols[name] = this.text
|
|
296
|
+
this.metadata.symbols[name] = this.text
|
|
297
|
+
.substring(startIndex, this.index)
|
|
298
|
+
.trim();
|
|
305
299
|
// Read whitespace until we find the next non-whitespace thing.
|
|
306
|
-
while (this.
|
|
300
|
+
while (this.nextIsWhitespace())
|
|
307
301
|
this.read();
|
|
308
302
|
}
|
|
309
303
|
}
|
|
310
304
|
parseBlock() {
|
|
311
|
-
// Read whitespace before the block.
|
|
312
|
-
this.readWhitespace();
|
|
313
305
|
// Read comment lines
|
|
314
|
-
while (this.nextIs(
|
|
306
|
+
while (this.nextIs('%')) {
|
|
315
307
|
this.readUntilNewLine();
|
|
316
308
|
}
|
|
317
309
|
// Parse and return a header if it starts with a hash
|
|
318
|
-
if (this.nextIs(
|
|
310
|
+
if (this.nextIs('#'))
|
|
319
311
|
return this.parseHeader();
|
|
320
312
|
// Parse and return a horizontal rule if it starts with a dash
|
|
321
|
-
else if (this.nextIs(
|
|
313
|
+
else if (this.nextIs('-'))
|
|
322
314
|
return this.parseRule();
|
|
323
315
|
// Parse and return an embed if it starts with a bar
|
|
324
|
-
else if (this.nextIs(
|
|
316
|
+
else if (this.nextIs('|'))
|
|
325
317
|
return this.parseEmbed();
|
|
326
318
|
// Parse and return a bulleted or numbered list
|
|
327
319
|
else if (this.nextMatches(bulletRE) || this.nextMatches(numberedRE))
|
|
@@ -336,19 +328,25 @@ export default class Parser {
|
|
|
336
328
|
else if (this.nextMatches(/^=[ \t]*\n/))
|
|
337
329
|
return this.parseCallout();
|
|
338
330
|
// Parse and return a table if the line starts with a ,
|
|
339
|
-
else if (this.nextIs(
|
|
331
|
+
else if (this.nextIs(','))
|
|
340
332
|
return this.parseTable();
|
|
341
333
|
// Parse the text as paragraph;
|
|
342
334
|
else
|
|
343
335
|
return this.parseParagraph();
|
|
344
336
|
}
|
|
345
337
|
parseParagraph() {
|
|
346
|
-
|
|
338
|
+
if (this.nextIsEmptyParagraph()) {
|
|
339
|
+
this.read();
|
|
340
|
+
this.read();
|
|
341
|
+
return new ParagraphNode(0, new FormatNode('', [new TextNode()]));
|
|
342
|
+
}
|
|
343
|
+
else
|
|
344
|
+
return new ParagraphNode(0, this.parseFormat());
|
|
347
345
|
}
|
|
348
346
|
parseHeader() {
|
|
349
347
|
// Read a sequence of hashes
|
|
350
348
|
let count = 0;
|
|
351
|
-
while (this.nextIs(
|
|
349
|
+
while (this.nextIs('#')) {
|
|
352
350
|
this.read();
|
|
353
351
|
count++;
|
|
354
352
|
}
|
|
@@ -378,10 +376,10 @@ export default class Parser {
|
|
|
378
376
|
if (numbered) {
|
|
379
377
|
// Read the digits and remember how many there were so we can backtrack.
|
|
380
378
|
digits = this.index;
|
|
381
|
-
this.readUntilNewlineOr(
|
|
379
|
+
this.readUntilNewlineOr('.');
|
|
382
380
|
digits = this.index - digits;
|
|
383
381
|
// Figure out this level.
|
|
384
|
-
while (this.nextIs(
|
|
382
|
+
while (this.nextIs('.')) {
|
|
385
383
|
this.read();
|
|
386
384
|
currentLevel++;
|
|
387
385
|
}
|
|
@@ -389,7 +387,7 @@ export default class Parser {
|
|
|
389
387
|
else {
|
|
390
388
|
// Figure out this level.
|
|
391
389
|
currentLevel = 0;
|
|
392
|
-
while (this.nextIs(
|
|
390
|
+
while (this.nextIs('*')) {
|
|
393
391
|
this.read();
|
|
394
392
|
currentLevel++;
|
|
395
393
|
}
|
|
@@ -400,7 +398,9 @@ export default class Parser {
|
|
|
400
398
|
this.readWhitespace();
|
|
401
399
|
// Parse content after the bullet.
|
|
402
400
|
const format = this.parseFormat();
|
|
403
|
-
items.push(format.isEmpty()
|
|
401
|
+
items.push(format.isEmpty()
|
|
402
|
+
? format.withSegmentAppended(new TextNode())
|
|
403
|
+
: format);
|
|
404
404
|
}
|
|
405
405
|
// Otherwise, unread the stars, then either stop parsing or parse nested list.
|
|
406
406
|
else {
|
|
@@ -427,14 +427,17 @@ export default class Parser {
|
|
|
427
427
|
currentLevel = lastLevel;
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
|
-
// Read trailing whitespace and newlines.
|
|
430
|
+
// Read trailing whitespace and newlines.
|
|
431
431
|
this.readWhitespace();
|
|
432
|
-
while (this.
|
|
432
|
+
while (this.nextIsWhitespace()) {
|
|
433
433
|
// Read the newline
|
|
434
434
|
this.read();
|
|
435
435
|
// Read whitespace before the next block.
|
|
436
436
|
this.readWhitespace();
|
|
437
437
|
}
|
|
438
|
+
// Stop if we reach an empty paragraph.
|
|
439
|
+
if (this.nextIsEmptyParagraph())
|
|
440
|
+
break;
|
|
438
441
|
}
|
|
439
442
|
return new ListNode(items, numbered);
|
|
440
443
|
}
|
|
@@ -446,13 +449,13 @@ export default class Parser {
|
|
|
446
449
|
// Read the newline
|
|
447
450
|
this.read();
|
|
448
451
|
// Read until we encounter a closing back tick.
|
|
449
|
-
let code =
|
|
450
|
-
while (this.more() && !this.nextIs(
|
|
452
|
+
let code = '';
|
|
453
|
+
while (this.more() && !this.nextIs('`')) {
|
|
451
454
|
let next = this.read(false);
|
|
452
|
-
if (next ===
|
|
453
|
-
if (this.nextIs(
|
|
455
|
+
if (next === '\\') {
|
|
456
|
+
if (this.nextIs('`')) {
|
|
454
457
|
this.read();
|
|
455
|
-
next =
|
|
458
|
+
next = '`';
|
|
456
459
|
}
|
|
457
460
|
}
|
|
458
461
|
code = code + next;
|
|
@@ -460,23 +463,23 @@ export default class Parser {
|
|
|
460
463
|
// Trim the code.
|
|
461
464
|
code = code.trim();
|
|
462
465
|
// Read the backtick.
|
|
463
|
-
if (this.nextIs(
|
|
466
|
+
if (this.nextIs('`'))
|
|
464
467
|
this.read();
|
|
465
468
|
let position = this.parsePosition();
|
|
466
|
-
// Read the caption. Note that parsing inline content stops at a newline,
|
|
469
|
+
// Read the caption. Note that parsing inline content stops at a newline,
|
|
467
470
|
// so if there's a line break after the last row, there won't be a caption.
|
|
468
471
|
const caption = this.parseFormat();
|
|
469
472
|
return new CodeNode(new TextNode(code), language, position, caption);
|
|
470
473
|
}
|
|
471
474
|
parsePosition() {
|
|
472
|
-
let position =
|
|
475
|
+
let position = '|';
|
|
473
476
|
// Is there a position indicator?
|
|
474
|
-
if (this.nextIs(
|
|
475
|
-
position =
|
|
477
|
+
if (this.nextIs('<')) {
|
|
478
|
+
position = '<';
|
|
476
479
|
this.read();
|
|
477
480
|
}
|
|
478
|
-
else if (this.nextIs(
|
|
479
|
-
position =
|
|
481
|
+
else if (this.nextIs('>')) {
|
|
482
|
+
position = '>';
|
|
480
483
|
this.read();
|
|
481
484
|
}
|
|
482
485
|
return position;
|
|
@@ -489,14 +492,14 @@ export default class Parser {
|
|
|
489
492
|
this.readWhitespace();
|
|
490
493
|
// Then read the newline.
|
|
491
494
|
this.read();
|
|
492
|
-
while (this.more() && !this.nextIs("
|
|
495
|
+
while (this.more() && !this.nextIs('"')) {
|
|
493
496
|
// Read a block
|
|
494
497
|
const block = this.parseBlock();
|
|
495
498
|
// Add it to the list if we parsed something.
|
|
496
499
|
if (block !== null)
|
|
497
500
|
blocks.push(block);
|
|
498
501
|
// Read whitespace until we find the next thing.
|
|
499
|
-
while (this.
|
|
502
|
+
while (this.nextIsWhitespace())
|
|
500
503
|
this.read();
|
|
501
504
|
}
|
|
502
505
|
// Read the closing " and the whitespace that follows.
|
|
@@ -506,7 +509,7 @@ export default class Parser {
|
|
|
506
509
|
// Read any whitespace after the position indicator.
|
|
507
510
|
this.readWhitespace();
|
|
508
511
|
// Read the credit.
|
|
509
|
-
const credit = this.nextIs(
|
|
512
|
+
const credit = this.nextIs('\n') ? undefined : this.parseFormat();
|
|
510
513
|
return new QuoteNode(blocks, credit, position);
|
|
511
514
|
}
|
|
512
515
|
parseCallout() {
|
|
@@ -518,14 +521,16 @@ export default class Parser {
|
|
|
518
521
|
// ...then read the newline.
|
|
519
522
|
this.read();
|
|
520
523
|
// Then, read until we find a closing _
|
|
521
|
-
while (this.more() && !this.nextIs(
|
|
524
|
+
while (this.more() && !this.nextIs('=')) {
|
|
522
525
|
// Read a block
|
|
523
526
|
const block = this.parseBlock();
|
|
524
527
|
// Add it to the list if we parsed something.
|
|
525
528
|
if (block !== null)
|
|
526
529
|
blocks.push(block);
|
|
527
530
|
// Read whitespace until we find the next thing.
|
|
528
|
-
while (this.peek() ===
|
|
531
|
+
while (this.peek() === ' ' ||
|
|
532
|
+
this.peek() === '\t' ||
|
|
533
|
+
this.peek() === '\n')
|
|
529
534
|
this.read();
|
|
530
535
|
}
|
|
531
536
|
// Read the closing =
|
|
@@ -535,29 +540,28 @@ export default class Parser {
|
|
|
535
540
|
// Read whitespace that follows.
|
|
536
541
|
this.readWhitespace();
|
|
537
542
|
return new CalloutNode(blocks, position);
|
|
538
|
-
;
|
|
539
543
|
}
|
|
540
544
|
parseTable() {
|
|
541
545
|
const rows = [];
|
|
542
546
|
// Parse rows until the lines stop starting with ,
|
|
543
|
-
while (this.more() && this.nextIs(
|
|
547
|
+
while (this.more() && this.nextIs(',')) {
|
|
544
548
|
let row = [];
|
|
545
|
-
while (this.more() && !this.nextIs(
|
|
549
|
+
while (this.more() && !this.nextIs('\n')) {
|
|
546
550
|
// Read the starting , or next |
|
|
547
551
|
this.read();
|
|
548
552
|
// Read whitespace that follows.
|
|
549
553
|
this.readWhitespace();
|
|
550
554
|
// Read content until reaching another | or the end of the line.
|
|
551
|
-
row.push(this.parseFormat(
|
|
555
|
+
row.push(this.parseFormat('|'));
|
|
552
556
|
}
|
|
553
557
|
// Add the row.
|
|
554
558
|
rows.push(row);
|
|
555
559
|
// Read the newline
|
|
556
560
|
this.read();
|
|
557
561
|
}
|
|
558
|
-
// Read the position indicator if there is one.
|
|
562
|
+
// Read the position indicator if there is one.
|
|
559
563
|
const position = this.parsePosition();
|
|
560
|
-
// Read the caption. Note that parsing inline content stops at a newline,
|
|
564
|
+
// Read the caption. Note that parsing inline content stops at a newline,
|
|
561
565
|
// so if there's a line break after the last row, there won't be a caption.
|
|
562
566
|
const caption = this.parseFormat();
|
|
563
567
|
// Return the new table.
|
|
@@ -568,38 +572,38 @@ export default class Parser {
|
|
|
568
572
|
parseFormat(awaiting) {
|
|
569
573
|
const segments = [];
|
|
570
574
|
// Read until hitting a delimiter.
|
|
571
|
-
while (this.more() && !this.nextIs(
|
|
575
|
+
while (this.more() && !this.nextIs('\n')) {
|
|
572
576
|
const next = this.peek();
|
|
573
577
|
const charAfterNext = this.charAfterNext();
|
|
574
578
|
// Parse some bold, italic, subscript, superscript
|
|
575
|
-
if (next ===
|
|
579
|
+
if (next === '_' || next === '*' || next === '^')
|
|
576
580
|
segments.push(this.parseStyle(next));
|
|
577
581
|
// Parse unformatted text
|
|
578
|
-
else if (this.nextIs(
|
|
582
|
+
else if (this.nextIs('`'))
|
|
579
583
|
segments.push(this.parseInlineCode());
|
|
580
584
|
// Parse a citation list
|
|
581
|
-
else if (this.nextIs(
|
|
585
|
+
else if (this.nextIs('<'))
|
|
582
586
|
segments.push(this.parseCitations());
|
|
583
587
|
// Parse a footnote
|
|
584
|
-
else if (this.nextIs(
|
|
588
|
+
else if (this.nextIs('{'))
|
|
585
589
|
segments.push(this.parseFootnote());
|
|
586
590
|
// Parse a definition
|
|
587
|
-
else if (this.nextIs(
|
|
591
|
+
else if (this.nextIs('~'))
|
|
588
592
|
segments.push(this.parseDefinition());
|
|
589
593
|
// Parse an escaped character
|
|
590
|
-
else if (this.nextIs(
|
|
594
|
+
else if (this.nextIs('\\'))
|
|
591
595
|
segments.push(this.parseEscaped());
|
|
592
596
|
// Parse a link
|
|
593
|
-
else if (this.nextIs(
|
|
597
|
+
else if (this.nextIs('['))
|
|
594
598
|
segments.push(this.parseLink());
|
|
595
599
|
// Parse inline comments
|
|
596
|
-
else if (this.charBeforeNext() ===
|
|
600
|
+
else if (this.charBeforeNext() === ' ' && this.nextIs('%'))
|
|
597
601
|
segments.push(this.parseComment());
|
|
598
602
|
// Parse an unresolved symbol
|
|
599
|
-
else if (next ===
|
|
603
|
+
else if (next === '@') {
|
|
600
604
|
// Read the @, then the symbol name.
|
|
601
605
|
this.read();
|
|
602
|
-
let symbol =
|
|
606
|
+
let symbol = '';
|
|
603
607
|
// Stop at the end of the name or file.
|
|
604
608
|
let next = this.peek();
|
|
605
609
|
while (next !== null && /[a-zA-Z0-9]/.test(next)) {
|
|
@@ -609,13 +613,18 @@ export default class Parser {
|
|
|
609
613
|
segments.push(new ErrorNode(undefined, "Couldn't find symbol @" + symbol));
|
|
610
614
|
}
|
|
611
615
|
// Parse a label
|
|
612
|
-
else if (next ===
|
|
616
|
+
else if (next === ':' &&
|
|
617
|
+
charAfterNext !== null &&
|
|
618
|
+
charAfterNext.match(/[a-z]/i)) {
|
|
613
619
|
segments.push(this.parseLabel());
|
|
614
620
|
}
|
|
615
621
|
// Keep reading text until finding a delimiter.
|
|
616
622
|
else {
|
|
617
|
-
let text =
|
|
618
|
-
while (this.more() &&
|
|
623
|
+
let text = '';
|
|
624
|
+
while (this.more() &&
|
|
625
|
+
(!awaiting || !this.nextIs(awaiting)) &&
|
|
626
|
+
!this.nextIsContentDelimiter() &&
|
|
627
|
+
!this.nextIs('\n'))
|
|
619
628
|
text = text + this.read();
|
|
620
629
|
segments.push(new TextNode(text));
|
|
621
630
|
}
|
|
@@ -623,33 +632,33 @@ export default class Parser {
|
|
|
623
632
|
if (this.peek() === awaiting)
|
|
624
633
|
break;
|
|
625
634
|
}
|
|
626
|
-
return new FormatNode(
|
|
635
|
+
return new FormatNode('', segments);
|
|
627
636
|
}
|
|
628
637
|
parseEmbed() {
|
|
629
638
|
// Read |
|
|
630
639
|
this.read();
|
|
631
640
|
// Read the URL
|
|
632
|
-
const url = this.readUntilNewlineOr(
|
|
633
|
-
if (this.peek() !==
|
|
641
|
+
const url = this.readUntilNewlineOr('|');
|
|
642
|
+
if (this.peek() !== '|')
|
|
634
643
|
return new ErrorNode(this.readUntilNewLine(), "Missing '|' after URL in embed");
|
|
635
644
|
// Read a |
|
|
636
645
|
this.read();
|
|
637
646
|
// Read the description
|
|
638
|
-
const description = this.readUntilNewlineOr(
|
|
639
|
-
if (this.peek() !==
|
|
647
|
+
const description = this.readUntilNewlineOr('|');
|
|
648
|
+
if (this.peek() !== '|')
|
|
640
649
|
return new ErrorNode(this.readUntilNewLine(), "Missing '|' after description in embed");
|
|
641
650
|
// Read a |
|
|
642
651
|
this.read();
|
|
643
652
|
// Parse the caption
|
|
644
|
-
const caption = this.parseFormat(
|
|
645
|
-
if (this.peek() !==
|
|
653
|
+
const caption = this.parseFormat('|');
|
|
654
|
+
if (this.peek() !== '|')
|
|
646
655
|
return new ErrorNode(this.readUntilNewLine(), "Missing '|' after caption in embed");
|
|
647
656
|
// Read a |
|
|
648
657
|
this.read();
|
|
649
658
|
// Parse the credit
|
|
650
|
-
const credit = this.parseFormat(
|
|
659
|
+
const credit = this.parseFormat('|');
|
|
651
660
|
// Check for the closing delimeter
|
|
652
|
-
if (this.peek() !==
|
|
661
|
+
if (this.peek() !== '|')
|
|
653
662
|
return new ErrorNode(this.readUntilNewLine(), "Missing '|' after credit in embed.");
|
|
654
663
|
// Read a |
|
|
655
664
|
this.read();
|
|
@@ -661,9 +670,9 @@ export default class Parser {
|
|
|
661
670
|
// Consume the opening %
|
|
662
671
|
this.read();
|
|
663
672
|
// Consume everything until the next %.
|
|
664
|
-
const comment = this.parseFormat(
|
|
673
|
+
const comment = this.parseFormat('%');
|
|
665
674
|
// Consume the closing %, if we didn't reach the end of input or a newline.
|
|
666
|
-
if (this.peek() ===
|
|
675
|
+
if (this.peek() === '%')
|
|
667
676
|
this.read();
|
|
668
677
|
return new CommentNode(comment);
|
|
669
678
|
}
|
|
@@ -671,7 +680,7 @@ export default class Parser {
|
|
|
671
680
|
// Consume the :
|
|
672
681
|
this.read();
|
|
673
682
|
// Consume everything until it's not a letter.
|
|
674
|
-
let id =
|
|
683
|
+
let id = '';
|
|
675
684
|
let next = this.peek();
|
|
676
685
|
while (next !== null && next.match(/[a-z]/i)) {
|
|
677
686
|
id = id + this.read();
|
|
@@ -684,26 +693,26 @@ export default class Parser {
|
|
|
684
693
|
const delimeter = this.read();
|
|
685
694
|
let subscript = false;
|
|
686
695
|
const segments = [];
|
|
687
|
-
let text =
|
|
696
|
+
let text = '';
|
|
688
697
|
// Special case subscript, which has an extra delimeter.
|
|
689
|
-
if (this.peek() ===
|
|
698
|
+
if (delimeter === '^' && this.peek() === 'v') {
|
|
690
699
|
this.read();
|
|
691
700
|
subscript = true;
|
|
692
701
|
}
|
|
693
702
|
if (delimeter === null)
|
|
694
|
-
return new ErrorNode(undefined,
|
|
703
|
+
return new ErrorNode(undefined, 'Somehow parsing formatted text at end of file.');
|
|
695
704
|
// Read some content until reaching the delimiter or the end of the line
|
|
696
|
-
while (this.more() && this.peek() !== delimeter && !this.nextIs(
|
|
697
|
-
// If this is more formatted text, make a text node with whatever we've accumulated so far,
|
|
705
|
+
while (this.more() && this.peek() !== delimeter && !this.nextIs('\n')) {
|
|
706
|
+
// If this is more formatted text, make a text node with whatever we've accumulated so far,
|
|
698
707
|
// then parse the formatted text, then reset the accumulator.
|
|
699
708
|
if (this.nextIsContentDelimiter()) {
|
|
700
709
|
// If the text is a non-empty string, make a text node with what we've accumulated.
|
|
701
|
-
if (text !==
|
|
710
|
+
if (text !== '')
|
|
702
711
|
segments.push(new TextNode(text));
|
|
703
712
|
// Parse the formatted content.
|
|
704
713
|
segments.push(this.parseFormat(awaiting));
|
|
705
714
|
// Reset the accumulator.
|
|
706
|
-
text =
|
|
715
|
+
text = '';
|
|
707
716
|
}
|
|
708
717
|
// Add the next character to the accumulator.
|
|
709
718
|
else {
|
|
@@ -711,36 +720,36 @@ export default class Parser {
|
|
|
711
720
|
}
|
|
712
721
|
}
|
|
713
722
|
// If there's more text, save it!
|
|
714
|
-
if (text !==
|
|
723
|
+
if (text !== '')
|
|
715
724
|
segments.push(new TextNode(text));
|
|
716
725
|
// Read the closing delimeter
|
|
717
726
|
if (this.nextIs(delimeter))
|
|
718
727
|
this.read();
|
|
719
728
|
// If it wasn't closed, add an error
|
|
720
729
|
else
|
|
721
|
-
segments.push(new ErrorNode(undefined,
|
|
722
|
-
return new FormatNode(subscript ?
|
|
730
|
+
segments.push(new ErrorNode(undefined, 'Unclosed ' + delimeter));
|
|
731
|
+
return new FormatNode(subscript ? 'v' : delimeter, segments);
|
|
723
732
|
}
|
|
724
733
|
parseInlineCode() {
|
|
725
734
|
// Parse the back tick
|
|
726
735
|
this.read();
|
|
727
736
|
// Read until we encounter a closing back tick.
|
|
728
|
-
let code =
|
|
729
|
-
while (this.more() && !this.nextIs(
|
|
737
|
+
let code = '';
|
|
738
|
+
while (this.more() && !this.nextIs('`')) {
|
|
730
739
|
let next = this.read(false);
|
|
731
|
-
if (next ===
|
|
732
|
-
if (this.nextIs(
|
|
740
|
+
if (next === '\\') {
|
|
741
|
+
if (this.nextIs('`')) {
|
|
733
742
|
this.read();
|
|
734
|
-
next =
|
|
743
|
+
next = '`';
|
|
735
744
|
}
|
|
736
745
|
}
|
|
737
746
|
code = code + next;
|
|
738
747
|
}
|
|
739
748
|
// Read the backtick.
|
|
740
|
-
if (this.nextIs(
|
|
749
|
+
if (this.nextIs('`'))
|
|
741
750
|
this.read();
|
|
742
751
|
// If there's a letter immediately after a backtick, it's a language for an inline code name
|
|
743
|
-
let language =
|
|
752
|
+
let language = '';
|
|
744
753
|
let next = this.peek();
|
|
745
754
|
if (next !== null && /^[a-z]$/.test(next)) {
|
|
746
755
|
do {
|
|
@@ -749,26 +758,29 @@ export default class Parser {
|
|
|
749
758
|
} while (next !== null && /^[a-z]$/.test(next));
|
|
750
759
|
}
|
|
751
760
|
else
|
|
752
|
-
language =
|
|
761
|
+
language = 'plaintext';
|
|
753
762
|
return new InlineCodeNode(new TextNode(code), language);
|
|
754
763
|
}
|
|
755
764
|
parseCitations() {
|
|
756
|
-
let citations =
|
|
765
|
+
let citations = '';
|
|
757
766
|
// Read the <
|
|
758
767
|
this.read();
|
|
759
768
|
// Read the citations.
|
|
760
|
-
citations = this.readUntilNewlineOr(
|
|
761
|
-
if (this.peek() ===
|
|
769
|
+
citations = this.readUntilNewlineOr('>');
|
|
770
|
+
if (this.peek() === '>')
|
|
762
771
|
this.read();
|
|
763
772
|
// Trim any whitespace, then split by commas, then remove any empty IDs.
|
|
764
|
-
const citationList = citations
|
|
773
|
+
const citationList = citations
|
|
774
|
+
.split(',')
|
|
775
|
+
.map((citation) => citation.trim())
|
|
776
|
+
.filter((citationID) => citationID.length > 0);
|
|
765
777
|
return new CitationsNode(citationList);
|
|
766
778
|
}
|
|
767
779
|
parseFootnote() {
|
|
768
780
|
// Read the {
|
|
769
781
|
this.read();
|
|
770
782
|
// Read the footnote content.
|
|
771
|
-
const footnote = this.parseFormat(
|
|
783
|
+
const footnote = this.parseFormat('}');
|
|
772
784
|
// Read the closing }
|
|
773
785
|
this.read();
|
|
774
786
|
return new FootnoteNode(footnote);
|
|
@@ -777,11 +789,11 @@ export default class Parser {
|
|
|
777
789
|
// Read the ~
|
|
778
790
|
this.read();
|
|
779
791
|
// Read the phrase
|
|
780
|
-
const text = this.readUntilNewlineOr(
|
|
792
|
+
const text = this.readUntilNewlineOr('~');
|
|
781
793
|
// Read the closing ~
|
|
782
794
|
this.read();
|
|
783
795
|
// Read the glossary entry ID
|
|
784
|
-
let glossaryID =
|
|
796
|
+
let glossaryID = '';
|
|
785
797
|
// Stop at the end of the name or file.
|
|
786
798
|
let next = this.peek();
|
|
787
799
|
while (next !== null && /[a-zA-Z]/.test(next)) {
|
|
@@ -796,26 +808,26 @@ export default class Parser {
|
|
|
796
808
|
const char = this.read();
|
|
797
809
|
if (char)
|
|
798
810
|
return new TextNode(char);
|
|
799
|
-
return new ErrorNode(undefined,
|
|
811
|
+
return new ErrorNode(undefined, 'Unterminated escape.');
|
|
800
812
|
}
|
|
801
813
|
parseLink() {
|
|
802
814
|
// Read the [
|
|
803
815
|
this.read();
|
|
804
816
|
// Read pure text until funding |
|
|
805
|
-
const text = this.readUntilNewlineOr(
|
|
817
|
+
const text = this.readUntilNewlineOr('|');
|
|
806
818
|
// Catch missing bars
|
|
807
|
-
if (this.peek() !==
|
|
819
|
+
if (this.peek() !== '|') {
|
|
808
820
|
this.readUntilNewLine();
|
|
809
821
|
return new ErrorNode(undefined, "Missing '|' in link");
|
|
810
822
|
}
|
|
811
823
|
// Read the |
|
|
812
824
|
this.read();
|
|
813
825
|
// Read the link
|
|
814
|
-
let url = this.readUntilNewlineOr(
|
|
826
|
+
let url = this.readUntilNewlineOr(']');
|
|
815
827
|
// Catch missing closing
|
|
816
|
-
if (this.peek() !==
|
|
828
|
+
if (this.peek() !== ']') {
|
|
817
829
|
this.readUntilNewLine();
|
|
818
|
-
return new ErrorNode(undefined,
|
|
830
|
+
return new ErrorNode(undefined, 'Missing ] in link');
|
|
819
831
|
}
|
|
820
832
|
// Read the ]
|
|
821
833
|
this.read();
|