bookish-press 0.4.1 → 0.4.3
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 +27 -24
- package/components/Auth.svelte.d.ts +4 -4
- package/components/Authentication.d.ts +2 -2
- package/components/BookPreview.svelte +75 -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 +47 -0
- package/components/app/Feedback.svelte.d.ts +18 -0
- package/components/app/Head.svelte +15 -0
- package/components/app/Head.svelte.d.ts +18 -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 +20 -0
- package/components/app/Paragraph.svelte.d.ts +18 -0
- package/components/app/Section.svelte +12 -0
- package/components/app/Section.svelte.d.ts +27 -0
- package/components/app/Table.svelte +32 -0
- package/components/app/Table.svelte.d.ts +27 -0
- package/components/app/TextInput.svelte +38 -0
- package/components/app/TextInput.svelte.d.ts +22 -0
- package/components/chapter/Atom.svelte +20 -6
- package/components/chapter/Atom.svelte.d.ts +3 -3
- package/components/chapter/Block.svelte +26 -21
- 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 +67 -24
- package/components/chapter/CaptionedCode.svelte.d.ts +4 -4
- package/components/chapter/ChapterBody.svelte +62 -9
- package/components/chapter/ChapterBody.svelte.d.ts +5 -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 +39 -17
- 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 +155 -67
- package/components/chapter/Embed.svelte.d.ts +6 -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 +63 -38
- package/components/chapter/Format.svelte.d.ts +5 -4
- package/components/chapter/InlineCode.svelte +16 -6
- package/components/chapter/InlineCode.svelte.d.ts +4 -4
- package/components/chapter/Label.svelte +38 -9
- package/components/chapter/Label.svelte.d.ts +4 -4
- package/components/chapter/Link.svelte +24 -19
- 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 +79 -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 +373 -244
- package/components/editor/BookishEditor.svelte.d.ts +9 -6
- 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 +82 -0
- package/components/editor/CaretView.svelte.d.ts +25 -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 +4 -3
- package/components/editor/Note.svelte.d.ts +6 -2
- package/components/editor/Permissions.svelte +95 -0
- package/components/editor/Permissions.svelte.d.ts +20 -0
- 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 +191 -144
- package/components/editor/Toolbar.svelte.d.ts +5 -8
- package/components/editor/ToolbarGroup.svelte +17 -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 +35 -24
- package/components/page/Acknowledgements.svelte.d.ts +4 -4
- package/components/page/Authors.svelte +34 -17
- package/components/page/Authors.svelte.d.ts +7 -6
- package/components/page/BookLoader.svelte +59 -0
- package/components/page/BookLoader.svelte.d.ts +16 -0
- package/components/page/BulkReferenceEditor.svelte +54 -23
- package/components/page/BulkReferenceEditor.svelte.d.ts +4 -4
- package/components/page/Chapter.svelte +234 -143
- 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 +42 -22
- package/components/page/Contexts.js +129 -17
- package/components/page/DefinitionView.svelte +129 -90
- package/components/page/DefinitionView.svelte.d.ts +3 -3
- package/components/page/Description.svelte +31 -19
- package/components/page/Description.svelte.d.ts +4 -4
- package/components/page/Edition.svelte +135 -81
- package/components/page/Edition.svelte.d.ts +5 -6
- package/components/page/EditionLoader.svelte +99 -0
- package/components/page/EditionLoader.svelte.d.ts +18 -0
- package/components/page/Editions.svelte +106 -0
- package/components/page/Editions.svelte.d.ts +14 -0
- package/components/page/Glossary.svelte +65 -49
- package/components/page/Glossary.svelte.d.ts +4 -4
- package/components/page/Header.svelte +143 -56
- package/components/page/Header.svelte.d.ts +8 -6
- package/components/page/Index.svelte +116 -80
- package/components/page/Index.svelte.d.ts +4 -4
- package/components/page/Instructions.svelte +18 -17
- package/components/page/Instructions.svelte.d.ts +6 -4
- package/components/page/License.svelte +39 -23
- 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 +81 -53
- 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/Publish.svelte +134 -0
- package/components/page/Publish.svelte.d.ts +14 -0
- package/components/page/Reference.svelte +259 -117
- package/components/page/Reference.svelte.d.ts +5 -5
- package/components/page/References.svelte +45 -48
- 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 +88 -63
- package/components/page/Search.svelte.d.ts +4 -4
- package/components/page/Status.svelte +46 -39
- package/components/page/Status.svelte.d.ts +4 -9
- package/components/page/SubdomainEditor.svelte +41 -27
- package/components/page/SubdomainEditor.svelte.d.ts +4 -4
- package/components/page/TableOfContents.svelte +264 -191
- 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 +97 -34
- package/components/page/TableOfContentsRow.svelte.d.ts +4 -4
- package/components/page/ThemeEditor.svelte +177 -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 +28 -21
- package/components/page/Unknown.svelte.d.ts +4 -4
- package/components/page/margins.js +50 -33
- package/index.d.ts +13 -0
- package/index.js +14 -0
- package/models/CRUD.d.ts +27 -0
- package/models/CRUD.js +262 -0
- package/models/Firebase.d.ts +1 -0
- package/models/Firebase.js +26 -16
- package/models/book/Book.d.ts +40 -39
- package/models/book/Book.js +121 -121
- 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 +50 -39
- package/models/book/Chapter.js +189 -198
- package/models/book/ChapterID.js +7 -7
- package/models/book/Definition.d.ts +1 -1
- package/models/book/Edition.d.ts +87 -61
- package/models/book/Edition.js +460 -309
- package/models/book/Reference.d.ts +24 -0
- package/models/book/Reference.js +78 -0
- package/models/book/Schema.d.ts +168 -0
- package/models/book/Schema.js +115 -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 +27 -27
- package/models/chapter/Parser.js +220 -206
- 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/package.json +108 -26
- 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/loadEdition.d.ts +0 -5
- package/models/loadEdition.js +0 -16
|
@@ -1,54 +1,96 @@
|
|
|
1
1
|
import { test, expect } from 'vitest';
|
|
2
|
-
import FormatNode from
|
|
3
|
-
import TextNode from
|
|
4
|
-
test(
|
|
5
|
-
const text = new TextNode(
|
|
6
|
-
const format = new FormatNode(
|
|
7
|
-
expect(format
|
|
2
|
+
import FormatNode from './FormatNode';
|
|
3
|
+
import TextNode from './TextNode';
|
|
4
|
+
test('Bold first two characters', () => {
|
|
5
|
+
const text = new TextNode('Hello');
|
|
6
|
+
const format = new FormatNode('', [text]);
|
|
7
|
+
expect(format
|
|
8
|
+
.withFormat({
|
|
9
|
+
start: { node: text, index: 0 },
|
|
10
|
+
end: { node: text, index: 2 },
|
|
11
|
+
}, '*')
|
|
12
|
+
?.toBookdown()).toBe('*He*llo');
|
|
8
13
|
});
|
|
9
|
-
test(
|
|
10
|
-
const text = new TextNode(
|
|
11
|
-
const format = new FormatNode(
|
|
12
|
-
expect(format
|
|
14
|
+
test('Unbold word', () => {
|
|
15
|
+
const text = new TextNode('Hello');
|
|
16
|
+
const format = new FormatNode('', [new FormatNode('*', [text])]);
|
|
17
|
+
expect(format
|
|
18
|
+
.withFormat({
|
|
19
|
+
start: { node: text, index: 0 },
|
|
20
|
+
end: { node: text, index: 5 },
|
|
21
|
+
}, '')
|
|
22
|
+
?.toBookdown()).toBe('Hello');
|
|
13
23
|
});
|
|
14
|
-
test(
|
|
15
|
-
const text = new TextNode(
|
|
16
|
-
const format = new FormatNode(
|
|
17
|
-
expect(format
|
|
24
|
+
test('Bold single caret position', () => {
|
|
25
|
+
const text = new TextNode('Hello');
|
|
26
|
+
const format = new FormatNode('', [text]);
|
|
27
|
+
expect(format
|
|
28
|
+
.withFormat({
|
|
29
|
+
start: { node: text, index: 2 },
|
|
30
|
+
end: { node: text, index: 2 },
|
|
31
|
+
}, '*')
|
|
32
|
+
?.toBookdown()).toBe('He**llo');
|
|
18
33
|
});
|
|
19
|
-
test(
|
|
20
|
-
const text = new TextNode(
|
|
21
|
-
const format = new FormatNode(
|
|
22
|
-
expect(format
|
|
34
|
+
test('Delete first two characters', () => {
|
|
35
|
+
const text = new TextNode('Hello');
|
|
36
|
+
const format = new FormatNode('', [text]);
|
|
37
|
+
expect(format
|
|
38
|
+
.withoutRange({
|
|
39
|
+
start: { node: text, index: 0 },
|
|
40
|
+
end: { node: text, index: 2 },
|
|
41
|
+
})
|
|
42
|
+
?.toBookdown()).toBe('llo');
|
|
23
43
|
});
|
|
24
|
-
test(
|
|
25
|
-
const text = new TextNode(
|
|
26
|
-
const bolded = new TextNode(
|
|
27
|
-
const format = new FormatNode(
|
|
28
|
-
|
|
44
|
+
test('Delete characters crossing format boundary', () => {
|
|
45
|
+
const text = new TextNode('He');
|
|
46
|
+
const bolded = new TextNode('ll');
|
|
47
|
+
const format = new FormatNode('', [
|
|
48
|
+
text,
|
|
49
|
+
new FormatNode('*', [bolded]),
|
|
50
|
+
new TextNode('o'),
|
|
51
|
+
]);
|
|
52
|
+
expect(format
|
|
53
|
+
.withoutRange({
|
|
54
|
+
start: { node: text, index: 1 },
|
|
55
|
+
end: { node: bolded, index: 1 },
|
|
56
|
+
})
|
|
57
|
+
?.toBookdown()).toBe('H*l*o');
|
|
29
58
|
});
|
|
30
|
-
test(
|
|
31
|
-
const text = new TextNode(
|
|
32
|
-
const indexAfterPeriod = text.getText().indexOf(
|
|
59
|
+
test('Split', () => {
|
|
60
|
+
const text = new TextNode('This is my paragraph. It is two sentences.');
|
|
61
|
+
const indexAfterPeriod = text.getText().indexOf('.') + 1;
|
|
33
62
|
const caret = { node: text, index: indexAfterPeriod };
|
|
34
|
-
const format = new FormatNode(
|
|
35
|
-
expect(format
|
|
63
|
+
const format = new FormatNode('', [text]);
|
|
64
|
+
expect(format
|
|
65
|
+
.split(caret)
|
|
66
|
+
?.map((t) => t.toBookdown())
|
|
67
|
+
.join('THEN')).toBe('This is my paragraph.THEN It is two sentences.');
|
|
36
68
|
});
|
|
37
|
-
test(
|
|
38
|
-
const first = new TextNode(
|
|
39
|
-
const second = new TextNode(
|
|
40
|
-
const third = new TextNode(
|
|
41
|
-
const format = new FormatNode(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
expect(format
|
|
47
|
-
.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
.
|
|
52
|
-
expect(format
|
|
53
|
-
.
|
|
69
|
+
test('Backspace/delete', () => {
|
|
70
|
+
const first = new TextNode('Hello, my name is ');
|
|
71
|
+
const second = new TextNode('Amy');
|
|
72
|
+
const third = new TextNode('.');
|
|
73
|
+
const format = new FormatNode('', [
|
|
74
|
+
first,
|
|
75
|
+
new FormatNode('*', [second]),
|
|
76
|
+
third,
|
|
77
|
+
]);
|
|
78
|
+
expect(format
|
|
79
|
+
.withoutCharacter({ node: first, index: 5 }, false)
|
|
80
|
+
?.root.toBookdown()).toBe('Hell, my name is *Amy*.');
|
|
81
|
+
expect(format
|
|
82
|
+
.withoutCharacter({ node: first, index: 5 }, true)
|
|
83
|
+
?.root.toBookdown()).toBe('Hello my name is *Amy*.');
|
|
84
|
+
expect(format
|
|
85
|
+
.withoutCharacter({ node: second, index: 0 }, false)
|
|
86
|
+
?.root.toBookdown()).toBe('Hello, my name is*Amy*.');
|
|
87
|
+
expect(format
|
|
88
|
+
.withoutCharacter({ node: second, index: 0 }, true)
|
|
89
|
+
?.root.toBookdown()).toBe('Hello, my name is *my*.');
|
|
90
|
+
expect(format
|
|
91
|
+
.withoutCharacter({ node: first, index: 0 }, false)
|
|
92
|
+
?.root.toBookdown()).toBeUndefined();
|
|
93
|
+
expect(format
|
|
94
|
+
.withoutCharacter({ node: third, index: 1 }, true)
|
|
95
|
+
?.root.toBookdown()).toBeUndefined();
|
|
54
96
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import MetadataNode from
|
|
2
|
-
import TextNode from
|
|
1
|
+
import MetadataNode from './MetadataNode';
|
|
2
|
+
import TextNode from './TextNode';
|
|
3
3
|
export default class InlineCodeNode extends MetadataNode<string> {
|
|
4
4
|
constructor(code?: TextNode, language?: string);
|
|
5
5
|
getType(): string;
|
|
@@ -1,18 +1,31 @@
|
|
|
1
|
-
import MetadataNode from
|
|
2
|
-
import TextNode from
|
|
1
|
+
import MetadataNode from './MetadataNode';
|
|
2
|
+
import TextNode from './TextNode';
|
|
3
3
|
export default class InlineCodeNode extends MetadataNode {
|
|
4
|
-
constructor(code, language =
|
|
4
|
+
constructor(code, language = 'plaintext') {
|
|
5
5
|
super(code === undefined ? new TextNode() : code, language);
|
|
6
6
|
}
|
|
7
|
-
getType() {
|
|
7
|
+
getType() {
|
|
8
|
+
return 'inline-code';
|
|
9
|
+
}
|
|
8
10
|
toText() {
|
|
9
11
|
return this.getText().getText();
|
|
10
12
|
}
|
|
11
|
-
toHTML() {
|
|
13
|
+
toHTML() {
|
|
14
|
+
return `<code>${this.getMeta()}</code>`;
|
|
15
|
+
}
|
|
12
16
|
toBookdown() {
|
|
13
|
-
return
|
|
17
|
+
return ('`' +
|
|
18
|
+
this.getText().toBookdown().replace(/`/g, '\\`') +
|
|
19
|
+
'`' +
|
|
20
|
+
(this.getMeta() === 'plaintext' ? '' : this.getMeta()));
|
|
21
|
+
}
|
|
22
|
+
copy() {
|
|
23
|
+
return new InlineCodeNode(this.getText(), this.getMeta());
|
|
24
|
+
}
|
|
25
|
+
withMeta(meta) {
|
|
26
|
+
return new InlineCodeNode(this.getText(), meta);
|
|
27
|
+
}
|
|
28
|
+
withText(text) {
|
|
29
|
+
return new InlineCodeNode(text, this.getMeta());
|
|
14
30
|
}
|
|
15
|
-
copy() { return new InlineCodeNode(this.getText(), this.getMeta()); }
|
|
16
|
-
withMeta(meta) { return new InlineCodeNode(this.getText(), meta); }
|
|
17
|
-
withText(text) { return new InlineCodeNode(text, this.getMeta()); }
|
|
18
31
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import AtomNode from
|
|
2
|
-
import type Caret from
|
|
3
|
-
import type FormatNode from
|
|
4
|
-
import type Node from
|
|
1
|
+
import AtomNode from './AtomNode';
|
|
2
|
+
import type Caret from './Caret';
|
|
3
|
+
import type FormatNode from './FormatNode';
|
|
4
|
+
import type Node from './Node';
|
|
5
5
|
export default class LabelNode extends AtomNode<string> {
|
|
6
6
|
constructor(newID: string);
|
|
7
7
|
getType(): string;
|
|
@@ -1,22 +1,40 @@
|
|
|
1
|
-
import AtomNode from
|
|
2
|
-
const ERROR_PLACEHOLDER =
|
|
1
|
+
import AtomNode from './AtomNode';
|
|
2
|
+
const ERROR_PLACEHOLDER = 'LABELNOIDERROR';
|
|
3
3
|
export default class LabelNode extends AtomNode {
|
|
4
4
|
constructor(newID) {
|
|
5
|
-
super(newID === ERROR_PLACEHOLDER ?
|
|
5
|
+
super(newID === ERROR_PLACEHOLDER ? '' : newID);
|
|
6
|
+
}
|
|
7
|
+
getType() {
|
|
8
|
+
return 'label';
|
|
9
|
+
}
|
|
10
|
+
getDefaultCaret() {
|
|
11
|
+
return { node: this, index: 0 };
|
|
12
|
+
}
|
|
13
|
+
toText() {
|
|
14
|
+
return '';
|
|
15
|
+
}
|
|
16
|
+
toHTML() {
|
|
17
|
+
return '';
|
|
6
18
|
}
|
|
7
|
-
getType() { return "label"; }
|
|
8
|
-
getDefaultCaret() { return { node: this, index: 0 }; }
|
|
9
|
-
toText() { return ""; }
|
|
10
|
-
toHTML() { return ""; }
|
|
11
19
|
toBookdown(format) {
|
|
12
20
|
const id = this.getMeta();
|
|
13
21
|
const nextText = format?.getNextTextOrAtom(this)?.toBookdown();
|
|
14
22
|
// The trailing space after enables parsing. The error placeholder handles invalid empty label IDs.
|
|
15
|
-
return `:${id ===
|
|
23
|
+
return `:${id === '' ? ERROR_PLACEHOLDER : id}${nextText?.startsWith(' ') ? '' : ' '}`;
|
|
24
|
+
}
|
|
25
|
+
getParentOf() {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
copy() {
|
|
29
|
+
return new LabelNode(this.getMeta());
|
|
30
|
+
}
|
|
31
|
+
withMeta(newID) {
|
|
32
|
+
return new LabelNode(newID);
|
|
33
|
+
}
|
|
34
|
+
withChildReplaced() {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
withContentInRange() {
|
|
38
|
+
return this.copy();
|
|
16
39
|
}
|
|
17
|
-
getParentOf() { return undefined; }
|
|
18
|
-
copy() { return new LabelNode(this.getMeta()); }
|
|
19
|
-
withMeta(newID) { return new LabelNode(newID); }
|
|
20
|
-
withChildReplaced() { return undefined; }
|
|
21
|
-
withContentInRange() { return this.copy(); }
|
|
22
40
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import MetadataNode from
|
|
2
|
-
import TextNode from
|
|
1
|
+
import MetadataNode from './MetadataNode';
|
|
2
|
+
import TextNode from './TextNode';
|
|
3
3
|
export default class LinkNode extends MetadataNode<string> {
|
|
4
4
|
constructor(text?: TextNode, url?: string);
|
|
5
5
|
getType(): string;
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import MetadataNode from
|
|
2
|
-
import TextNode from
|
|
1
|
+
import MetadataNode from './MetadataNode';
|
|
2
|
+
import TextNode from './TextNode';
|
|
3
3
|
export default class LinkNode extends MetadataNode {
|
|
4
|
-
constructor(text, url =
|
|
4
|
+
constructor(text, url = '') {
|
|
5
5
|
super(text === undefined ? new TextNode() : text, url);
|
|
6
6
|
}
|
|
7
|
-
getType() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
getType() {
|
|
8
|
+
return 'link';
|
|
9
|
+
}
|
|
10
|
+
toText() {
|
|
11
|
+
return this.getText().toText();
|
|
12
|
+
}
|
|
13
|
+
toHTML() {
|
|
14
|
+
return `<a href="${this.getMeta()}">${this.getText().toHTML()}</a>`;
|
|
15
|
+
}
|
|
16
|
+
toBookdown() {
|
|
17
|
+
return `[${this.getText().toBookdown()}|${this.getMeta()}]`;
|
|
18
|
+
}
|
|
11
19
|
copy() {
|
|
12
20
|
return new LinkNode(this.getText(), this.getMeta());
|
|
13
21
|
}
|
|
14
|
-
withMeta(meta) {
|
|
15
|
-
|
|
22
|
+
withMeta(meta) {
|
|
23
|
+
return new LinkNode(this.getText(), meta);
|
|
24
|
+
}
|
|
25
|
+
withText(text) {
|
|
26
|
+
return new LinkNode(text, this.getMeta());
|
|
27
|
+
}
|
|
16
28
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type Node from
|
|
2
|
-
import FormatNode from
|
|
3
|
-
import type { Format } from
|
|
4
|
-
import type Caret from
|
|
5
|
-
import { type CaretRange } from
|
|
6
|
-
import BlockNode from
|
|
7
|
-
import type Edit from
|
|
8
|
-
export
|
|
1
|
+
import type Node from './Node';
|
|
2
|
+
import FormatNode from './FormatNode';
|
|
3
|
+
import type { Format } from './FormatNode';
|
|
4
|
+
import type Caret from './Caret';
|
|
5
|
+
import { type CaretRange } from './Caret';
|
|
6
|
+
import BlockNode from './BlockNode';
|
|
7
|
+
import type Edit from './Edit';
|
|
8
|
+
export type ListNodeType = FormatNode | ListNode;
|
|
9
9
|
export default class ListNode extends BlockNode {
|
|
10
10
|
#private;
|
|
11
11
|
constructor(items: Array<FormatNode | ListNode>, numbered: boolean);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import FormatNode from
|
|
2
|
-
import { caretToIndex, indexToCaret } from
|
|
3
|
-
import BlockNode from
|
|
1
|
+
import FormatNode from './FormatNode';
|
|
2
|
+
import { caretToIndex, indexToCaret } from './Caret';
|
|
3
|
+
import BlockNode from './BlockNode';
|
|
4
4
|
export default class ListNode extends BlockNode {
|
|
5
5
|
#numbered;
|
|
6
6
|
#items;
|
|
@@ -9,22 +9,43 @@ export default class ListNode extends BlockNode {
|
|
|
9
9
|
this.#numbered = numbered;
|
|
10
10
|
let adjustedItems = items
|
|
11
11
|
// Make sure all format nodes have an empty text.
|
|
12
|
-
.map(i => i instanceof FormatNode ? i.withTextIfEmpty() : i)
|
|
12
|
+
.map((i) => (i instanceof FormatNode ? i.withTextIfEmpty() : i))
|
|
13
13
|
// Strip all empty sublists.
|
|
14
|
-
.filter(i => !i.isEmpty());
|
|
14
|
+
.filter((i) => !i.isEmpty());
|
|
15
15
|
this.#items = adjustedItems;
|
|
16
16
|
}
|
|
17
|
-
getType() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
getType() {
|
|
18
|
+
return 'list';
|
|
19
|
+
}
|
|
20
|
+
isNumbered() {
|
|
21
|
+
return this.#numbered;
|
|
22
|
+
}
|
|
23
|
+
isEmpty() {
|
|
24
|
+
return (this.#items.length === 0 ||
|
|
25
|
+
this.#items.every((i) => i instanceof ListNode && i.isEmpty()));
|
|
26
|
+
}
|
|
27
|
+
getItems() {
|
|
28
|
+
return this.#items;
|
|
29
|
+
}
|
|
30
|
+
getChildren() {
|
|
31
|
+
return this.#items;
|
|
32
|
+
}
|
|
33
|
+
getListItems() {
|
|
34
|
+
return this.#items.filter((i) => i instanceof ListNode);
|
|
35
|
+
}
|
|
36
|
+
getLength() {
|
|
37
|
+
return this.#items.length;
|
|
38
|
+
}
|
|
39
|
+
getLastItem() {
|
|
40
|
+
return this.getFirstLastItem(false);
|
|
41
|
+
}
|
|
42
|
+
getFirstItem() {
|
|
43
|
+
return this.getFirstLastItem(true);
|
|
44
|
+
}
|
|
26
45
|
getFormats() {
|
|
27
|
-
return this.#items.reduce((previous, current) => previous.concat(current instanceof FormatNode
|
|
46
|
+
return this.#items.reduce((previous, current) => previous.concat(current instanceof FormatNode
|
|
47
|
+
? [current]
|
|
48
|
+
: current.getFormats()), []);
|
|
28
49
|
}
|
|
29
50
|
getFirstLastItem(first) {
|
|
30
51
|
if (this.#items.length === 0)
|
|
@@ -44,30 +65,46 @@ export default class ListNode extends BlockNode {
|
|
|
44
65
|
return 1;
|
|
45
66
|
}
|
|
46
67
|
toText() {
|
|
47
|
-
return this.#items.map(item => item.toText()).join(
|
|
68
|
+
return this.#items.map((item) => item.toText()).join(' ');
|
|
48
69
|
}
|
|
49
70
|
toBookdown(level = 1) {
|
|
50
|
-
return this.isNumbered()
|
|
51
|
-
this.#items
|
|
52
|
-
|
|
71
|
+
return this.isNumbered()
|
|
72
|
+
? this.#items
|
|
73
|
+
.map((item, number) => (item instanceof ListNode
|
|
74
|
+
? ''
|
|
75
|
+
: number + 1 + '.'.repeat(level) + ' ') +
|
|
76
|
+
item.toBookdown(level + 1))
|
|
77
|
+
.join('\n')
|
|
78
|
+
: this.#items
|
|
79
|
+
.map((item) => (item instanceof ListNode
|
|
80
|
+
? ''
|
|
81
|
+
: '*'.repeat(level) + ' ') +
|
|
82
|
+
item.toBookdown(level + 1))
|
|
83
|
+
.join('\n');
|
|
53
84
|
}
|
|
54
85
|
toHTML() {
|
|
55
|
-
return this.isNumbered()
|
|
56
|
-
`<ol>${this.#items
|
|
57
|
-
|
|
86
|
+
return this.isNumbered()
|
|
87
|
+
? `<ol>${this.#items
|
|
88
|
+
.map((i) => `<li>${i.toHTML()}</li>`)
|
|
89
|
+
.join('')}</ol>`
|
|
90
|
+
: `<ul>${this.#items
|
|
91
|
+
.map((i) => `<li>${i.toHTML()}</li>`)
|
|
92
|
+
.join('')}</ul>`;
|
|
58
93
|
}
|
|
59
94
|
getParentOf(node) {
|
|
60
|
-
return this.#items
|
|
95
|
+
return this.#items
|
|
96
|
+
.map((b) => (b === node ? this : b.getParentOf(node)))
|
|
97
|
+
.find((b) => b !== undefined);
|
|
61
98
|
}
|
|
62
99
|
atBeginningOfItem(root, caret) {
|
|
63
|
-
const format = caret.node.getFarthestParentMatching(root, n => n instanceof FormatNode);
|
|
64
|
-
return format !== undefined &&
|
|
100
|
+
const format = caret.node.getFarthestParentMatching(root, (n) => n instanceof FormatNode);
|
|
101
|
+
return (format !== undefined &&
|
|
65
102
|
caret.node.hasAncestor(root, this) &&
|
|
66
103
|
caret.index === 0 &&
|
|
67
|
-
format.getTextNodes()[0] === caret.node;
|
|
104
|
+
format.getTextNodes()[0] === caret.node);
|
|
68
105
|
}
|
|
69
106
|
getItemContaining(caret) {
|
|
70
|
-
const match = this.#items.find(n => n.getParentOf(caret.node) !== undefined);
|
|
107
|
+
const match = this.#items.find((n) => n.getParentOf(caret.node) !== undefined);
|
|
71
108
|
if (match === undefined)
|
|
72
109
|
return undefined;
|
|
73
110
|
const index = this.#items.indexOf(match);
|
|
@@ -80,9 +117,13 @@ export default class ListNode extends BlockNode {
|
|
|
80
117
|
return;
|
|
81
118
|
return this.#items[index];
|
|
82
119
|
}
|
|
83
|
-
getFirstCaret() {
|
|
120
|
+
getFirstCaret() {
|
|
121
|
+
return this.#items.length === 0
|
|
122
|
+
? undefined
|
|
123
|
+
: this.#items[0].getFirstCaret();
|
|
124
|
+
}
|
|
84
125
|
copy() {
|
|
85
|
-
return new ListNode(this.#items.map(i => i.copy()), this.#numbered);
|
|
126
|
+
return new ListNode(this.#items.map((i) => i.copy()), this.#numbered);
|
|
86
127
|
}
|
|
87
128
|
withStyle(numbered) {
|
|
88
129
|
return new ListNode(this.#items, numbered);
|
|
@@ -211,14 +252,16 @@ export default class ListNode extends BlockNode {
|
|
|
211
252
|
}
|
|
212
253
|
withItemSplit(caret) {
|
|
213
254
|
// Which item contains the caret?
|
|
214
|
-
const item = this.#items.find(i => i instanceof FormatNode && i.contains(caret.node));
|
|
255
|
+
const item = this.#items.find((i) => i instanceof FormatNode && i.contains(caret.node));
|
|
215
256
|
if (item === undefined)
|
|
216
257
|
return;
|
|
217
258
|
const parts = item.split(caret);
|
|
218
259
|
if (parts === undefined)
|
|
219
260
|
return;
|
|
220
261
|
const [first, second] = parts;
|
|
221
|
-
return this.withItemAfter(second, item)
|
|
262
|
+
return this.withItemAfter(second, item)
|
|
263
|
+
?.withItemAfter(first, item)
|
|
264
|
+
?.withoutItem(item);
|
|
222
265
|
}
|
|
223
266
|
// Recursively search for the given item and indent it, constructing a new list.
|
|
224
267
|
withItemIndented(format) {
|
|
@@ -283,9 +326,16 @@ export default class ListNode extends BlockNode {
|
|
|
283
326
|
const index = this.#items.indexOf(node);
|
|
284
327
|
if (index < 0)
|
|
285
328
|
return;
|
|
286
|
-
return new ListNode(replacement === undefined
|
|
287
|
-
[
|
|
288
|
-
|
|
329
|
+
return new ListNode(replacement === undefined
|
|
330
|
+
? [
|
|
331
|
+
...this.#items.slice(0, index),
|
|
332
|
+
...this.#items.slice(index + 1),
|
|
333
|
+
]
|
|
334
|
+
: [
|
|
335
|
+
...this.#items.slice(0, index),
|
|
336
|
+
replacement,
|
|
337
|
+
...this.#items.slice(index + 1),
|
|
338
|
+
], this.#numbered);
|
|
289
339
|
}
|
|
290
340
|
withContentInRange(range) {
|
|
291
341
|
const containsStart = this.contains(range.start.node);
|
|
@@ -316,7 +366,7 @@ export default class ListNode extends BlockNode {
|
|
|
316
366
|
if (!(node instanceof ListNode))
|
|
317
367
|
return;
|
|
318
368
|
// Find the anchor item.
|
|
319
|
-
const anchor = this.#items.find(i => i.contains(caret.node));
|
|
369
|
+
const anchor = this.#items.find((i) => i.contains(caret.node));
|
|
320
370
|
if (anchor === undefined)
|
|
321
371
|
return;
|
|
322
372
|
const items = node.getItems();
|
|
@@ -343,7 +393,9 @@ export default class ListNode extends BlockNode {
|
|
|
343
393
|
lastItem = item;
|
|
344
394
|
}
|
|
345
395
|
// The caret should be the last item inserted.
|
|
346
|
-
const newCaret = lastItem instanceof FormatNode
|
|
396
|
+
const newCaret = lastItem instanceof FormatNode
|
|
397
|
+
? lastItem.getLastCaret()
|
|
398
|
+
: lastItem.getLastItem()?.getLastCaret();
|
|
347
399
|
if (newCaret === undefined)
|
|
348
400
|
return;
|
|
349
401
|
return { root: newList, range: { start: newCaret, end: newCaret } };
|
|
@@ -352,9 +404,15 @@ export default class ListNode extends BlockNode {
|
|
|
352
404
|
const sortedRange = this.sortRange(range);
|
|
353
405
|
const itemStart = this.getItemContaining(sortedRange.start);
|
|
354
406
|
const itemEnd = this.getItemContaining(sortedRange.end);
|
|
407
|
+
// This edits all of the formats contained in the range in the list, since the BlockNode class doesn't care about
|
|
408
|
+
// what formats are stored in.
|
|
355
409
|
const edit = super.withRangeFormatted(sortedRange, format);
|
|
356
410
|
// If we were deleting and two list items were involved, merge them.
|
|
357
|
-
if (edit &&
|
|
411
|
+
if (edit &&
|
|
412
|
+
format === undefined &&
|
|
413
|
+
itemStart !== undefined &&
|
|
414
|
+
itemEnd !== undefined &&
|
|
415
|
+
itemStart !== itemEnd) {
|
|
358
416
|
const newList = edit.root;
|
|
359
417
|
const itemIndex = itemEnd - (this.#items.length - newList.#items.length);
|
|
360
418
|
if (itemIndex > 0 && newList.getLength() > 1) {
|
|
@@ -362,7 +420,10 @@ export default class ListNode extends BlockNode {
|
|
|
362
420
|
const mergedEdit = newList.withItemMergedBackwards(itemIndex);
|
|
363
421
|
if (mergedEdit === undefined)
|
|
364
422
|
return;
|
|
365
|
-
return {
|
|
423
|
+
return {
|
|
424
|
+
root: mergedEdit[0],
|
|
425
|
+
range: { start: mergedEdit[1], end: mergedEdit[1] },
|
|
426
|
+
};
|
|
366
427
|
}
|
|
367
428
|
}
|
|
368
429
|
return edit;
|
|
@@ -1,48 +1,53 @@
|
|
|
1
1
|
import { test, expect } from 'vitest';
|
|
2
|
-
import FormatNode from
|
|
3
|
-
import ListNode from
|
|
4
|
-
import TextNode from
|
|
5
|
-
const oneText = new TextNode(
|
|
6
|
-
const oneFormat = new FormatNode(
|
|
7
|
-
const twoText = new TextNode(
|
|
8
|
-
const twoFormat = new FormatNode(
|
|
9
|
-
const threeText = new TextNode(
|
|
10
|
-
const threeFormat = new FormatNode(
|
|
11
|
-
const fourText = new TextNode(
|
|
12
|
-
const fourFormat = new FormatNode(
|
|
13
|
-
const fiveText = new TextNode(
|
|
14
|
-
const fiveFormat = new FormatNode(
|
|
2
|
+
import FormatNode from './FormatNode';
|
|
3
|
+
import ListNode from './ListNode';
|
|
4
|
+
import TextNode from './TextNode';
|
|
5
|
+
const oneText = new TextNode('one');
|
|
6
|
+
const oneFormat = new FormatNode('', [oneText]);
|
|
7
|
+
const twoText = new TextNode('two');
|
|
8
|
+
const twoFormat = new FormatNode('', [twoText]);
|
|
9
|
+
const threeText = new TextNode('three');
|
|
10
|
+
const threeFormat = new FormatNode('', [threeText]);
|
|
11
|
+
const fourText = new TextNode('four');
|
|
12
|
+
const fourFormat = new FormatNode('', [fourText]);
|
|
13
|
+
const fiveText = new TextNode('five');
|
|
14
|
+
const fiveFormat = new FormatNode('', [fiveText]);
|
|
15
15
|
const shortList = new ListNode([oneFormat, twoFormat, threeFormat], false);
|
|
16
|
-
const list = new ListNode([
|
|
17
|
-
|
|
16
|
+
const list = new ListNode([
|
|
17
|
+
oneFormat,
|
|
18
|
+
new ListNode([twoFormat, threeFormat, fourFormat], false),
|
|
19
|
+
fiveFormat,
|
|
20
|
+
], false);
|
|
21
|
+
test('Insert items', () => {
|
|
18
22
|
expect(shortList.withItemAppended(fourFormat)?.toBookdown()).toBe(`* one\n* two\n* three\n* four`);
|
|
19
23
|
expect(shortList.withItemPrepended(fourFormat)?.toBookdown()).toBe(`* four\n* one\n* two\n* three`);
|
|
20
24
|
expect(shortList.withItemAt(fourFormat, 9)).toBeUndefined();
|
|
21
25
|
expect(shortList.withItemAt(fourFormat, 1)?.toBookdown()).toBe(`* one\n* four\n* two\n* three`);
|
|
22
26
|
expect(shortList.withItemAfter(fourFormat, oneFormat)?.toBookdown()).toBe(`* one\n* four\n* two\n* three`);
|
|
23
27
|
expect(shortList.withItemBefore(fourFormat, twoFormat)?.toBookdown()).toBe(`* one\n* four\n* two\n* three`);
|
|
24
|
-
expect(shortList
|
|
28
|
+
expect(shortList
|
|
29
|
+
.withListAppended(new ListNode([fourFormat, fiveFormat], true))
|
|
30
|
+
?.toBookdown()).toBe(`* one\n* two\n* three\n* four\n* five`);
|
|
25
31
|
});
|
|
26
|
-
test(
|
|
32
|
+
test('Remove items', () => {
|
|
27
33
|
expect(shortList.withItemReplaced(1, fourFormat)?.toBookdown()).toBe(`* one\n* four\n* three`);
|
|
28
34
|
expect(shortList.withoutItemAt(0)?.toBookdown()).toBe(`* two\n* three`);
|
|
29
35
|
});
|
|
30
|
-
test(
|
|
31
|
-
expect(shortList.withItemSplit({ node: threeText, index: 2 })?.toBookdown())
|
|
32
|
-
.toBe("* one\n* two\n* th\n* ree");
|
|
36
|
+
test('Split', () => {
|
|
37
|
+
expect(shortList.withItemSplit({ node: threeText, index: 2 })?.toBookdown()).toBe('* one\n* two\n* th\n* ree');
|
|
33
38
|
});
|
|
34
|
-
test(
|
|
39
|
+
test('Merge', () => {
|
|
35
40
|
const merged = shortList.withItemMergedBackwards(1);
|
|
36
41
|
expect(merged).not.toBeUndefined();
|
|
37
42
|
if (merged !== undefined)
|
|
38
|
-
expect(merged[0].toBookdown()).toBe(
|
|
43
|
+
expect(merged[0].toBookdown()).toBe('* onetwo\n* three');
|
|
39
44
|
});
|
|
40
|
-
test(
|
|
45
|
+
test('Indent', () => {
|
|
41
46
|
expect(list.withItemIndented(oneFormat)?.toBookdown()).toBe(`** one\n** two\n** three\n** four\n* five`);
|
|
42
47
|
expect(list.withItemIndented(twoFormat)?.toBookdown()).toBe(`* one\n*** two\n** three\n** four\n* five`);
|
|
43
48
|
expect(list.withItemIndented(fiveFormat)?.toBookdown()).toBe(`* one\n** two\n** three\n** four\n** five`);
|
|
44
49
|
});
|
|
45
|
-
test(
|
|
50
|
+
test('Unindent', () => {
|
|
46
51
|
expect(list.withItemUnindented(twoFormat)?.toBookdown()).toBe(`* one\n* two\n** three\n** four\n* five`);
|
|
47
52
|
expect(list.withItemUnindented(oneFormat)?.toBookdown()).toBeUndefined();
|
|
48
53
|
expect(list.withItemUnindented(threeFormat)?.toBookdown()).toBe(`* one\n** two\n* three\n** four\n* five`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CaretRange } from
|
|
2
|
-
import Node from
|
|
3
|
-
import type TextNode from
|
|
1
|
+
import type { CaretRange } from './Caret';
|
|
2
|
+
import Node from './Node';
|
|
3
|
+
import type TextNode from './TextNode';
|
|
4
4
|
export default abstract class MetadataNode<MetaType> extends Node {
|
|
5
5
|
#private;
|
|
6
6
|
constructor(text: TextNode, meta: MetaType);
|