edytor 0.1.0-next.34 → 0.1.0-next.38
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 +9 -4
- package/dist/block/block.svelte.d.ts +20 -10
- package/dist/block/block.svelte.js +68 -12
- package/dist/block/block.utils.d.ts +69 -0
- package/dist/block/colors.d.ts +62 -0
- package/dist/block/colors.js +106 -0
- package/dist/block/inlineBlock.svelte.d.ts +2 -1
- package/dist/block/inlineBlock.svelte.js +6 -4
- package/dist/clipboard/createClipboardFragment.js +34 -1
- package/dist/clipboard/htmlFlow.d.ts +5 -3
- package/dist/clipboard/htmlFlow.js +32 -7
- package/dist/clipboard/moveText.d.ts +35 -0
- package/dist/clipboard/moveText.js +79 -0
- package/dist/clipboard/serializeClipboardFragment.js +20 -4
- package/dist/cloudflare/DocumentRoom.d.ts +79 -512
- package/dist/cloudflare/DocumentRoom.js +158 -3725
- package/dist/cloudflare/index.d.ts +3 -2
- package/dist/cloudflare/index.js +3 -2
- package/dist/cloudflare/room/access.d.ts +31 -0
- package/dist/cloudflare/room/access.js +237 -0
- package/dist/cloudflare/room/admission.d.ts +124 -0
- package/dist/cloudflare/room/admission.js +588 -0
- package/dist/cloudflare/room/comments.d.ts +58 -0
- package/dist/cloudflare/room/comments.js +293 -0
- package/dist/cloudflare/room/context.d.ts +827 -0
- package/dist/cloudflare/room/context.js +298 -0
- package/dist/cloudflare/room/forged.d.ts +50 -0
- package/dist/cloudflare/room/forged.js +250 -0
- package/dist/cloudflare/room/frames.d.ts +31 -0
- package/dist/cloudflare/room/frames.js +53 -0
- package/dist/cloudflare/room/history.d.ts +100 -0
- package/dist/cloudflare/room/history.js +500 -0
- package/dist/cloudflare/room/moves.d.ts +60 -0
- package/dist/cloudflare/room/moves.js +422 -0
- package/dist/cloudflare/room/presence.d.ts +94 -0
- package/dist/cloudflare/room/presence.js +292 -0
- package/dist/cloudflare/room/purge.d.ts +16 -0
- package/dist/cloudflare/room/purge.js +123 -0
- package/dist/cloudflare/room/replicas.d.ts +51 -0
- package/dist/cloudflare/room/replicas.js +146 -0
- package/dist/cloudflare/room/scheduler.d.ts +39 -0
- package/dist/cloudflare/room/scheduler.js +122 -0
- package/dist/cloudflare/room/storage.d.ts +164 -0
- package/dist/cloudflare/room/storage.js +787 -0
- package/dist/cloudflare/room/updates.d.ts +89 -0
- package/dist/cloudflare/room/updates.js +327 -0
- package/dist/cloudflare/room/validation.d.ts +61 -0
- package/dist/cloudflare/room/validation.js +228 -0
- package/dist/cloudflare/routeDocumentSocket.d.ts +20 -0
- package/dist/cloudflare/routeDocumentSocket.js +46 -1
- package/dist/collaboration/comments/client.d.ts +96 -0
- package/dist/collaboration/comments/client.js +133 -0
- package/dist/collaboration/comments/index.d.ts +8 -0
- package/dist/collaboration/comments/index.js +7 -0
- package/dist/collaboration/comments/threads.d.ts +27 -0
- package/dist/collaboration/comments/threads.js +62 -0
- package/dist/collaboration/history/HistoryPanel.svelte +525 -0
- package/dist/collaboration/history/HistoryPanel.svelte.d.ts +7 -0
- package/dist/collaboration/history/VersionHighlights.svelte +103 -0
- package/dist/collaboration/history/VersionHighlights.svelte.d.ts +9 -0
- package/dist/collaboration/history/client.d.ts +75 -0
- package/dist/collaboration/history/client.js +50 -0
- package/dist/collaboration/history/diff.d.ts +42 -0
- package/dist/collaboration/history/diff.js +99 -0
- package/dist/collaboration/history/index.d.ts +9 -0
- package/dist/collaboration/history/index.js +9 -0
- package/dist/collaboration/history/panel.d.ts +43 -0
- package/dist/collaboration/history/panel.js +3 -0
- package/dist/collaboration/history/versionHighlights.d.ts +9 -0
- package/dist/collaboration/history/versionHighlights.js +17 -0
- package/dist/components/Block.svelte +65 -1
- package/dist/components/Edytor.svelte +22 -4
- package/dist/components/Edytor.svelte.d.ts +13 -1
- package/dist/components/Suggestion.svelte +1 -1
- package/dist/crdt/admission.js +4 -2
- package/dist/crdt/attribution/block.js +4 -3
- package/dist/crdt/doc/anchors.d.ts +17 -0
- package/dist/crdt/doc/anchors.js +83 -0
- package/dist/crdt/doc/capability.d.ts +56 -0
- package/dist/crdt/doc/capability.js +211 -0
- package/dist/crdt/doc/content.d.ts +12 -0
- package/dist/crdt/doc/content.js +75 -0
- package/dist/crdt/doc/delete.d.ts +14 -0
- package/dist/crdt/doc/delete.js +101 -0
- package/dist/crdt/doc/events.d.ts +9 -0
- package/dist/crdt/doc/events.js +63 -0
- package/dist/crdt/doc/funnel.d.ts +50 -0
- package/dist/crdt/doc/funnel.js +227 -0
- package/dist/crdt/doc/gate.d.ts +106 -0
- package/dist/crdt/doc/gate.js +118 -0
- package/dist/crdt/doc/history.d.ts +27 -0
- package/dist/crdt/doc/history.js +207 -0
- package/dist/crdt/doc/layout.d.ts +10 -0
- package/dist/crdt/doc/layout.js +190 -0
- package/dist/crdt/doc/meta.d.ts +19 -0
- package/dist/crdt/doc/meta.js +215 -0
- package/dist/crdt/doc/moves.d.ts +21 -0
- package/dist/crdt/doc/moves.js +254 -0
- package/dist/crdt/doc/plan.d.ts +28 -0
- package/dist/crdt/doc/plan.js +77 -0
- package/dist/crdt/doc/reads.d.ts +79 -0
- package/dist/crdt/doc/reads.js +351 -0
- package/dist/crdt/doc/seed.d.ts +38 -0
- package/dist/crdt/doc/seed.js +109 -0
- package/dist/crdt/doc/split-merge.d.ts +12 -0
- package/dist/crdt/doc/split-merge.js +183 -0
- package/dist/crdt/doc/steps.d.ts +57 -0
- package/dist/crdt/doc/steps.js +370 -0
- package/dist/crdt/doc/table.d.ts +21 -0
- package/dist/crdt/doc/table.js +288 -0
- package/dist/crdt/doc/types.d.ts +312 -0
- package/dist/crdt/doc/types.js +1 -0
- package/dist/crdt/document.js +15 -11
- package/dist/crdt/edytor-doc.d.ts +67 -506
- package/dist/crdt/edytor-doc.js +116 -2461
- package/dist/crdt/engine-api.d.ts +6 -0
- package/dist/crdt/flow.d.ts +6 -0
- package/dist/crdt/flow.js +20 -3
- package/dist/crdt/incarnations.d.ts +16 -3
- package/dist/crdt/incarnations.js +17 -3
- package/dist/crdt/index.d.ts +39 -13
- package/dist/crdt/index.js +5 -3
- package/dist/crdt/migration/generation.js +5 -3
- package/dist/crdt/migration/legacy-schema.js +5 -3
- package/dist/crdt/migration/migrate.js +6 -4
- package/dist/crdt/placement/display.d.ts +106 -0
- package/dist/crdt/placement/display.js +347 -0
- package/dist/crdt/placement/model.d.ts +15 -169
- package/dist/crdt/placement/model.js +12 -566
- package/dist/crdt/placement/resolve.d.ts +38 -0
- package/dist/crdt/placement/resolve.js +169 -0
- package/dist/crdt/placement/source.d.ts +43 -0
- package/dist/crdt/placement/source.js +66 -0
- package/dist/crdt/protocol.d.ts +5 -3
- package/dist/crdt/protocol.js +5 -3
- package/dist/crdt/protocols/comments.d.ts +219 -0
- package/dist/crdt/protocols/comments.js +283 -0
- package/dist/crdt/protocols/sync.js +5 -4
- package/dist/crdt/providers/index.d.ts +1 -0
- package/dist/crdt/providers/index.js +3 -1
- package/dist/crdt/providers/indexeddb.js +15 -3
- package/dist/crdt/providers/room.d.ts +6 -0
- package/dist/crdt/providers/room.js +8 -1
- package/dist/crdt/providers/websocket.d.ts +2 -0
- package/dist/crdt/providers/websocket.js +58 -3
- package/dist/crdt/purge.d.ts +6 -0
- package/dist/crdt/purge.js +34 -4
- package/dist/crdt/rangeDelete.d.ts +9 -0
- package/dist/crdt/rangeDelete.js +40 -0
- package/dist/crdt/semantics.d.ts +96 -6
- package/dist/crdt/semantics.js +64 -9
- package/dist/crdt/structs.d.ts +118 -8
- package/dist/crdt/structs.js +108 -0
- package/dist/crdt/tables.d.ts +44 -0
- package/dist/crdt/tables.js +58 -0
- package/dist/crdt/text/delete-index.d.ts +142 -0
- package/dist/crdt/text/delete-index.js +372 -0
- package/dist/crdt/text/deletes.d.ts +49 -0
- package/dist/crdt/text/deletes.js +18 -398
- package/dist/crdt/text/index/anchored.d.ts +17 -0
- package/dist/crdt/text/index/anchored.js +197 -0
- package/dist/crdt/text/index/cache.d.ts +16 -0
- package/dist/crdt/text/index/cache.js +171 -0
- package/dist/crdt/text/index/checks.d.ts +15 -0
- package/dist/crdt/text/index/checks.js +156 -0
- package/dist/crdt/text/index/claims.d.ts +18 -0
- package/dist/crdt/text/index/claims.js +213 -0
- package/dist/crdt/text/index/fold.d.ts +23 -0
- package/dist/crdt/text/index/fold.js +501 -0
- package/dist/crdt/text/index/layout.d.ts +34 -0
- package/dist/crdt/text/index/layout.js +288 -0
- package/dist/crdt/text/index/placement.d.ts +39 -0
- package/dist/crdt/text/index/placement.js +475 -0
- package/dist/crdt/text/index/records.d.ts +13 -0
- package/dist/crdt/text/index/records.js +145 -0
- package/dist/crdt/text/index/report.d.ts +18 -0
- package/dist/crdt/text/index/report.js +338 -0
- package/dist/crdt/text/index/shared.d.ts +64 -0
- package/dist/crdt/text/index/shared.js +107 -0
- package/dist/crdt/text/index/state.d.ts +223 -0
- package/dist/crdt/text/index/state.js +120 -0
- package/dist/crdt/text/index/streams.d.ts +20 -0
- package/dist/crdt/text/index/streams.js +197 -0
- package/dist/crdt/text/items.d.ts +8 -0
- package/dist/crdt/text/items.js +3 -0
- package/dist/crdt/text/model.d.ts +9 -54
- package/dist/crdt/text/model.js +18 -246
- package/dist/crdt/text/ranges.d.ts +20 -0
- package/dist/crdt/text/ranges.js +82 -0
- package/dist/crdt/text/runs.d.ts +16 -16
- package/dist/crdt/text/runs.js +39 -2486
- package/dist/crdt/text/streams.d.ts +45 -0
- package/dist/crdt/text/streams.js +138 -0
- package/dist/crdt/vendor/yjs/UPSTREAM.md +38 -13
- package/dist/edytor.svelte.d.ts +18 -5
- package/dist/edytor.svelte.js +51 -16
- package/dist/events/beforeInputCommands.d.ts +0 -2
- package/dist/events/beforeInputCommands.js +26 -15
- package/dist/events/beforeInputDeleteCommands.js +8 -1
- package/dist/events/onDrop.d.ts +11 -0
- package/dist/events/onDrop.js +89 -3
- package/dist/events/onKeyDown.js +6 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +8 -1
- package/dist/kinds.d.ts +9 -0
- package/dist/kinds.js +11 -2
- package/dist/labels.d.ts +488 -0
- package/dist/labels.js +431 -0
- package/dist/plugins/blockHandles/BlockHandle.svelte +4 -7
- package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +4 -0
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +5 -0
- package/dist/plugins/blockHandles/blockHandlesPlugin.d.ts +3 -0
- package/dist/plugins/blockHandles/blockHandlesPlugin.js +5 -2
- package/dist/plugins/blockMenu/BlockMenu.svelte +129 -25
- package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +69 -12
- package/dist/plugins/blockMenu/BlockMenuController.svelte.js +155 -21
- package/dist/plugins/blockMenu/blockMenuPlugin.d.ts +4 -3
- package/dist/plugins/blockMenu/blockMenuPlugin.js +7 -4
- package/dist/plugins/code/CodeHeader.svelte +11 -8
- package/dist/plugins/code/CodePlugin.svelte +8 -3
- package/dist/plugins/code/languages.d.ts +16 -2
- package/dist/plugins/code/languages.js +5 -1
- package/dist/plugins/columns/ColumnResize.svelte +1 -1
- package/dist/plugins/columns/ColumnsPlugin.svelte +30 -9
- package/dist/plugins/columns/ColumnsPlugin.svelte.d.ts +8 -0
- package/dist/plugins/columns/resize.svelte.d.ts +6 -1
- package/dist/plugins/columns/resize.svelte.js +6 -1
- package/dist/plugins/comments/CommentsController.svelte.d.ts +124 -0
- package/dist/plugins/comments/CommentsController.svelte.js +351 -0
- package/dist/plugins/comments/CommentsSidebar.svelte +601 -0
- package/dist/plugins/comments/CommentsSidebar.svelte.d.ts +16 -0
- package/dist/plugins/comments/commentsPlugin.d.ts +48 -0
- package/dist/plugins/comments/commentsPlugin.js +60 -0
- package/dist/plugins/equation/EquationEditor.svelte +138 -0
- package/dist/plugins/equation/EquationEditor.svelte.d.ts +8 -0
- package/dist/plugins/equation/EquationPlugin.svelte +328 -0
- package/dist/plugins/equation/EquationPlugin.svelte.d.ts +33 -0
- package/dist/plugins/equation/EquationView.svelte +34 -0
- package/dist/plugins/equation/EquationView.svelte.d.ts +7 -0
- package/dist/plugins/equation/equation.svelte.d.ts +142 -0
- package/dist/plugins/equation/equation.svelte.js +295 -0
- package/dist/plugins/find/FindBar.svelte +17 -16
- package/dist/plugins/find/FindController.svelte.d.ts +6 -1
- package/dist/plugins/find/FindController.svelte.js +6 -1
- package/dist/plugins/find/findPlugin.d.ts +3 -0
- package/dist/plugins/find/findPlugin.js +2 -1
- package/dist/plugins/icons.js +13 -0
- package/dist/plugins/image/ImageChrome.svelte +11 -10
- package/dist/plugins/image/ImageEmpty.svelte +19 -16
- package/dist/plugins/image/ImagePlugin.svelte +21 -4
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +8 -0
- package/dist/plugins/image/controls.svelte.d.ts +6 -1
- package/dist/plugins/image/controls.svelte.js +6 -1
- package/dist/plugins/image/image.d.ts +5 -0
- package/dist/plugins/image/image.js +3 -0
- package/dist/plugins/index.d.ts +12 -2
- package/dist/plugins/index.js +10 -1
- package/dist/plugins/markdownShortcuts.js +99 -67
- package/dist/plugins/media/AudioPlugin.svelte +11 -5
- package/dist/plugins/media/BookmarkPlugin.svelte +26 -14
- package/dist/plugins/media/BookmarkPlugin.svelte.d.ts +5 -0
- package/dist/plugins/media/EmbedPlugin.svelte +25 -12
- package/dist/plugins/media/EmbedPlugin.svelte.d.ts +5 -0
- package/dist/plugins/media/FilePlugin.svelte +15 -8
- package/dist/plugins/media/MediaEmpty.svelte +14 -13
- package/dist/plugins/media/MediaEmpty.svelte.d.ts +3 -8
- package/dist/plugins/media/UrlPasteMenu.svelte +1 -1
- package/dist/plugins/media/VideoPlugin.svelte +11 -5
- package/dist/plugins/media/media.d.ts +12 -2
- package/dist/plugins/media/media.js +12 -13
- package/dist/plugins/media/urlPaste.svelte.d.ts +7 -2
- package/dist/plugins/media/urlPaste.svelte.js +9 -5
- package/dist/plugins/mention/MentionPlugin.svelte +169 -31
- package/dist/plugins/mention/MentionPlugin.svelte.d.ts +35 -2
- package/dist/plugins/page/PageLink.svelte +129 -0
- package/dist/plugins/page/PageLink.svelte.d.ts +11 -0
- package/dist/plugins/page/PagePlugin.svelte +127 -0
- package/dist/plugins/page/PagePlugin.svelte.d.ts +44 -0
- package/dist/plugins/page/page.d.ts +58 -0
- package/dist/plugins/page/page.js +42 -0
- package/dist/plugins/pageLink/PageLinkPlugin.svelte +169 -0
- package/dist/plugins/pageLink/PageLinkPlugin.svelte.d.ts +58 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte +155 -63
- package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +23 -2
- package/dist/plugins/richtext/TodoCheckbox.svelte +35 -0
- package/dist/plugins/richtext/TodoCheckbox.svelte.d.ts +11 -0
- package/dist/plugins/richtext/labels.d.ts +5 -0
- package/dist/plugins/richtext/labels.js +3 -0
- package/dist/plugins/richtext/richTextOperations.d.ts +6 -1
- package/dist/plugins/richtext/richTextOperations.js +5 -0
- package/dist/plugins/slashMenu/SlashMenu.svelte +11 -7
- package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +25 -29
- package/dist/plugins/slashMenu/SlashMenuController.svelte.js +51 -146
- package/dist/plugins/slashMenu/slashMenuPlugin.d.ts +3 -0
- package/dist/plugins/slashMenu/slashMenuPlugin.js +7 -25
- package/dist/plugins/suggestions/SuggestionBars.svelte +13 -6
- package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +2 -0
- package/dist/plugins/suggestions/suggestionsPlugin.d.ts +3 -0
- package/dist/plugins/suggestions/suggestionsPlugin.js +3 -1
- package/dist/plugins/table/TableChrome.svelte +153 -0
- package/dist/plugins/table/TableChrome.svelte.d.ts +7 -0
- package/dist/plugins/table/TablePlugin.svelte +450 -0
- package/dist/plugins/table/TablePlugin.svelte.d.ts +43 -0
- package/dist/plugins/table/chrome.svelte.d.ts +153 -0
- package/dist/plugins/table/chrome.svelte.js +420 -0
- package/dist/plugins/table/table.css +202 -0
- package/dist/plugins/table/table.d.ts +94 -0
- package/dist/plugins/table/table.js +224 -0
- package/dist/plugins/toc/TableOfContents.svelte +83 -0
- package/dist/plugins/toc/TableOfContents.svelte.d.ts +7 -0
- package/dist/plugins/toc/TocPlugin.svelte +71 -0
- package/dist/plugins/toc/TocPlugin.svelte.d.ts +32 -0
- package/dist/plugins/toc/toc.d.ts +29 -0
- package/dist/plugins/toc/toc.js +10 -0
- package/dist/plugins/toolbar/LinkCard.svelte +8 -7
- package/dist/plugins/toolbar/Toolbar.svelte +21 -18
- package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +10 -2
- package/dist/plugins/toolbar/ToolbarController.svelte.js +12 -2
- package/dist/plugins/toolbar/toolbarPlugin.d.ts +3 -0
- package/dist/plugins/toolbar/toolbarPlugin.js +2 -1
- package/dist/plugins/triggers/TriggerController.svelte.d.ts +131 -0
- package/dist/plugins/triggers/TriggerController.svelte.js +333 -0
- package/dist/plugins/triggers/TriggerMenu.svelte +144 -0
- package/dist/plugins/triggers/TriggerMenu.svelte.d.ts +7 -0
- package/dist/plugins/triggers/place.d.ts +15 -0
- package/dist/plugins/triggers/place.js +37 -0
- package/dist/plugins/triggers/triggers.d.ts +12 -0
- package/dist/plugins/triggers/triggers.js +87 -0
- package/dist/plugins.d.ts +188 -4
- package/dist/selection/selection.svelte.d.ts +22 -0
- package/dist/selection/selection.svelte.js +29 -2
- package/dist/selection/selection.utils.d.ts +7 -5
- package/dist/selection/selection.utils.js +5 -14
- package/dist/session/announcer.svelte.d.ts +2 -1
- package/dist/session/announcer.svelte.js +15 -9
- package/dist/session/attempt.js +1 -1
- package/dist/session/bindings.js +2 -3
- package/dist/session/commands.d.ts +8 -2
- package/dist/session/commands.js +45 -7
- package/dist/session/composition.svelte.js +5 -9
- package/dist/session/editing/text.d.ts +7 -0
- package/dist/session/editing/text.js +17 -0
- package/dist/session/inputRules.d.ts +20 -0
- package/dist/session/inputRules.js +128 -0
- package/dist/session/navigation.js +1 -1
- package/dist/session/ports.d.ts +45 -0
- package/dist/session/ports.js +1 -0
- package/dist/surface/attributes.js +4 -0
- package/dist/surface/overlay.d.ts +15 -3
- package/dist/surface/overlay.js +30 -3
- package/dist/surface/projector.svelte.d.ts +15 -0
- package/dist/surface/projector.svelte.js +32 -2
- package/dist/text/text.svelte.d.ts +4 -2
- package/dist/text/text.svelte.js +9 -7
- package/dist/themes/notion.css +130 -14
- package/dist/utils.d.ts +1 -1
- package/package.json +12 -12
- /package/dist/{events → text}/wordBoundary.d.ts +0 -0
- /package/dist/{events → text}/wordBoundary.js +0 -0
package/README.md
CHANGED
|
@@ -10,19 +10,24 @@
|
|
|
10
10
|
<p>
|
|
11
11
|
<a href="https://edytor.dev/docs">Documentation</a> •
|
|
12
12
|
<a href="#quick-start">Quick start</a> •
|
|
13
|
-
<a href="https://edytor.dev/docs/reference/migration">
|
|
13
|
+
<a href="https://edytor.dev/docs/reference/migration">Changelog</a>
|
|
14
14
|
</p>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
Edytor aims to be for Svelte what Slate.js is for React: a heavily customizable editor with an API to build any kind of collaborative rich text editor.
|
|
18
18
|
|
|
19
|
-
> **Work in progress.** Edytor is a pre-release (`0.1.0-next.
|
|
19
|
+
> **Work in progress.** Edytor is a pre-release (`0.1.0-next.38`, `edytor@next` on npm) and not ready for production; the API changes between releases without a compatibility layer. The untagged `edytor@0.0.11` on npm predates the current API. Issues and PRs are welcome: when you report a bug, include the document's JSON value.
|
|
20
20
|
|
|
21
21
|
## Features
|
|
22
22
|
|
|
23
|
-
- **Notion-style editing out of the box.** `<Edytor />` alone is a rich text editor with images and block handles: headings, lists, to-dos, toggles, callouts, quotes, dividers, ten marks and Notion's hotkeys. Add the Notion theme, a block menu (drag one block, or every block the selection covers), a slash menu, a selection toolbar, markdown shortcuts (`markdownShortcutsPlugin`) and code blocks.
|
|
23
|
+
- **Notion-style editing out of the box.** `<Edytor />` alone is a rich text editor with images and block handles: headings, toggle headings, lists, to-dos, toggles, callouts, quotes, dividers, ten marks and Notion's hotkeys. Add the Notion theme, a block menu (block colours; drag one block, or every block the selection covers), a slash menu, a selection toolbar, markdown shortcuts (`markdownShortcutsPlugin`) and code blocks.
|
|
24
|
+
- **Pages and a table of contents, opt-in.** `createPagePlugin` links a block to another document (a page per room, opened and named by your app), and `tocPlugin` lists the headings live ([Page](https://edytor.dev/docs/plugins/page), [Table of contents](https://edytor.dev/docs/plugins/table-of-contents)).
|
|
24
25
|
- **Columns, opt-in.** List `columnsPlugin` for Notion's multi-column layouts: drag a block to the edge of another to put them side by side, or pick "2 columns" to "5 columns"; drag the gap to resize. Layouts converge across collaborators and the room ([Columns](https://edytor.dev/docs/plugins/columns)).
|
|
26
|
+
- **Tables, opt-in.** List `tablePlugin` for Notion's simple table: cells of text, <kbd>Tab</kbd> between them, rows and columns added, moved and deleted from the table's edges and grips, resizable columns, header row and column, HTML tables pasted and copied. Concurrent row and column edits converge on every replica ([Table](https://edytor.dev/docs/plugins/table)).
|
|
27
|
+
- **Mentions, page links and your own triggers.** `createMentionPlugin` (`@` people) and `createPageLinkPlugin` (`[[` pages) take your app's search; a plugin's `inputRules` (`:smile:` → 😄) and `triggers` (a menu on a typed character) declare the rest ([Input rules and triggers](https://edytor.dev/docs/plugins/input-rules)).
|
|
28
|
+
- **Comments, opt-in.** `createCommentsPlugin` adds Notion's comment threads: select text, press Comment, and the thread shows in a sidebar beside it with replies, Resolve and Re-open. The room keeps the threads beside the document and sends each change live; the anchor follows the text through edits and is not copied ([Comments](https://edytor.dev/docs/plugins/comments)).
|
|
25
29
|
- **Your markup.** Blocks, marks and inline atoms render through your Svelte snippets; the slash menu, toolbar, block menu and handles take a snippet and keep their behavior.
|
|
30
|
+
- **Your language.** Every word the chrome shows or says, slash keywords included, comes from a labels dictionary each plugin takes; English by default ([Localization](https://edytor.dev/docs/customization/localization)).
|
|
26
31
|
- **Synced properties.** `block.data`, `atom.data` and `edytor.data` read and write like plain objects (`bind:value={block.data.title}`); each property and each array item syncs on its own, so concurrent edits of different properties, or of different items of one array, merge.
|
|
27
32
|
- **AI suggestions.** `edytor.suggestions.add(position, content)` proposes text, paragraphs, lists, to-dos or images after, before or inside a block, at the end of its text, or in place of the selection; it streams in, shows only on your screen, and becomes one undo step when accepted ([Suggestions](https://edytor.dev/docs/editor/suggestions)).
|
|
28
33
|
- **Plugins that can veto anything.** Every command is prepared before it writes; plugins see the command and each planned step and can refuse or replace it.
|
|
@@ -99,7 +104,7 @@ The [documentation site](https://edytor.dev/docs) is the single source for the A
|
|
|
99
104
|
- [Editor](https://edytor.dev/docs/editor/edytor-component): the component, commands, selection, history, clipboard, readonly
|
|
100
105
|
- [Plugins](https://edytor.dev/docs/plugins) and [customization](https://edytor.dev/docs/customization/blocks): bundled plugins, custom blocks and marks, [hotkeys and editing behavior](https://edytor.dev/docs/customization/hotkeys)
|
|
101
106
|
- [Collaboration](https://edytor.dev/docs/collaboration) and [server](https://edytor.dev/docs/server/quick-start): documents, providers, presence, the Durable Object room and its protocol
|
|
102
|
-
- [Reference](https://edytor.dev/docs/reference/document-api): the document API, [troubleshooting](https://edytor.dev/docs/reference/troubleshooting), [migration from 0.0.11](https://edytor.dev/docs/reference/migration), limitations, [platform support](https://edytor.dev/docs/reference/platform-support)
|
|
107
|
+
- [Reference](https://edytor.dev/docs/reference/document-api): the document API, [troubleshooting](https://edytor.dev/docs/reference/troubleshooting), the [changelog](https://edytor.dev/docs/reference/migration) (with [migration from 0.0.11](https://edytor.dev/docs/reference/migration#upgrading-from-0011)), [importing v13 documents](https://edytor.dev/docs/reference/v13-import), limitations, [platform support](https://edytor.dev/docs/reference/platform-support)
|
|
103
108
|
|
|
104
109
|
## Contributing
|
|
105
110
|
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { Text } from '../text/text.svelte.js';
|
|
2
|
-
import { Edytor } from '../edytor.svelte.js';
|
|
2
|
+
import type { Edytor } from '../edytor.svelte.js';
|
|
3
3
|
import type { JSONBlock, JSONText, JSONInlineBlock } from '../utils/json.js';
|
|
4
4
|
import { type BlockOperations } from './block.utils.js';
|
|
5
5
|
import type { BlockDefinition } from '../plugins.js';
|
|
6
6
|
import { InlineBlock } from './inlineBlock.svelte.js';
|
|
7
7
|
import type { DocBlock } from '../crdt/index.js';
|
|
8
|
-
/**
|
|
9
|
-
* An id-only block handle (§2.4 "Handles", R4): every getter reads the
|
|
10
|
-
* document index (transaction-aware), every mutator issues a command. The
|
|
11
|
-
* view keeps one per id (`edytor.idToBlock`); `node` is the element the core
|
|
12
|
-
* renders for it (O45).
|
|
13
|
-
*/
|
|
14
8
|
/** Mark an element inside a block's markup as non-editable chrome (`block.void`, a preview's too). */
|
|
15
9
|
export declare const voidChrome: (node: HTMLElement) => void;
|
|
10
|
+
/**
|
|
11
|
+
* An id-only block handle: every getter reads the document index
|
|
12
|
+
* (transaction-aware), every mutator issues a command. The view keeps one per
|
|
13
|
+
* id (`edytor.idToBlock`); `node` is the element the core renders for it.
|
|
14
|
+
*
|
|
15
|
+
* A reactive reader (a template, a `$derived`, an `$effect`) of a getter
|
|
16
|
+
* depends on the cells the answer comes from (this block's, its parent's,
|
|
17
|
+
* the root's list), so it re-runs when a commit changes them, as `data`
|
|
18
|
+
* does; a read anywhere else is a plain read of the document.
|
|
19
|
+
*/
|
|
16
20
|
export declare class Block {
|
|
17
21
|
#private;
|
|
18
22
|
readonly: boolean;
|
|
@@ -160,10 +164,16 @@ export declare class Block {
|
|
|
160
164
|
ops: import("../crdt/index.js").DataPatch[];
|
|
161
165
|
atom?: string;
|
|
162
166
|
}) => void;
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Insert an inline atom: at `offset` of the block's content (block
|
|
169
|
+
* offsets, an inline atom counting 1; a caret's), or at `index` of the
|
|
170
|
+
* text segment `text`. One `addInlineBlock` operation (its payload names
|
|
171
|
+
* the segment). Answers the text segment right after the atom, where a
|
|
172
|
+
* caret goes (`null` when it was not written, `undefined` when refused).
|
|
173
|
+
*/
|
|
174
|
+
addInlineBlock: (payload: BlockOperations["addInlineBlock"] | {
|
|
175
|
+
offset: number;
|
|
165
176
|
block: JSONInlineBlock;
|
|
166
|
-
text: Text;
|
|
167
177
|
}) => Text | null | undefined;
|
|
168
178
|
normalizeContent: () => void;
|
|
169
179
|
normalizeChildren: () => void;
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { Text } from '../text/text.svelte.js';
|
|
2
|
-
import { Edytor } from '../edytor.svelte.js';
|
|
3
2
|
import { batch, removeInlineBlock, addChildBlock, insertBlockAfter, insertBlockBefore, mergeBlockBackward, mergeBlockForward, nestBlock, removeBlock, setBlock, splitBlock, prepareSplit, duplicateBlock, prepareDuplicate, prepareSet, prepareMove, prepareMoves, prepareInsertAfter, prepareInsertBefore, prepareRemove, prepareMergeBackward, prepareMergeForward, prepareUnNest, prepareNest, prepareRemoveInline, preparePatch, patchData, prepareDeleteRange, addChildBlocks, pushContentIntoBlock, unNestBlock, moveBlock, moveBlocks, normalizeContent, addInlineBlock, textAfterAtom, blockOf, acceptSuggestedText, suggestText, deleteContentAtRange, normalizeChildren } from './block.utils.js';
|
|
4
3
|
import { jsonBlockToSpec, jsonContentToItems } from '../utils/json.js';
|
|
5
4
|
import { InlineBlock } from './inlineBlock.svelte.js';
|
|
6
5
|
import { revealed } from '../selection/replaceSelection.js';
|
|
7
6
|
import { propsProxy } from '../session/props.js';
|
|
8
|
-
/**
|
|
9
|
-
* An id-only block handle (§2.4 "Handles", R4): every getter reads the
|
|
10
|
-
* document index (transaction-aware), every mutator issues a command. The
|
|
11
|
-
* view keeps one per id (`edytor.idToBlock`); `node` is the element the core
|
|
12
|
-
* renders for it (O45).
|
|
13
|
-
*/
|
|
14
7
|
/** Mark an element inside a block's markup as non-editable chrome (`block.void`, a preview's too). */
|
|
15
8
|
export const voidChrome = (node) => {
|
|
16
9
|
node.setAttribute('data-edytor-void', `true`);
|
|
17
10
|
node.style.userSelect = 'none';
|
|
18
11
|
node.setAttribute('contenteditable', 'false');
|
|
19
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* An id-only block handle: every getter reads the document index
|
|
15
|
+
* (transaction-aware), every mutator issues a command. The view keeps one per
|
|
16
|
+
* id (`edytor.idToBlock`); `node` is the element the core renders for it.
|
|
17
|
+
*
|
|
18
|
+
* A reactive reader (a template, a `$derived`, an `$effect`) of a getter
|
|
19
|
+
* depends on the cells the answer comes from (this block's, its parent's,
|
|
20
|
+
* the root's list), so it re-runs when a commit changes them, as `data`
|
|
21
|
+
* does; a read anywhere else is a plain read of the document.
|
|
22
|
+
*/
|
|
20
23
|
export class Block {
|
|
21
24
|
readonly = false;
|
|
22
25
|
edytor;
|
|
@@ -29,21 +32,43 @@ export class Block {
|
|
|
29
32
|
get isRoot() {
|
|
30
33
|
return this.id === 'root';
|
|
31
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Under a reactive reader, depend on block `id`'s cell (the root: its
|
|
37
|
+
* child list): the commit that patches it re-runs the reader. A cell
|
|
38
|
+
* that goes away (the block died) re-runs it too.
|
|
39
|
+
*/
|
|
40
|
+
#track(id = this.id) {
|
|
41
|
+
if (!$effect.tracking())
|
|
42
|
+
return;
|
|
43
|
+
const cells = this.edytor.cells;
|
|
44
|
+
if (id === 'root')
|
|
45
|
+
void cells?.rootIds;
|
|
46
|
+
else
|
|
47
|
+
cells?.get(id);
|
|
48
|
+
}
|
|
32
49
|
/** The typed document node — `null` for the root. */
|
|
33
50
|
get model() {
|
|
34
51
|
return this.isRoot ? null : this.edytor.facade.block(this.id);
|
|
35
52
|
}
|
|
36
53
|
/** The display parent (the root for a top-level block); none for the root or a dead block. */
|
|
37
54
|
get parent() {
|
|
38
|
-
|
|
55
|
+
if (this.isRoot)
|
|
56
|
+
return undefined;
|
|
57
|
+
this.#track();
|
|
58
|
+
const at = this.edytor.facade.positionOf(this.id);
|
|
59
|
+
// The parent's child list names this block: a move patches it.
|
|
60
|
+
if (at)
|
|
61
|
+
this.#track(at.parent ?? 'root');
|
|
39
62
|
return at ? this.edytor.idToBlock.block(at.parent ?? 'root') : undefined;
|
|
40
63
|
}
|
|
41
64
|
get children() {
|
|
65
|
+
this.#track();
|
|
42
66
|
const { facade, idToBlock } = this.edytor;
|
|
43
67
|
return facade.childrenIds(this.isRoot ? null : this.id).map(idToBlock.block);
|
|
44
68
|
}
|
|
45
69
|
/** Text segments and inline atoms, alternating, starting and ending with a text. */
|
|
46
70
|
get content() {
|
|
71
|
+
this.#track();
|
|
47
72
|
const handles = this.edytor.idToBlock;
|
|
48
73
|
let ordinal = 0;
|
|
49
74
|
return handles
|
|
@@ -53,7 +78,10 @@ export class Block {
|
|
|
53
78
|
: handles.atom(this.id, part.item.id));
|
|
54
79
|
}
|
|
55
80
|
get type() {
|
|
56
|
-
|
|
81
|
+
if (this.isRoot)
|
|
82
|
+
return 'root';
|
|
83
|
+
this.#track();
|
|
84
|
+
return this.edytor.facade.blockTypeOf(this.id) ?? '';
|
|
57
85
|
}
|
|
58
86
|
/** Retype the block — the `setBlock` command (readonly, hooks, `dispatcher.last`). */
|
|
59
87
|
set type(value) {
|
|
@@ -139,7 +167,13 @@ export class Block {
|
|
|
139
167
|
return undefined;
|
|
140
168
|
}
|
|
141
169
|
get index() {
|
|
142
|
-
|
|
170
|
+
if (this.isRoot)
|
|
171
|
+
return 0;
|
|
172
|
+
const at = this.edytor.facade.positionOf(this.id);
|
|
173
|
+
this.#track();
|
|
174
|
+
if (at)
|
|
175
|
+
this.#track(at.parent ?? 'root');
|
|
176
|
+
return at?.index || 0;
|
|
143
177
|
}
|
|
144
178
|
get depth() {
|
|
145
179
|
return this.parent ? this.parent.depth + 1 : 0;
|
|
@@ -155,7 +189,10 @@ export class Block {
|
|
|
155
189
|
}
|
|
156
190
|
/** The block is visible in the document (a dead handle answers false). */
|
|
157
191
|
get isInTree() {
|
|
158
|
-
|
|
192
|
+
if (this.isRoot)
|
|
193
|
+
return true;
|
|
194
|
+
this.#track();
|
|
195
|
+
return this.edytor.facade.isVisibleBlock(this.id);
|
|
159
196
|
}
|
|
160
197
|
/**
|
|
161
198
|
* @deprecated `edytor.suggestions` with `{ end: block.id }`. The content of
|
|
@@ -211,6 +248,9 @@ export class Block {
|
|
|
211
248
|
}
|
|
212
249
|
/** This block's JSON — the document's one serializer (`facade.blockJSON`). */
|
|
213
250
|
get value() {
|
|
251
|
+
// Its subtree's: every commit re-runs a reactive reader.
|
|
252
|
+
if ($effect.tracking())
|
|
253
|
+
void this.edytor.valueRevision;
|
|
214
254
|
if (!this.isRoot)
|
|
215
255
|
return this.edytor.facade.blockJSON(this.id);
|
|
216
256
|
const { data = {}, children } = this.edytor.facade.toJSON();
|
|
@@ -294,7 +334,20 @@ export class Block {
|
|
|
294
334
|
pushContentIntoBlock = batch('pushContentIntoBlock', pushContentIntoBlock);
|
|
295
335
|
removeInlineBlock = batch('removeInlineBlock', removeInlineBlock, prepareRemoveInline);
|
|
296
336
|
patchData = batch('patchData', patchData, preparePatch);
|
|
297
|
-
|
|
337
|
+
#addInline = batch('addInlineBlock', addInlineBlock, undefined, textAfterAtom);
|
|
338
|
+
/**
|
|
339
|
+
* Insert an inline atom: at `offset` of the block's content (block
|
|
340
|
+
* offsets, an inline atom counting 1; a caret's), or at `index` of the
|
|
341
|
+
* text segment `text`. One `addInlineBlock` operation (its payload names
|
|
342
|
+
* the segment). Answers the text segment right after the atom, where a
|
|
343
|
+
* caret goes (`null` when it was not written, `undefined` when refused).
|
|
344
|
+
*/
|
|
345
|
+
addInlineBlock = (payload) => {
|
|
346
|
+
if (!('offset' in payload))
|
|
347
|
+
return this.#addInline(payload);
|
|
348
|
+
const at = this.textAtOffset(Math.max(0, payload.offset));
|
|
349
|
+
return at ? this.#addInline({ index: at.offset, text: at.text, block: payload.block }) : null;
|
|
350
|
+
};
|
|
298
351
|
normalizeContent = batch('normalizeContent', normalizeContent);
|
|
299
352
|
normalizeChildren = batch('normalizeChildren', normalizeChildren);
|
|
300
353
|
/** @deprecated `edytor.suggestions.add({ end: block.id }, …)`. */
|
|
@@ -385,6 +438,8 @@ export class Block {
|
|
|
385
438
|
node.setAttribute(name, value);
|
|
386
439
|
this.node = node;
|
|
387
440
|
const release = this.edytor.surface.register(node, 'block', this.id);
|
|
441
|
+
// A block laid out again with no commit moves the chrome beside it (the overlay measures).
|
|
442
|
+
const unobserve = this.edytor.overlay.observe(node);
|
|
388
443
|
const onDestroy = this.edytor.plugins.flatMap((plugin) => {
|
|
389
444
|
const action = plugin.onBlockAttached?.({ node, block: this });
|
|
390
445
|
return typeof action === 'function' ? [action] : [];
|
|
@@ -395,6 +450,7 @@ export class Block {
|
|
|
395
450
|
if (this.node === node)
|
|
396
451
|
this.node = undefined;
|
|
397
452
|
release();
|
|
453
|
+
unobserve();
|
|
398
454
|
onDestroy.forEach((destroy) => destroy());
|
|
399
455
|
}
|
|
400
456
|
};
|
|
@@ -135,6 +135,19 @@ export type BlockOperations = {
|
|
|
135
135
|
}[];
|
|
136
136
|
replacement: string;
|
|
137
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* A comment thread's anchor (`plugins/comments`): its `comment:<thread>`
|
|
140
|
+
* mark over each run of the text it was made on, one plan, one undo step
|
|
141
|
+
* (its steps: a `formatRange` per run).
|
|
142
|
+
*/
|
|
143
|
+
addComment: {
|
|
144
|
+
thread: string;
|
|
145
|
+
runs: {
|
|
146
|
+
block: string;
|
|
147
|
+
offset: number;
|
|
148
|
+
length: number;
|
|
149
|
+
}[];
|
|
150
|
+
};
|
|
138
151
|
deleteContentAtRange: {
|
|
139
152
|
start: [number, number];
|
|
140
153
|
end: [number, number];
|
|
@@ -146,6 +159,30 @@ export type BlockOperations = {
|
|
|
146
159
|
flow: Flow;
|
|
147
160
|
target: FlowTarget;
|
|
148
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* A text range dragged inside the editor and dropped at `to` (block
|
|
164
|
+
* offsets): its content placed at `to`, then the range deleted — or,
|
|
165
|
+
* with `copy` (Alt), only placed. Both are prepared before any write:
|
|
166
|
+
* hooks see the placement's planned steps and the deletion's, and a
|
|
167
|
+
* veto or a refusal of either writes nothing.
|
|
168
|
+
*/
|
|
169
|
+
moveText: {
|
|
170
|
+
from: {
|
|
171
|
+
start: {
|
|
172
|
+
block: string;
|
|
173
|
+
offset: number;
|
|
174
|
+
};
|
|
175
|
+
end: {
|
|
176
|
+
block: string;
|
|
177
|
+
offset: number;
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
to: {
|
|
181
|
+
block: string;
|
|
182
|
+
offset: number;
|
|
183
|
+
};
|
|
184
|
+
copy: boolean;
|
|
185
|
+
};
|
|
149
186
|
deleteBlocks: {
|
|
150
187
|
blocks: Block[];
|
|
151
188
|
};
|
|
@@ -157,6 +194,38 @@ export type BlockOperations = {
|
|
|
157
194
|
};
|
|
158
195
|
/** A divider at the caret: its steps are the conversion, insertion or split it plans. */
|
|
159
196
|
insertDivider: {};
|
|
197
|
+
/** A table's row at `index`, one empty cell per column (`table.insert-row`). */
|
|
198
|
+
insertTableRow: {
|
|
199
|
+
index: number;
|
|
200
|
+
};
|
|
201
|
+
/** A table's rows, with their cells (`table.delete-row`). */
|
|
202
|
+
deleteTableRows: {
|
|
203
|
+
rows: Block[];
|
|
204
|
+
};
|
|
205
|
+
/** A table's column at `index`, an empty cell in every row (`table.insert-column`). */
|
|
206
|
+
insertTableColumn: {
|
|
207
|
+
index: number;
|
|
208
|
+
width?: number;
|
|
209
|
+
};
|
|
210
|
+
/** A table's column, by id or position, with its cells (`table.delete-column`). */
|
|
211
|
+
deleteTableColumn: {
|
|
212
|
+
column: string | number;
|
|
213
|
+
};
|
|
214
|
+
/** A table's column moved to position `to` (`table.move-column`). */
|
|
215
|
+
moveTableColumn: {
|
|
216
|
+
column: string | number;
|
|
217
|
+
to: number;
|
|
218
|
+
};
|
|
219
|
+
/** A table's rows moved to position `to` among its rows (`table.move-row`). */
|
|
220
|
+
moveTableRows: {
|
|
221
|
+
rows: Block[];
|
|
222
|
+
to: number;
|
|
223
|
+
};
|
|
224
|
+
/** The cell a row shows none of in `column`, created (`table.pad`). */
|
|
225
|
+
fillTableCell: {
|
|
226
|
+
row: string;
|
|
227
|
+
column: string | number;
|
|
228
|
+
};
|
|
160
229
|
};
|
|
161
230
|
/**
|
|
162
231
|
* Bind an operation onto its wrapper: every call is dispatched as a command
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Block colours (Notion's "Color" in the block menu): a block's text colour
|
|
3
|
+
* and background, by palette name, in two data leaves, `data.color` and
|
|
4
|
+
* `data.background`. Each is one property of the block, so two people
|
|
5
|
+
* colouring it at once keep one value each (per-leaf last writer), and
|
|
6
|
+
* Turn into keeps them (a retype sets only the leaves it names).
|
|
7
|
+
*
|
|
8
|
+
* The core renders a valid name as `data-edytor-color` and
|
|
9
|
+
* `data-edytor-background` on the block element (`Block.svelte`, owned by
|
|
10
|
+
* the attribute table), and its stylesheet paints the bundled names from
|
|
11
|
+
* theme tokens (`--edytor-color-<name>`, `--edytor-background-<name>`).
|
|
12
|
+
*/
|
|
13
|
+
import type { Block } from './block.svelte.js';
|
|
14
|
+
import type { Edytor } from '../edytor.svelte.js';
|
|
15
|
+
/** Notion's palette: the colour names a block may hold, in menu order ("Default" is none). */
|
|
16
|
+
export declare const BLOCK_COLORS: readonly ["gray", "brown", "orange", "yellow", "green", "blue", "purple", "pink", "red"];
|
|
17
|
+
/**
|
|
18
|
+
* Notion's light values of the palette: the fallbacks of the theme tokens
|
|
19
|
+
* (`--edytor-color-<name>`, `--edytor-background-<name>`), as the core's
|
|
20
|
+
* stylesheet (`Block.svelte`) and the Notion theme write them.
|
|
21
|
+
*/
|
|
22
|
+
export declare const BLOCK_PALETTE: Record<(typeof BLOCK_COLORS)[number], {
|
|
23
|
+
color: string;
|
|
24
|
+
background: string;
|
|
25
|
+
}>;
|
|
26
|
+
/** A block's colour fields: its text colour and its background. */
|
|
27
|
+
export type BlockColorField = 'color' | 'background';
|
|
28
|
+
/** `value` as a colour name, or `undefined`. */
|
|
29
|
+
export declare const colorName: (value: unknown) => string | undefined;
|
|
30
|
+
/** The block element's colour attributes for `data` (absent when it holds none). */
|
|
31
|
+
export declare const colorAttributes: (data: Readonly<Record<string, unknown>> | undefined) => {
|
|
32
|
+
'data-edytor-color': string | undefined;
|
|
33
|
+
'data-edytor-background': string | undefined;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Whether `block` takes a colour: a block showing its own text (a
|
|
37
|
+
* paragraph, a heading, a list item, a toggle, a callout), not a void (a
|
|
38
|
+
* divider, an image), an island (a code block) or one of its lines.
|
|
39
|
+
*/
|
|
40
|
+
export declare const colorable: (block: Block) => boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Set `field` of every colourable block of `blocks` to `value` (`null`
|
|
43
|
+
* removes it: the default), as one command and one undo step; each block
|
|
44
|
+
* is its own data write (`patchData`), so an extension vetoing one keeps
|
|
45
|
+
* that block as it was. Answers whether any block changed.
|
|
46
|
+
*/
|
|
47
|
+
export declare const setBlockColor: (edytor: Edytor, blocks: Iterable<Block>, field: BlockColorField, value: string | null) => boolean;
|
|
48
|
+
/**
|
|
49
|
+
* A block's colours as the classes Notion's HTML export writes
|
|
50
|
+
* (`block-color-red`, `block-color-red_background`), space-separated; empty
|
|
51
|
+
* when it holds none. The copy's `text/html` names them so.
|
|
52
|
+
*/
|
|
53
|
+
export declare const colorClasses: (data: Readonly<Record<string, unknown>> | undefined) => string;
|
|
54
|
+
/**
|
|
55
|
+
* The palette colours `element`'s classes name as Notion's HTML export does
|
|
56
|
+
* (its `teal` read as green): what a paste keeps. A class naming no palette
|
|
57
|
+
* colour adds nothing.
|
|
58
|
+
*/
|
|
59
|
+
export declare const colorsOfClasses: (element: Element) => {
|
|
60
|
+
color?: string;
|
|
61
|
+
background?: string;
|
|
62
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/** Notion's palette: the colour names a block may hold, in menu order ("Default" is none). */
|
|
2
|
+
export const BLOCK_COLORS = [
|
|
3
|
+
'gray',
|
|
4
|
+
'brown',
|
|
5
|
+
'orange',
|
|
6
|
+
'yellow',
|
|
7
|
+
'green',
|
|
8
|
+
'blue',
|
|
9
|
+
'purple',
|
|
10
|
+
'pink',
|
|
11
|
+
'red'
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Notion's light values of the palette: the fallbacks of the theme tokens
|
|
15
|
+
* (`--edytor-color-<name>`, `--edytor-background-<name>`), as the core's
|
|
16
|
+
* stylesheet (`Block.svelte`) and the Notion theme write them.
|
|
17
|
+
*/
|
|
18
|
+
export const BLOCK_PALETTE = {
|
|
19
|
+
gray: { color: '#7d7a75', background: '#f0efed' },
|
|
20
|
+
brown: { color: '#9f765a', background: '#f5ede9' },
|
|
21
|
+
orange: { color: '#d27b2d', background: '#fbebde' },
|
|
22
|
+
yellow: { color: '#cb9434', background: '#f9f3dc' },
|
|
23
|
+
green: { color: '#50946e', background: '#e8f1ec' },
|
|
24
|
+
blue: { color: '#387dc9', background: '#e5f2fc' },
|
|
25
|
+
purple: { color: '#9a6bb4', background: '#f3ebf9' },
|
|
26
|
+
pink: { color: '#c14c8a', background: '#fae9f1' },
|
|
27
|
+
red: { color: '#cf5148', background: '#fce9e7' }
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* A colour name the core renders: lowercase letters, digits and hyphens,
|
|
31
|
+
* starting with a letter (an app's own name, such as `teal`, renders too,
|
|
32
|
+
* and its stylesheet paints it). Anything else renders nothing.
|
|
33
|
+
*/
|
|
34
|
+
const NAME = /^[a-z][a-z0-9-]{0,31}$/;
|
|
35
|
+
/** `value` as a colour name, or `undefined`. */
|
|
36
|
+
export const colorName = (value) => typeof value === 'string' && NAME.test(value) ? value : undefined;
|
|
37
|
+
/** The block element's colour attributes for `data` (absent when it holds none). */
|
|
38
|
+
export const colorAttributes = (data) => ({
|
|
39
|
+
'data-edytor-color': colorName(data?.color),
|
|
40
|
+
'data-edytor-background': colorName(data?.background)
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Whether `block` takes a colour: a block showing its own text (a
|
|
44
|
+
* paragraph, a heading, a list item, a toggle, a callout), not a void (a
|
|
45
|
+
* divider, an image), an island (a code block) or one of its lines.
|
|
46
|
+
*/
|
|
47
|
+
export const colorable = (block) => {
|
|
48
|
+
const { facade } = block.edytor;
|
|
49
|
+
const line = block.parent && !block.parent.isRoot && facade.isLines(block.parent.id);
|
|
50
|
+
return (!block.isRoot &&
|
|
51
|
+
block.rendersContent &&
|
|
52
|
+
!facade.isVoid(block.id) &&
|
|
53
|
+
!facade.isIsland(block.id) &&
|
|
54
|
+
!line);
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Set `field` of every colourable block of `blocks` to `value` (`null`
|
|
58
|
+
* removes it: the default), as one command and one undo step; each block
|
|
59
|
+
* is its own data write (`patchData`), so an extension vetoing one keeps
|
|
60
|
+
* that block as it was. Answers whether any block changed.
|
|
61
|
+
*/
|
|
62
|
+
export const setBlockColor = (edytor, blocks, field, value) => {
|
|
63
|
+
const name = value === null ? undefined : colorName(value);
|
|
64
|
+
if (value !== null && name === undefined)
|
|
65
|
+
return false;
|
|
66
|
+
const painted = [...blocks].filter((block) => colorable(block) && edytor.facade.blockDataOf(block.id)?.[field] !== name);
|
|
67
|
+
if (!painted.length)
|
|
68
|
+
return false;
|
|
69
|
+
const applied = edytor.dispatcher.each('setBlockColor', painted, (block) => {
|
|
70
|
+
block.patchData({ ops: [{ path: [field], value: name }] });
|
|
71
|
+
return edytor.dispatcher.last?.status === 'applied';
|
|
72
|
+
});
|
|
73
|
+
return applied.some(Boolean);
|
|
74
|
+
};
|
|
75
|
+
/** The class Notion's HTML export gives a block's colour: `block-color-<name>`, `block-color-<name>_background`. */
|
|
76
|
+
const CLASS = /^block-color-([a-z]+)(_background)?$/;
|
|
77
|
+
/** Notion's export names the palette's green `teal`. */
|
|
78
|
+
const EXPORTED = { teal: 'green' };
|
|
79
|
+
/**
|
|
80
|
+
* A block's colours as the classes Notion's HTML export writes
|
|
81
|
+
* (`block-color-red`, `block-color-red_background`), space-separated; empty
|
|
82
|
+
* when it holds none. The copy's `text/html` names them so.
|
|
83
|
+
*/
|
|
84
|
+
export const colorClasses = (data) => {
|
|
85
|
+
const color = colorName(data?.color);
|
|
86
|
+
const background = colorName(data?.background);
|
|
87
|
+
return [color && `block-color-${color}`, background && `block-color-${background}_background`]
|
|
88
|
+
.filter(Boolean)
|
|
89
|
+
.join(' ');
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* The palette colours `element`'s classes name as Notion's HTML export does
|
|
93
|
+
* (its `teal` read as green): what a paste keeps. A class naming no palette
|
|
94
|
+
* colour adds nothing.
|
|
95
|
+
*/
|
|
96
|
+
export const colorsOfClasses = (element) => {
|
|
97
|
+
const found = {};
|
|
98
|
+
for (const name of element.classList) {
|
|
99
|
+
const [, raw, background] = CLASS.exec(name) ?? [];
|
|
100
|
+
const color = raw && (EXPORTED[raw] ?? raw);
|
|
101
|
+
if (!color || !BLOCK_COLORS.includes(color))
|
|
102
|
+
continue;
|
|
103
|
+
found[background ? 'background' : 'color'] = color;
|
|
104
|
+
}
|
|
105
|
+
return found;
|
|
106
|
+
};
|
|
@@ -5,7 +5,8 @@ import type { Block } from './block.svelte.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* An id-only inline-atom handle: atom `id`, shown in
|
|
7
7
|
* block `blockId`. Getters read the document index; `node` is the element
|
|
8
|
-
* that renders it (a Surface fact).
|
|
8
|
+
* that renders it (a Surface fact). A reactive reader of a getter depends on
|
|
9
|
+
* the block's cell, so it re-runs when a commit changes the block's content.
|
|
9
10
|
*/
|
|
10
11
|
export declare class InlineBlock {
|
|
11
12
|
#private;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { clearDomSelection } from '../selection/domSelection.js';
|
|
2
1
|
import { propsProxy } from '../session/props.js';
|
|
3
2
|
const INLINE_EDGE_CARET_THRESHOLD_PX = 4;
|
|
4
3
|
const isTextPart = (part) => part !== undefined && !(part instanceof InlineBlock);
|
|
5
4
|
/**
|
|
6
5
|
* An id-only inline-atom handle: atom `id`, shown in
|
|
7
6
|
* block `blockId`. Getters read the document index; `node` is the element
|
|
8
|
-
* that renders it (a Surface fact).
|
|
7
|
+
* that renders it (a Surface fact). A reactive reader of a getter depends on
|
|
8
|
+
* the block's cell, so it re-runs when a commit changes the block's content.
|
|
9
9
|
*/
|
|
10
10
|
export class InlineBlock {
|
|
11
11
|
_def = 'inline';
|
|
@@ -25,6 +25,8 @@ export class InlineBlock {
|
|
|
25
25
|
return this.edytor.idToBlock.block(this.blockId);
|
|
26
26
|
}
|
|
27
27
|
get #item() {
|
|
28
|
+
if ($effect.tracking())
|
|
29
|
+
this.edytor.cells?.get(this.blockId);
|
|
28
30
|
const parts = this.edytor.idToBlock.parts(this.blockId);
|
|
29
31
|
const part = parts.find((part) => part.kind === 'inline' && part.item.id === this.id);
|
|
30
32
|
return part?.kind === 'inline' ? part.item : undefined;
|
|
@@ -88,10 +90,10 @@ export class InlineBlock {
|
|
|
88
90
|
if (event.clientX >= rect.right - INLINE_EDGE_CARET_THRESHOLD_PX && isTextPart(after))
|
|
89
91
|
return selection.setAtTextOffset(after, 0);
|
|
90
92
|
selection.selectInlineBlock(this);
|
|
91
|
-
|
|
93
|
+
this.edytor.ports.surface.clear();
|
|
92
94
|
// The atom took the press: the caret the browser still leaves for it
|
|
93
95
|
// (Chromium parks one at the host's start before the release) is its own.
|
|
94
|
-
this.edytor.
|
|
96
|
+
this.edytor.ports.surface.parked();
|
|
95
97
|
};
|
|
96
98
|
node.addEventListener('pointerdown', selectInlineBlock);
|
|
97
99
|
return {
|
|
@@ -67,7 +67,40 @@ const extractBlockRange = (edytor) => {
|
|
|
67
67
|
return value;
|
|
68
68
|
});
|
|
69
69
|
};
|
|
70
|
-
|
|
70
|
+
/**
|
|
71
|
+
* `fragment` without the marks whose record says `copy: false` (a
|
|
72
|
+
* comment's anchor, `comment:<id>`: Notion copies the text, not the
|
|
73
|
+
* comment): one rule for copy, cut and the internal paste they feed.
|
|
74
|
+
*/
|
|
75
|
+
const withoutUncopied = (edytor, fragment) => {
|
|
76
|
+
if (!fragment)
|
|
77
|
+
return fragment;
|
|
78
|
+
const strip = (content) => {
|
|
79
|
+
for (const part of content ?? []) {
|
|
80
|
+
if (!('text' in part) || !part.marks)
|
|
81
|
+
continue;
|
|
82
|
+
for (const key of Object.keys(part.marks))
|
|
83
|
+
if (edytor.marks.get(key)?.copy === false)
|
|
84
|
+
delete part.marks[key];
|
|
85
|
+
if (Object.keys(part.marks).length === 0)
|
|
86
|
+
delete part.marks;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const walk = (blocks) => {
|
|
90
|
+
for (const block of blocks) {
|
|
91
|
+
strip(block.content);
|
|
92
|
+
if (block.children)
|
|
93
|
+
walk(block.children);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
if (fragment.kind === 'blocks')
|
|
97
|
+
walk(fragment.blocks);
|
|
98
|
+
else
|
|
99
|
+
strip(fragment.content);
|
|
100
|
+
return fragment;
|
|
101
|
+
};
|
|
102
|
+
export const createEdytorClipboardFragment = (edytor) => withoutUncopied(edytor, fragmentOf(edytor));
|
|
103
|
+
const fragmentOf = (edytor) => {
|
|
71
104
|
// A layout the block selection covers whole is copied as the layout (D3).
|
|
72
105
|
const selectedBlocks = selectedMembers(edytor, liftLayouts(edytor.selection.selectedBlocks));
|
|
73
106
|
if (selectedBlocks.length > 0) {
|
|
@@ -2,8 +2,8 @@ import type { Edytor } from '../edytor.svelte.js';
|
|
|
2
2
|
import type { Flow } from '../crdt/flow.js';
|
|
3
3
|
import type { BlockDefinition } from '../plugins.js';
|
|
4
4
|
import { type SerializableContent } from '../utils/json.js';
|
|
5
|
-
/** What HTML import reads: the kind and
|
|
6
|
-
export type ImportKinds = Pick<Edytor, 'blocks' | 'marks'> & {
|
|
5
|
+
/** What HTML import reads: the kind, mark and atom records, and the document's default child. */
|
|
6
|
+
export type ImportKinds = Pick<Edytor, 'blocks' | 'marks'> & Partial<Pick<Edytor, 'inlineBlocks'>> & {
|
|
7
7
|
document: Pick<Edytor['document'], 'defaultChild'>;
|
|
8
8
|
};
|
|
9
9
|
type Values = Record<string, SerializableContent>;
|
|
@@ -17,7 +17,9 @@ export declare const tagOf: (type: string, kind: BlockDefinition, data: Values)
|
|
|
17
17
|
* `tag`, and each record's `parse` hook first (aliases, sanitized values).
|
|
18
18
|
* A void kind with a `parse` hook (an image, an embed, a video) is found
|
|
19
19
|
* by its hook only, and a void takes only its `figcaption`'s text; an
|
|
20
|
-
* `iframe`, `video` or `audio` no hook claims carries nothing.
|
|
20
|
+
* `iframe`, `video` or `audio` no hook claims carries nothing. An atom
|
|
21
|
+
* kind's `parse` hook claims inline elements (an equation's `<math>`): the
|
|
22
|
+
* atom, never its text. Unknown
|
|
21
23
|
* elements degrade to text runs; whitespace collapses as HTML renders it. `null` when the HTML carries nothing (`flow.shape`, F-P10).
|
|
22
24
|
*/
|
|
23
25
|
export declare const flowOfHtml: (kinds: ImportKinds, html: string | undefined) => Flow | null;
|