bookish-press 0.4.0 → 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 -80
- 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,31 +1,34 @@
|
|
|
1
|
-
<script>import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import
|
|
1
|
+
<script>import BookishNode from '../../models/chapter/Node';
|
|
2
|
+
import ChapterNode from '../../models/chapter/ChapterNode';
|
|
3
|
+
import Parser from '../../models/chapter/Parser';
|
|
4
|
+
import LinkNode from '../../models/chapter/LinkNode';
|
|
5
|
+
import ParagraphNode from '../../models/chapter/ParagraphNode';
|
|
6
|
+
import TextNode from '../../models/chapter/TextNode';
|
|
7
|
+
import AtomNode from '../../models/chapter/AtomNode';
|
|
8
|
+
import FormatNode from '../../models/chapter/FormatNode';
|
|
9
|
+
import BlocksNode from '../../models/chapter/BlocksNode';
|
|
10
|
+
import ListNode from '../../models/chapter/ListNode';
|
|
11
|
+
import TableNode from '../../models/chapter/TableNode';
|
|
12
|
+
import MetadataNode from '../../models/chapter/MetadataNode';
|
|
13
|
+
import CodeNode from '../../models/chapter/CodeNode';
|
|
14
|
+
import BlockNode from '../../models/chapter/BlockNode';
|
|
15
|
+
import EmbedNode from '../../models/chapter/EmbedNode';
|
|
16
|
+
import ErrorNode from '../../models/chapter/ErrorNode';
|
|
17
|
+
import { caretRangeToIndexRange, indexRangeToCaretRange, } from '../../models/chapter/Caret';
|
|
18
|
+
import commands from './Commands';
|
|
19
|
+
import { afterUpdate, onMount, setContext } from 'svelte';
|
|
20
|
+
import { getCaret } from '../page/Contexts';
|
|
21
|
+
import CaretView from './CaretView.svelte';
|
|
22
22
|
const IDLE_TIME = 500;
|
|
23
|
-
export let
|
|
23
|
+
export let text;
|
|
24
|
+
export let parser;
|
|
24
25
|
export let save;
|
|
25
26
|
export let chapter;
|
|
26
27
|
export let autofocus = false;
|
|
27
28
|
export let component;
|
|
28
29
|
export let placeholder;
|
|
30
|
+
export let leasee;
|
|
31
|
+
export let lease;
|
|
29
32
|
let element = null;
|
|
30
33
|
let caretRange = undefined;
|
|
31
34
|
let caretCoordinate = undefined;
|
|
@@ -35,9 +38,19 @@ let editorFocused = false;
|
|
|
35
38
|
let undoStack = [];
|
|
36
39
|
let undoPosition = -1;
|
|
37
40
|
let clipboard = undefined;
|
|
38
|
-
let editedNode = ast;
|
|
39
41
|
let ignoredInput = false;
|
|
40
|
-
let
|
|
42
|
+
let activeEditor = getCaret();
|
|
43
|
+
let editedNode;
|
|
44
|
+
$: {
|
|
45
|
+
// Note: when the text changes externally, the caret will be lost. We either have
|
|
46
|
+
// to implement fancy operational transform revision control for collaborative editing
|
|
47
|
+
// or a basic chapter locking strategy to avoid data loss. I went with locking for maintenance simplicity,
|
|
48
|
+
// but it would be nice to implement operational transform in the future.
|
|
49
|
+
if (editedNode === undefined || editedNode.toBookdown() !== text) {
|
|
50
|
+
editedNode = parser(text);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
$: locked = typeof leasee === 'string';
|
|
41
54
|
onMount(() => {
|
|
42
55
|
const caret = editedNode.getFirstCaret();
|
|
43
56
|
if (caret)
|
|
@@ -47,15 +60,15 @@ onMount(() => {
|
|
|
47
60
|
element.focus();
|
|
48
61
|
}
|
|
49
62
|
// Listen to selection changes
|
|
50
|
-
document.addEventListener(
|
|
63
|
+
document.addEventListener('selectionchange', handleSelectionChange);
|
|
51
64
|
// Stop listening to selection changes
|
|
52
65
|
return () => {
|
|
53
|
-
document.removeEventListener(
|
|
66
|
+
document.removeEventListener('selectionchange', handleSelectionChange);
|
|
54
67
|
};
|
|
55
68
|
});
|
|
56
69
|
onMount(() => {
|
|
57
70
|
// When input happens, set a timer and then see if idle time has elapsed. If it has, track time since last keystroke to control caret blinking behavior.
|
|
58
|
-
const keystrokeTimer =
|
|
71
|
+
const keystrokeTimer = setInterval(() => {
|
|
59
72
|
// Remember that we're idle so we can render things accordingly.
|
|
60
73
|
const isIdle = Date.now() - lastInputTime > IDLE_TIME;
|
|
61
74
|
if (isIdle) {
|
|
@@ -83,19 +96,26 @@ afterUpdate(() => {
|
|
|
83
96
|
const sortedRange = caretRange;
|
|
84
97
|
let startNode = document.querySelector(`[data-nodeid='${sortedRange.start.node.nodeID}`);
|
|
85
98
|
let endNode = document.querySelector(`[data-nodeid='${sortedRange.end.node.nodeID}`);
|
|
86
|
-
// If we found both selected nodes and we have a reference to the DOM, update the
|
|
99
|
+
// If we found both selected nodes and we have a reference to the DOM, update the
|
|
87
100
|
// browser's selection if necessary and measure it's position so we can draw our own caret.
|
|
88
101
|
if (startNode && endNode && element) {
|
|
89
102
|
// If the current selection isn't different from the new one, then we don't do any of this.
|
|
90
|
-
// This prevents an infinite loop when, for example, the user clicks, the browser selection changes,
|
|
103
|
+
// This prevents an infinite loop when, for example, the user clicks, the browser selection changes,
|
|
91
104
|
// and we update the caret range, which updates the browser selection, ad infinitum.
|
|
92
105
|
let rangeChanged = true;
|
|
93
106
|
let currentRange = undefined;
|
|
94
107
|
if (docSelection.rangeCount > 0) {
|
|
95
108
|
currentRange = docSelection.getRangeAt(0);
|
|
96
109
|
// If our caret range is non-empty TextNodes at a particular index and equal to the browser's caret range, then nothing's changed, so we shouldn't update the selection.
|
|
97
|
-
const startIsEqual =
|
|
98
|
-
|
|
110
|
+
const startIsEqual = startNode.childNodes.length > 0 &&
|
|
111
|
+
currentRange.startContainer ===
|
|
112
|
+
startNode.childNodes[0] &&
|
|
113
|
+
currentRange.startOffset ===
|
|
114
|
+
sortedRange.start.index;
|
|
115
|
+
const endIsEqual = endNode.childNodes.length > 0 &&
|
|
116
|
+
currentRange.endContainer ===
|
|
117
|
+
endNode.childNodes[0] &&
|
|
118
|
+
currentRange.endOffset === sortedRange.end.index;
|
|
99
119
|
if (startIsEqual && endIsEqual)
|
|
100
120
|
rangeChanged = false;
|
|
101
121
|
}
|
|
@@ -105,7 +125,8 @@ afterUpdate(() => {
|
|
|
105
125
|
// We only do this to the end node if it's different from the start node.
|
|
106
126
|
// We leave them in there so that the "rangeChanged" guard below can track them.
|
|
107
127
|
const emptyStart = startNode.childNodes.length === 0;
|
|
108
|
-
const emptyEnd = startNode !== endNode &&
|
|
128
|
+
const emptyEnd = startNode !== endNode &&
|
|
129
|
+
endNode.childNodes.length === 0;
|
|
109
130
|
if (emptyStart)
|
|
110
131
|
startNode.appendChild(document.createTextNode('\ufeff'));
|
|
111
132
|
if (emptyEnd)
|
|
@@ -113,7 +134,9 @@ afterUpdate(() => {
|
|
|
113
134
|
// If we're just after a new line, set the selection to the character after.
|
|
114
135
|
const afterNewLine = sortedRange.start.node instanceof TextNode &&
|
|
115
136
|
sortedRange.start.index > 0 &&
|
|
116
|
-
sortedRange.start.node
|
|
137
|
+
sortedRange.start.node
|
|
138
|
+
.getText()
|
|
139
|
+
.charAt(sortedRange.start.index - 1) === '\n';
|
|
117
140
|
// If the range has changed, set the selection so we can measure it's location.
|
|
118
141
|
// We guard this to avoid triggering unnecessary selection change events that don't actually modify the selection.
|
|
119
142
|
if (rangeChanged) {
|
|
@@ -122,7 +145,7 @@ afterUpdate(() => {
|
|
|
122
145
|
}
|
|
123
146
|
catch (e) {
|
|
124
147
|
console.error(e);
|
|
125
|
-
|
|
148
|
+
console.error(`Error setting caret range, trying to set to ${startNode.childNodes[0]}:${sortedRange.start.index} - ${endNode.childNodes[0]}:${sortedRange.end.index}`);
|
|
126
149
|
}
|
|
127
150
|
currentRange = docSelection.getRangeAt(0);
|
|
128
151
|
}
|
|
@@ -130,26 +153,35 @@ afterUpdate(() => {
|
|
|
130
153
|
if (currentRange) {
|
|
131
154
|
const rangeRect = currentRange.getBoundingClientRect();
|
|
132
155
|
const textRect = startNode.getBoundingClientRect();
|
|
133
|
-
const lineHeightString = window
|
|
134
|
-
|
|
156
|
+
const lineHeightString = window
|
|
157
|
+
.getComputedStyle(startNode)
|
|
158
|
+
.getPropertyValue('line-height');
|
|
159
|
+
const lineHeight = lineHeightString.endsWith('px')
|
|
160
|
+
? parseInt(lineHeightString.substring(0, lineHeightString.length - 2))
|
|
161
|
+
: undefined;
|
|
135
162
|
// Is the caret in relatively positioned ancestors above the editor? Undo their offsets.
|
|
136
|
-
let caretAncestor = startNode.closest(
|
|
163
|
+
let caretAncestor = startNode.closest('.bookish-editor');
|
|
137
164
|
let relativeX = 0;
|
|
138
165
|
let relativeY = 0;
|
|
139
166
|
while (caretAncestor != null) {
|
|
140
|
-
if (window.getComputedStyle(caretAncestor)
|
|
167
|
+
if (window.getComputedStyle(caretAncestor)
|
|
168
|
+
.position === 'relative') {
|
|
141
169
|
relativeX += caretAncestor.offsetLeft;
|
|
142
170
|
relativeY += caretAncestor.offsetTop;
|
|
143
171
|
}
|
|
144
172
|
caretAncestor = caretAncestor.parentElement;
|
|
145
173
|
}
|
|
146
174
|
// If we're after a new line, calculate the correct position, since selections don't actually render to the next line.
|
|
147
|
-
const left = afterNewLine
|
|
148
|
-
|
|
175
|
+
const left = afterNewLine
|
|
176
|
+
? textRect.left
|
|
177
|
+
: rangeRect.left;
|
|
178
|
+
const top = afterNewLine && lineHeight
|
|
179
|
+
? rangeRect.top + lineHeight
|
|
180
|
+
: rangeRect.top;
|
|
149
181
|
const position = {
|
|
150
182
|
x: left + window.scrollX - relativeX,
|
|
151
183
|
y: top + window.scrollY - relativeY,
|
|
152
|
-
height: rangeRect.height
|
|
184
|
+
height: rangeRect.height,
|
|
153
185
|
};
|
|
154
186
|
newCaretPosition = position;
|
|
155
187
|
}
|
|
@@ -161,38 +193,30 @@ afterUpdate(() => {
|
|
|
161
193
|
}
|
|
162
194
|
// Save the new caret position so we render it.
|
|
163
195
|
caretCoordinate = newCaretPosition;
|
|
164
|
-
// If the caret position is outside the window, and the editor is focused, scroll to make the caret visible.
|
|
165
|
-
if (newCaretPosition && editorFocused) {
|
|
166
|
-
const caretTop = newCaretPosition.y;
|
|
167
|
-
const caretBottom = caretTop + newCaretPosition.height;
|
|
168
|
-
const windowHeight = window.innerHeight;
|
|
169
|
-
const toolbar = element?.querySelector(".bookish-editor-toolbar");
|
|
170
|
-
const toolbarHeight = toolbar ? toolbar.clientHeight : 0;
|
|
171
|
-
const buffer = newCaretPosition.height * 5;
|
|
172
|
-
if (caretTop < window.scrollY + buffer + toolbarHeight) {
|
|
173
|
-
window.scrollTo({ top: caretTop - buffer, behavior: 'smooth' });
|
|
174
|
-
}
|
|
175
|
-
else if (caretBottom > window.scrollY + windowHeight - buffer) {
|
|
176
|
-
window.scrollTo({ top: caretBottom - (windowHeight - buffer), behavior: 'smooth' });
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
196
|
});
|
|
180
197
|
function rangeToCaret(domNode, rangeIndex) {
|
|
181
198
|
// If it's a text node, find the closest TextNode parent
|
|
182
199
|
if (domNode.nodeType === Node.TEXT_NODE) {
|
|
183
200
|
let parent = domNode.parentNode;
|
|
184
201
|
// Keep looking up until we find the TextNode span with the node ID.
|
|
185
|
-
while (parent &&
|
|
202
|
+
while (parent &&
|
|
203
|
+
!(parent instanceof HTMLElement &&
|
|
204
|
+
parent.classList.contains('bookish-text')))
|
|
186
205
|
parent = parent.parentNode;
|
|
187
206
|
if (parent && parent.dataset.nodeid) {
|
|
188
207
|
const node = editedNode.getNode(parseInt(parent.dataset.nodeid));
|
|
189
208
|
if (node instanceof TextNode)
|
|
190
209
|
// Account for the zero-width spaces that we insert in order to make selections possible on empty text nodes.
|
|
191
|
-
return {
|
|
210
|
+
return {
|
|
211
|
+
node: node,
|
|
212
|
+
index: Math.min(rangeIndex, node.getLength()),
|
|
213
|
+
};
|
|
192
214
|
}
|
|
193
215
|
}
|
|
194
216
|
// If it's an element, see if it has a nodeID and handle it accordingly.
|
|
195
|
-
else if (domNode.nodeType === Node.ELEMENT_NODE &&
|
|
217
|
+
else if (domNode.nodeType === Node.ELEMENT_NODE &&
|
|
218
|
+
domNode instanceof HTMLElement &&
|
|
219
|
+
domNode.dataset.nodeid) {
|
|
196
220
|
const node = editedNode.getNode(parseInt(domNode.dataset.nodeid));
|
|
197
221
|
// These assume that triple clicks on paragraphs in the browser choose text nodes for the selection start
|
|
198
222
|
// and spans or paragraph nodes for the end.
|
|
@@ -213,7 +237,7 @@ function handleSelectionChange() {
|
|
|
213
237
|
keyboardIdle = false;
|
|
214
238
|
// Map the browser selection to our caret range model.
|
|
215
239
|
const selection = document.getSelection();
|
|
216
|
-
if (selection && selection.anchorNode && selection.
|
|
240
|
+
if (selection && selection.anchorNode && selection.focusNode) {
|
|
217
241
|
const start = rangeToCaret(selection.anchorNode, selection.anchorOffset);
|
|
218
242
|
const end = rangeToCaret(selection.focusNode, selection.focusOffset);
|
|
219
243
|
// If we found to text nodes, set the selection
|
|
@@ -234,9 +258,17 @@ function getCaretCoordinate(caret) {
|
|
|
234
258
|
range.setStart(domNode.childNodes.length === 0 ? domNode : domNode.childNodes[0], domNode.childNodes.length === 0 ? 0 : caret.index);
|
|
235
259
|
const characterRect = range.getBoundingClientRect();
|
|
236
260
|
if (characterRect.left > 0)
|
|
237
|
-
return {
|
|
261
|
+
return {
|
|
262
|
+
top: characterRect.top,
|
|
263
|
+
left: characterRect.left,
|
|
264
|
+
height: characterRect.height,
|
|
265
|
+
};
|
|
238
266
|
const elementRect = domNode.getBoundingClientRect();
|
|
239
|
-
return {
|
|
267
|
+
return {
|
|
268
|
+
top: elementRect.top,
|
|
269
|
+
left: elementRect.left,
|
|
270
|
+
height: elementRect.height,
|
|
271
|
+
};
|
|
240
272
|
}
|
|
241
273
|
function getCaretOnLine(caret, below) {
|
|
242
274
|
if (caret.node instanceof TextNode || caret.node instanceof AtomNode) {
|
|
@@ -248,7 +280,8 @@ function getCaretOnLine(caret, below) {
|
|
|
248
280
|
let previousCandidate = undefined;
|
|
249
281
|
let previousCoordinate = undefined;
|
|
250
282
|
if (startCoordinate) {
|
|
251
|
-
while (candidate.node instanceof TextNode ||
|
|
283
|
+
while (candidate.node instanceof TextNode ||
|
|
284
|
+
candidate.node instanceof AtomNode) {
|
|
252
285
|
const candidateCoordinate = getCaretCoordinate(candidate);
|
|
253
286
|
// Did we make it to the next line and the character before/after? If we're going down,
|
|
254
287
|
// we're looking for a top that's below the bottom. If we're going up, we're looking for a bottom
|
|
@@ -256,21 +289,43 @@ function getCaretOnLine(caret, below) {
|
|
|
256
289
|
if (candidateCoordinate) {
|
|
257
290
|
const startTop = startCoordinate.top;
|
|
258
291
|
const candidateTop = candidateCoordinate.top;
|
|
259
|
-
const closerCandidate = previousCoordinate &&
|
|
292
|
+
const closerCandidate = previousCoordinate &&
|
|
293
|
+
previousCandidate &&
|
|
294
|
+
Math.abs(startCoordinate.left - previousCoordinate.left) <
|
|
295
|
+
Math.abs(startCoordinate.left -
|
|
296
|
+
candidateCoordinate.left)
|
|
297
|
+
? previousCandidate
|
|
298
|
+
: candidate;
|
|
260
299
|
if (below) {
|
|
261
300
|
// If this candidate is on the line below the start line, then return the last candidate on the line below the start line.
|
|
262
|
-
if (previousCandidate &&
|
|
301
|
+
if (previousCandidate &&
|
|
302
|
+
previousCoordinate &&
|
|
303
|
+
previousCoordinate.top >
|
|
304
|
+
startTop + startCoordinate.height &&
|
|
305
|
+
candidateTop >
|
|
306
|
+
previousCoordinate.top +
|
|
307
|
+
previousCoordinate.height)
|
|
263
308
|
return previousCandidate;
|
|
264
309
|
// If this is just below the start position, stop and return the closer of the current and previous candidates.
|
|
265
|
-
else if (candidateTop >
|
|
310
|
+
else if (candidateTop >
|
|
311
|
+
startTop + startCoordinate.height &&
|
|
312
|
+
candidateCoordinate.left >= startCoordinate.left)
|
|
266
313
|
return closerCandidate;
|
|
267
314
|
}
|
|
268
315
|
else {
|
|
269
316
|
// If this candidate is on the live above the line above the start line, then return the last candidate on the line above the start line.
|
|
270
|
-
if (previousCandidate &&
|
|
317
|
+
if (previousCandidate &&
|
|
318
|
+
previousCoordinate &&
|
|
319
|
+
previousCoordinate.top +
|
|
320
|
+
previousCoordinate.height <
|
|
321
|
+
startTop &&
|
|
322
|
+
candidateTop + candidateCoordinate.height <
|
|
323
|
+
previousCoordinate.top)
|
|
271
324
|
return previousCandidate;
|
|
272
325
|
// If this is just above the start position, stop and return the closer of the current and previous candidates.
|
|
273
|
-
if (candidateTop + candidateCoordinate.height <
|
|
326
|
+
if (candidateTop + candidateCoordinate.height <
|
|
327
|
+
startTop &&
|
|
328
|
+
candidateCoordinate.left <= startCoordinate.left)
|
|
274
329
|
return closerCandidate;
|
|
275
330
|
}
|
|
276
331
|
}
|
|
@@ -279,7 +334,8 @@ function getCaretOnLine(caret, below) {
|
|
|
279
334
|
if (nextCandidate === undefined)
|
|
280
335
|
break;
|
|
281
336
|
// If the caret didn't move, we stop searching, something is wrong.
|
|
282
|
-
if (nextCandidate.node === candidate.node &&
|
|
337
|
+
if (nextCandidate.node === candidate.node &&
|
|
338
|
+
nextCandidate.index === candidate.index) {
|
|
283
339
|
break;
|
|
284
340
|
}
|
|
285
341
|
// Otherwise, we advance to the next candidate.
|
|
@@ -301,21 +357,22 @@ function atParagraphStart() {
|
|
|
301
357
|
caretRange.start.index !== caretRange.end.index ||
|
|
302
358
|
!(caretRange.start.node instanceof TextNode))
|
|
303
359
|
return false;
|
|
304
|
-
const firstCaret = caretRange.start.node
|
|
305
|
-
|
|
360
|
+
const firstCaret = caretRange.start.node
|
|
361
|
+
.getFormatRoot(editedNode)
|
|
362
|
+
?.getFirstCaret();
|
|
363
|
+
return (firstCaret !== undefined &&
|
|
364
|
+
firstCaret.node === caretRange.start.node &&
|
|
365
|
+
firstCaret.index === caretRange.start.index);
|
|
306
366
|
}
|
|
307
367
|
function undo() {
|
|
308
368
|
// Grab the next state
|
|
309
369
|
let undoState = undoStack[undoPosition + 1];
|
|
310
370
|
// Restore the content of the chapter.
|
|
311
|
-
let node =
|
|
312
|
-
ast instanceof FormatNode ? Parser.parseFormat($edition, undoState.bookdown) :
|
|
313
|
-
ast instanceof EmbedNode ? Parser.parseEmbed($edition, undoState.bookdown) :
|
|
314
|
-
undefined;
|
|
371
|
+
let node = parser(undoState.bookdown);
|
|
315
372
|
if (node === undefined || node instanceof ErrorNode)
|
|
316
373
|
return;
|
|
317
374
|
// Restore the view
|
|
318
|
-
|
|
375
|
+
updateRoot(node);
|
|
319
376
|
// Save the undo.
|
|
320
377
|
save(node);
|
|
321
378
|
// Move the undo state down a position.
|
|
@@ -331,13 +388,10 @@ function redo() {
|
|
|
331
388
|
// Grab the next state
|
|
332
389
|
let undoState = undoStack[undoPosition - 1];
|
|
333
390
|
// Restore the content of the chapter.
|
|
334
|
-
let node =
|
|
335
|
-
ast instanceof FormatNode ? Parser.parseFormat($edition, undoState.bookdown) :
|
|
336
|
-
ast instanceof EmbedNode ? Parser.parseEmbed($edition, undoState.bookdown) :
|
|
337
|
-
undefined;
|
|
391
|
+
let node = parser(undoState.bookdown);
|
|
338
392
|
if (node === undefined)
|
|
339
393
|
return;
|
|
340
|
-
|
|
394
|
+
updateRoot(node);
|
|
341
395
|
// Move the undo state down a position.
|
|
342
396
|
if (undoPosition > 0)
|
|
343
397
|
undoPosition = undoPosition - 1;
|
|
@@ -354,39 +408,50 @@ function getCaretContext() {
|
|
|
354
408
|
const nodes = editedNode.getNodes();
|
|
355
409
|
let inside = false;
|
|
356
410
|
let includesList = false;
|
|
357
|
-
nodes.forEach(n => {
|
|
411
|
+
nodes.forEach((n) => {
|
|
358
412
|
if (caretRange === undefined)
|
|
359
413
|
return;
|
|
360
414
|
if (n === caretRange.start.node)
|
|
361
415
|
inside = true;
|
|
362
|
-
if (inside &&
|
|
416
|
+
if (inside &&
|
|
417
|
+
n.getClosestParentMatching(editedNode, (p) => p instanceof ListNode) !== undefined)
|
|
363
418
|
includesList = true;
|
|
364
419
|
if (n === caretRange.end.node)
|
|
365
420
|
inside = false;
|
|
366
421
|
});
|
|
367
|
-
const parents = editedNode
|
|
422
|
+
const parents = editedNode
|
|
423
|
+
.getParentsOf(caretRange.start.node)
|
|
424
|
+
?.reverse();
|
|
368
425
|
return {
|
|
369
426
|
// We make a new range so that setCaretRange always causes a re-render
|
|
370
427
|
chapter: chapter,
|
|
371
428
|
range: { start: caretRange.start, end: caretRange.end },
|
|
372
429
|
start: caretRange.start,
|
|
373
430
|
end: caretRange.end,
|
|
374
|
-
isSelection: caretRange.start.node !== caretRange.end.node ||
|
|
431
|
+
isSelection: caretRange.start.node !== caretRange.end.node ||
|
|
432
|
+
caretRange.start.index !== caretRange.end.index,
|
|
375
433
|
root: editedNode,
|
|
376
|
-
blocks: parents?.find(n => n instanceof BlocksNode),
|
|
377
|
-
paragraph: parents?.find(n => n instanceof ParagraphNode),
|
|
378
|
-
block: parents?.find(n => n instanceof BlockNode),
|
|
379
|
-
code: parents?.find(n => n instanceof CodeNode),
|
|
380
|
-
list: parents?.find(n => n instanceof ListNode),
|
|
381
|
-
atom: parents?.find(n => n instanceof AtomNode),
|
|
382
|
-
meta: parents?.find(n => n instanceof MetadataNode),
|
|
434
|
+
blocks: parents?.find((n) => n instanceof BlocksNode),
|
|
435
|
+
paragraph: parents?.find((n) => n instanceof ParagraphNode),
|
|
436
|
+
block: parents?.find((n) => n instanceof BlockNode),
|
|
437
|
+
code: parents?.find((n) => n instanceof CodeNode),
|
|
438
|
+
list: parents?.find((n) => n instanceof ListNode),
|
|
439
|
+
atom: parents?.find((n) => n instanceof AtomNode),
|
|
440
|
+
meta: parents?.find((n) => n instanceof MetadataNode),
|
|
383
441
|
includesList: includesList,
|
|
384
|
-
table: parents?.find(n => n instanceof TableNode),
|
|
385
|
-
format:
|
|
442
|
+
table: parents?.find((n) => n instanceof TableNode),
|
|
443
|
+
format: caretRange.end.node instanceof TextNode ||
|
|
444
|
+
caretRange.end.node instanceof AtomNode
|
|
445
|
+
? caretRange.end.node.getFormatRoot(editedNode)
|
|
446
|
+
: undefined,
|
|
386
447
|
startIsText: caretRange.start.node instanceof TextNode,
|
|
387
448
|
endIsText: caretRange.end.node instanceof TextNode,
|
|
388
|
-
startIsTextOrAtom: caretRange.start.node instanceof TextNode ||
|
|
389
|
-
|
|
449
|
+
startIsTextOrAtom: caretRange.start.node instanceof TextNode ||
|
|
450
|
+
caretRange.start.node instanceof AtomNode ||
|
|
451
|
+
caretRange.start.node instanceof EmbedNode,
|
|
452
|
+
endIsTextOrAtom: caretRange.end.node instanceof TextNode ||
|
|
453
|
+
caretRange.end.node instanceof AtomNode ||
|
|
454
|
+
caretRange.start.node instanceof EmbedNode,
|
|
390
455
|
atParagraphStart: atParagraphStart(),
|
|
391
456
|
undoStack: undoStack,
|
|
392
457
|
undoPosition: undoPosition,
|
|
@@ -394,15 +459,18 @@ function getCaretContext() {
|
|
|
394
459
|
redo: redo,
|
|
395
460
|
clipboard: clipboard,
|
|
396
461
|
handleCopy: handleCopy,
|
|
397
|
-
handlePaste: handlePaste
|
|
462
|
+
handlePaste: handlePaste,
|
|
398
463
|
};
|
|
399
464
|
}
|
|
400
465
|
function getUtilities() {
|
|
401
466
|
return {
|
|
402
|
-
getCaretOnLine: getCaretOnLine
|
|
467
|
+
getCaretOnLine: getCaretOnLine,
|
|
403
468
|
};
|
|
404
469
|
}
|
|
405
|
-
function
|
|
470
|
+
function handlePress(event) {
|
|
471
|
+
handleKey(event, true);
|
|
472
|
+
}
|
|
473
|
+
function handleKey(event, press = false) {
|
|
406
474
|
// Only handle keystrokes when this is focused.
|
|
407
475
|
// Otherwise, we let any focusable elements in this editor handle them.
|
|
408
476
|
if (!editorFocused)
|
|
@@ -417,35 +485,51 @@ function handleKeyDown(event) {
|
|
|
417
485
|
if (context === undefined)
|
|
418
486
|
return;
|
|
419
487
|
// Loop through the commands to see if there's a match.
|
|
420
|
-
const unmatched = commands.every(command => {
|
|
488
|
+
const unmatched = commands.every((command) => {
|
|
421
489
|
// If the keystroke and caret position matches the command signature, execute the command and update the caret range.
|
|
422
|
-
if ((command.
|
|
423
|
-
command.
|
|
424
|
-
|
|
425
|
-
(command.
|
|
490
|
+
if ((command.press === undefined || command.press === press) &&
|
|
491
|
+
(command.shift === undefined ||
|
|
492
|
+
command.shift === event.shiftKey) &&
|
|
493
|
+
(command.alt === undefined || command.alt === event.altKey) &&
|
|
494
|
+
(command.control === undefined ||
|
|
495
|
+
command.control === (event.ctrlKey || event.metaKey)) &&
|
|
496
|
+
(command.key === undefined ||
|
|
497
|
+
(Array.isArray(command.key) &&
|
|
498
|
+
command.key.includes(event.key)) ||
|
|
499
|
+
(command.key instanceof Function &&
|
|
500
|
+
command.key(event.key)) ||
|
|
501
|
+
command.key === event.key) &&
|
|
426
502
|
(command.code === undefined || command.code === event.code) &&
|
|
427
|
-
(command.active === true ||
|
|
428
|
-
|
|
429
|
-
|
|
503
|
+
(command.active === true ||
|
|
504
|
+
(command.active instanceof Function &&
|
|
505
|
+
command.active.call(undefined, context, event.key)))) {
|
|
430
506
|
// Execute the command
|
|
431
|
-
executeCommand(command, event.key);
|
|
507
|
+
const handled = executeCommand(command, event.key);
|
|
508
|
+
if (handled) {
|
|
509
|
+
event.preventDefault();
|
|
510
|
+
event.stopPropagation();
|
|
511
|
+
}
|
|
432
512
|
// Stop searching for a matching command.
|
|
433
|
-
return
|
|
513
|
+
return handled;
|
|
434
514
|
}
|
|
435
515
|
// Continue searching for a matching command.
|
|
436
516
|
return true;
|
|
437
517
|
});
|
|
438
518
|
if (unmatched) {
|
|
439
519
|
// Toolbar navigation
|
|
440
|
-
if (event.key ===
|
|
441
|
-
// If we've selected a FootnoteNode or Comment, navigate to the footnote or comment text.
|
|
442
|
-
if (caretRange.start.node instanceof AtomNode &&
|
|
443
|
-
|
|
520
|
+
if (event.key === 'Escape') {
|
|
521
|
+
// If we've selected a FootnoteNode or Comment, navigate to the footnote or comment text to edit it.
|
|
522
|
+
if (caretRange.start.node instanceof AtomNode &&
|
|
523
|
+
caretRange.start.node.getMeta() instanceof FormatNode) {
|
|
524
|
+
const firstCaret = caretRange.start.node
|
|
525
|
+
.getMeta()
|
|
526
|
+
.getFirstCaret();
|
|
444
527
|
caretRange = { start: firstCaret, end: firstCaret };
|
|
445
528
|
event.preventDefault();
|
|
446
529
|
event.stopPropagation();
|
|
447
530
|
return true;
|
|
448
531
|
}
|
|
532
|
+
// If we're inside an atom node, select the atom itself.
|
|
449
533
|
else if (caretRange.start.node.isInside(editedNode, AtomNode)) {
|
|
450
534
|
const atom = caretRange.start.node.getClosestParentOfType(editedNode, AtomNode);
|
|
451
535
|
if (atom) {
|
|
@@ -456,19 +540,19 @@ function handleKeyDown(event) {
|
|
|
456
540
|
return true;
|
|
457
541
|
}
|
|
458
542
|
}
|
|
459
|
-
if
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
543
|
+
// Otherwise, if we have a reference to this editor's DOM element, find the nearest focusable element in it's toolbar and focus on that.
|
|
544
|
+
const controls = [
|
|
545
|
+
document.querySelector('.bookish-editor-toolbar [tabindex="0"]'),
|
|
546
|
+
document.querySelector('.bookish-editor-toolbar input'),
|
|
547
|
+
document.querySelector('.bookish-editor-toolbar select'),
|
|
548
|
+
document.querySelector('.bookish-editor-toolbar button'),
|
|
549
|
+
];
|
|
550
|
+
const match = controls.find((control) => control && control instanceof HTMLElement);
|
|
551
|
+
if (match && match instanceof HTMLElement) {
|
|
552
|
+
match.focus();
|
|
553
|
+
event.preventDefault();
|
|
554
|
+
event.stopPropagation();
|
|
555
|
+
return true;
|
|
472
556
|
}
|
|
473
557
|
}
|
|
474
558
|
}
|
|
@@ -483,20 +567,29 @@ function executeCommand(command, key) {
|
|
|
483
567
|
if (results !== undefined) {
|
|
484
568
|
const { root, range } = results;
|
|
485
569
|
const newRange = { start: range.start, end: range.end };
|
|
486
|
-
if (root === editedNode && command.
|
|
570
|
+
if (root === editedNode && command.mutates)
|
|
487
571
|
console.error(`Warning: immutability violation on ${command.description}`);
|
|
488
572
|
// Set the range to force a rerender, assuming something in the document changed.
|
|
489
573
|
caretRange = newRange;
|
|
490
574
|
// Save the copy in the undo stack if this isn't a navigation or selection state.
|
|
491
|
-
if (command.category !==
|
|
575
|
+
if (command.category !== 'navigation' &&
|
|
576
|
+
command.category !== 'selection' &&
|
|
577
|
+
command.category !== 'history') {
|
|
492
578
|
saveEdit(root, newRange, command);
|
|
493
579
|
}
|
|
580
|
+
return true;
|
|
494
581
|
}
|
|
495
|
-
else
|
|
582
|
+
else {
|
|
496
583
|
ignoredInput = true;
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
497
586
|
}
|
|
587
|
+
return false;
|
|
498
588
|
}
|
|
499
|
-
function saveEdit(newRoot, newRange, command) {
|
|
589
|
+
async function saveEdit(newRoot, newRange, command) {
|
|
590
|
+
// Don't save edits if locked.
|
|
591
|
+
if (locked)
|
|
592
|
+
return;
|
|
500
593
|
// Call the save callback.
|
|
501
594
|
save(newRoot);
|
|
502
595
|
// Initialize a new history if we don't have one.
|
|
@@ -505,25 +598,39 @@ function saveEdit(newRoot, newRange, command) {
|
|
|
505
598
|
if (undoStack.length === 0 && caretRange !== undefined) {
|
|
506
599
|
const currentRange = caretRangeToIndexRange(editedNode, caretRange);
|
|
507
600
|
if (currentRange !== undefined)
|
|
508
|
-
newStack = [
|
|
601
|
+
newStack = [
|
|
602
|
+
{
|
|
509
603
|
bookdown: editedNode.toBookdown(),
|
|
510
604
|
command: undefined,
|
|
511
|
-
range: currentRange
|
|
512
|
-
}
|
|
605
|
+
range: currentRange,
|
|
606
|
+
},
|
|
607
|
+
];
|
|
513
608
|
}
|
|
514
609
|
// Change the chapter's AST.
|
|
515
|
-
|
|
610
|
+
updateRoot(newRoot);
|
|
516
611
|
// Set the new undo stack, pre-pending the new command to the front.
|
|
517
612
|
const newTextRange = caretRangeToIndexRange(newRoot, newRange);
|
|
518
613
|
if (newTextRange !== undefined)
|
|
519
|
-
undoStack = [
|
|
614
|
+
undoStack = [
|
|
615
|
+
{
|
|
520
616
|
bookdown: newRoot.toBookdown(),
|
|
521
617
|
command: command,
|
|
522
|
-
range: newTextRange
|
|
618
|
+
range: newTextRange,
|
|
523
619
|
// If the undo position is beyond the front, clear everything before it, because we're changing history.
|
|
524
|
-
},
|
|
620
|
+
},
|
|
621
|
+
...(undoPosition > 0 ? newStack.slice(undoPosition) : newStack),
|
|
622
|
+
];
|
|
525
623
|
// Set the undo position to the last index.
|
|
526
624
|
undoPosition = 0;
|
|
625
|
+
// Focus the editor on the new caret location, unless the toolbar is focused.
|
|
626
|
+
if (!toolbarIsFocused())
|
|
627
|
+
element?.focus();
|
|
628
|
+
// Update the caret
|
|
629
|
+
claimActiveEditor();
|
|
630
|
+
}
|
|
631
|
+
function updateRoot(newRoot) {
|
|
632
|
+
editedNode = newRoot;
|
|
633
|
+
text = editedNode.toBookdown();
|
|
527
634
|
}
|
|
528
635
|
function editNode(previous, edited) {
|
|
529
636
|
if (caretRange) {
|
|
@@ -533,8 +640,12 @@ function editNode(previous, edited) {
|
|
|
533
640
|
saveEdit(newRoot, { start: caretRange.start, end: caretRange.end });
|
|
534
641
|
// Update the range if the current range contains the previous node. This will generally
|
|
535
642
|
// be true any time a selected atom node is edited.
|
|
536
|
-
if (caretRange.start.node === previous &&
|
|
537
|
-
|
|
643
|
+
if (caretRange.start.node === previous &&
|
|
644
|
+
(edited instanceof AtomNode || edited instanceof TextNode))
|
|
645
|
+
caretRange = {
|
|
646
|
+
start: { node: edited, index: 0 },
|
|
647
|
+
end: { node: edited, index: 0 },
|
|
648
|
+
};
|
|
538
649
|
}
|
|
539
650
|
}
|
|
540
651
|
function handleMouseDown() {
|
|
@@ -546,20 +657,25 @@ function handleMouseDown() {
|
|
|
546
657
|
if (caretRange)
|
|
547
658
|
caretRange = { start: caretRange.start, end: caretRange.end };
|
|
548
659
|
// If we've selected a non-TextNode, release it, so the browser is free to select a text node.
|
|
549
|
-
if (caretRange &&
|
|
660
|
+
if (caretRange &&
|
|
661
|
+
!(caretRange.start.node instanceof TextNode ||
|
|
662
|
+
caretRange.start.node instanceof AtomNode ||
|
|
663
|
+
caretRange.start.node instanceof EmbedNode)) {
|
|
550
664
|
caretRange = undefined;
|
|
551
665
|
}
|
|
552
666
|
}
|
|
553
|
-
function
|
|
554
|
-
|
|
667
|
+
function isFocused() {
|
|
668
|
+
return (document.activeElement === element ||
|
|
669
|
+
(element !== null && element?.contains(document.activeElement)) ||
|
|
670
|
+
toolbarIsFocused());
|
|
555
671
|
}
|
|
556
|
-
function
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
}
|
|
672
|
+
function handleFocus() {
|
|
673
|
+
editorFocused = isFocused();
|
|
674
|
+
lease(true);
|
|
560
675
|
}
|
|
561
|
-
function
|
|
562
|
-
editorFocused =
|
|
676
|
+
function handleBlur() {
|
|
677
|
+
editorFocused = isFocused();
|
|
678
|
+
lease(false);
|
|
563
679
|
}
|
|
564
680
|
function handleCopy(node) {
|
|
565
681
|
// Set the editor's clipboard.
|
|
@@ -568,15 +684,30 @@ function handleCopy(node) {
|
|
|
568
684
|
if (navigator.clipboard) {
|
|
569
685
|
navigator.clipboard.write([
|
|
570
686
|
new ClipboardItem({
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
687
|
+
'text/plain': new Blob([node.toText()], {
|
|
688
|
+
type: 'text/plain',
|
|
689
|
+
}),
|
|
690
|
+
'text/html': new Blob([node.toHTML()], {
|
|
691
|
+
type: 'text/html',
|
|
692
|
+
}),
|
|
693
|
+
}),
|
|
574
694
|
]);
|
|
575
695
|
}
|
|
576
696
|
else
|
|
577
697
|
window.alert("Your browser doesn't support copying to the clipboard :(");
|
|
578
698
|
}
|
|
579
|
-
function handlePaste(context,
|
|
699
|
+
function handlePaste(context, text, save) {
|
|
700
|
+
if (text instanceof BookishNode)
|
|
701
|
+
return handlePasteNode(context, text, save);
|
|
702
|
+
const plain = text.plain === undefined ? undefined : new TextNode(text.plain);
|
|
703
|
+
if (plain) {
|
|
704
|
+
const edit = handlePasteNode(context, plain, save);
|
|
705
|
+
if (edit)
|
|
706
|
+
return edit;
|
|
707
|
+
}
|
|
708
|
+
return undefined;
|
|
709
|
+
}
|
|
710
|
+
function handlePasteNode(context, node, save) {
|
|
580
711
|
// Track revisions in these two variables.
|
|
581
712
|
let newRoot = context.root;
|
|
582
713
|
let newCaret = context.start;
|
|
@@ -619,110 +750,113 @@ function handlePaste(context, node, save) {
|
|
|
619
750
|
return { root: newChapter, range: edit.range };
|
|
620
751
|
}
|
|
621
752
|
}
|
|
753
|
+
function toolbarIsFocused() {
|
|
754
|
+
const toolbar = document.querySelector('.bookish-editor-toolbar');
|
|
755
|
+
return toolbar !== null && toolbar.contains(document.activeElement);
|
|
756
|
+
}
|
|
622
757
|
$: isAtom = caretRange && caretRange.start.node instanceof AtomNode;
|
|
623
|
-
$: inAtom =
|
|
624
|
-
|
|
625
|
-
$:
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
758
|
+
$: inAtom =
|
|
759
|
+
caretRange && caretRange.start.node.isInside(editedNode, AtomNode);
|
|
760
|
+
$: isSelection =
|
|
761
|
+
caretRange !== undefined &&
|
|
762
|
+
(caretRange.start.node !== caretRange.end.node ||
|
|
763
|
+
caretRange.start.index !== caretRange.end.index);
|
|
764
|
+
$: isItalic =
|
|
765
|
+
caretRange !== undefined &&
|
|
766
|
+
isSelection === false &&
|
|
767
|
+
caretRange.start.node instanceof TextNode &&
|
|
768
|
+
caretRange.start.node.isItalic(editedNode);
|
|
769
|
+
$: isBold =
|
|
770
|
+
caretRange !== undefined &&
|
|
771
|
+
isSelection === false &&
|
|
772
|
+
caretRange.start.node instanceof TextNode &&
|
|
773
|
+
caretRange.start.node.isBold(editedNode);
|
|
774
|
+
$: isLink =
|
|
775
|
+
caretRange !== undefined &&
|
|
776
|
+
isSelection === false &&
|
|
777
|
+
caretRange.start.node.getClosestParentMatching(editedNode, (p) => p instanceof LinkNode) !== undefined;
|
|
778
|
+
// When the caret context or editor focus changes, update the active editor.
|
|
629
779
|
$: {
|
|
630
|
-
caretRange
|
|
631
|
-
|
|
632
|
-
|
|
780
|
+
if ((caretRange || editorFocused) && isFocused())
|
|
781
|
+
claimActiveEditor();
|
|
782
|
+
else
|
|
783
|
+
activeEditor.set(undefined);
|
|
633
784
|
}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
785
|
+
function claimActiveEditor() {
|
|
786
|
+
activeEditor.set({
|
|
787
|
+
range: caretRange,
|
|
788
|
+
coordinate: caretCoordinate,
|
|
789
|
+
setCaret: (range) => {
|
|
790
|
+
caretRange = range;
|
|
791
|
+
element?.focus();
|
|
792
|
+
},
|
|
793
|
+
edit: editNode,
|
|
794
|
+
executor: executeCommand,
|
|
795
|
+
context: getCaretContext(),
|
|
796
|
+
root: editedNode,
|
|
797
|
+
focused: editorFocused,
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
// Pass the function above to all children so they can claim the active editor for non-focus reasons.
|
|
801
|
+
// (Drag and drop, for example.)
|
|
802
|
+
setContext('claimeditor', claimActiveEditor);
|
|
647
803
|
</script>
|
|
648
804
|
|
|
649
|
-
<div
|
|
650
|
-
class={`bookish-editor ${inAtom ?
|
|
805
|
+
<div
|
|
806
|
+
class={`bookish-editor ${inAtom ? 'bookish-editor-atom-focused' : ''}`}
|
|
807
|
+
class:locked
|
|
808
|
+
aria-disabled={locked}
|
|
651
809
|
bind:this={element}
|
|
652
|
-
on:keydown={
|
|
653
|
-
on:
|
|
810
|
+
on:keydown={handleKey}
|
|
811
|
+
on:keypress={handlePress}
|
|
654
812
|
on:mousedown|stopPropagation={handleMouseDown}
|
|
655
|
-
on:focus={
|
|
656
|
-
on:blur={
|
|
657
|
-
|
|
658
|
-
tabIndex=0
|
|
813
|
+
on:focus={handleFocus}
|
|
814
|
+
on:blur={handleBlur}
|
|
815
|
+
tabIndex="0"
|
|
659
816
|
>
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
817
|
+
<!-- A view of the root -->
|
|
818
|
+
<svelte:component
|
|
819
|
+
this={component}
|
|
820
|
+
node={editedNode}
|
|
821
|
+
{placeholder}
|
|
822
|
+
editable={true}
|
|
823
|
+
/>
|
|
824
|
+
<!-- The caret. We render our own since this view isn't contentEditable and we can't show a caret.
|
|
664
825
|
Customize the rendering based on the formatting applied to the text node. -->
|
|
665
|
-
{#if caretCoordinate && caretRange && !isAtom &&
|
|
666
|
-
<
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
826
|
+
{#if caretCoordinate && caretRange && !isAtom && isSelection === false && editorFocused}
|
|
827
|
+
<CaretView
|
|
828
|
+
left={caretCoordinate.x}
|
|
829
|
+
top={caretCoordinate.y}
|
|
830
|
+
height={caretCoordinate.height}
|
|
831
|
+
blink={editorFocused && keyboardIdle}
|
|
832
|
+
ignored={ignoredInput}
|
|
833
|
+
linked={isLink}
|
|
834
|
+
bold={isBold}
|
|
835
|
+
italic={isItalic}
|
|
836
|
+
disabled={!editorFocused || locked}
|
|
837
|
+
{locked}
|
|
838
|
+
/>
|
|
670
839
|
{/if}
|
|
671
|
-
<svelte:component this={component} node={editedNode} placeholder={placeholder} />
|
|
672
840
|
</div>
|
|
673
841
|
|
|
674
842
|
<style>
|
|
675
|
-
.bookish-editor
|
|
676
|
-
|
|
677
|
-
outline-offset: var(--bookish-app-chrome-padding);
|
|
678
|
-
border-radius: var(--bookish-app-chrome-roundedness);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
.bookish-editor.bookish-editor-atom-focused:focus {
|
|
682
|
-
outline: none;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
.bookish-editor-caret {
|
|
686
|
-
left: 0;
|
|
687
|
-
top: 0;
|
|
688
|
-
width: 0px;
|
|
689
|
-
background: none;
|
|
690
|
-
outline: 1px solid var(--bookish-paragraph-color);
|
|
691
|
-
display: inline-block;
|
|
692
|
-
box-sizing: border-box;
|
|
693
|
-
position: absolute;
|
|
694
|
-
z-index: 1;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
@keyframes bookish-editor-caret-blink {
|
|
698
|
-
100% {
|
|
699
|
-
outline: none;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
.bookish-editor-caret-disabled {
|
|
704
|
-
outline-color: var(--bookish-app-chrome-muted);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
.bookish-editor-caret-blink {
|
|
708
|
-
animation: bookish-editor-caret-blink 1s steps(2) infinite;
|
|
843
|
+
.bookish-editor {
|
|
844
|
+
min-height: 1em;
|
|
709
845
|
}
|
|
710
846
|
|
|
711
|
-
.bookish-
|
|
712
|
-
|
|
847
|
+
.locked :global(.bookish-text) {
|
|
848
|
+
color: var(--app-muted-color);
|
|
713
849
|
}
|
|
714
850
|
|
|
715
|
-
.bookish-editor
|
|
716
|
-
outline
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
animation: failure 100ms 10;
|
|
851
|
+
.bookish-editor:focus {
|
|
852
|
+
outline: var(--app-chrome-border-size) solid
|
|
853
|
+
var(--app-interactive-color);
|
|
854
|
+
outline-offset: var(--app-chrome-padding);
|
|
855
|
+
border-radius: var(--app-chrome-roundedness);
|
|
721
856
|
}
|
|
722
857
|
|
|
723
|
-
.bookish-editor-
|
|
724
|
-
outline
|
|
725
|
-
outline-color: var(--bookish-link-color);
|
|
858
|
+
.bookish-editor.bookish-editor-atom-focused:focus {
|
|
859
|
+
outline: none;
|
|
726
860
|
}
|
|
727
861
|
|
|
728
862
|
.bookish-editor-inline-editor {
|
|
@@ -743,13 +877,8 @@ $: caretStore.set({
|
|
|
743
877
|
font-weight: bold;
|
|
744
878
|
}
|
|
745
879
|
|
|
746
|
-
:global(.bookish-editor .bookish-table table td) {
|
|
747
|
-
border: var(--bookish-app-chrome-border-width) dashed var(--bookish-app-chrome-border-color);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
880
|
.bookish-editor :global(hr) {
|
|
751
881
|
margin-top: 1em;
|
|
752
|
-
margin-bottom: 1em;
|
|
882
|
+
margin-bottom: 1em;
|
|
753
883
|
}
|
|
754
|
-
|
|
755
|
-
</style>
|
|
884
|
+
</style>
|