edytor 0.1.0-next.32 → 0.1.0-next.36
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 +10 -6
- package/dist/block/block.svelte.d.ts +34 -38
- package/dist/block/block.svelte.js +24 -8
- package/dist/block/block.utils.d.ts +19 -1
- package/dist/block/block.utils.js +2 -1
- package/dist/block/colors.d.ts +47 -0
- package/dist/block/colors.js +74 -0
- package/dist/block/inlineBlock.svelte.d.ts +1 -4
- package/dist/block/inlineBlock.svelte.js +2 -1
- package/dist/clipboard/htmlFlow.d.ts +4 -2
- package/dist/clipboard/htmlFlow.js +101 -17
- package/dist/cloudflare/DocumentRoom.d.ts +164 -486
- package/dist/cloudflare/DocumentRoom.js +219 -3276
- package/dist/cloudflare/history.d.ts +4 -4
- package/dist/cloudflare/history.js +3 -3
- package/dist/cloudflare/index.d.ts +3 -3
- package/dist/cloudflare/index.js +2 -2
- package/dist/cloudflare/locks.d.ts +1 -1
- package/dist/cloudflare/locks.js +1 -1
- package/dist/cloudflare/move.d.ts +11 -1
- package/dist/cloudflare/move.js +8 -3
- package/dist/cloudflare/room/access.d.ts +31 -0
- package/dist/cloudflare/room/access.js +226 -0
- package/dist/cloudflare/room/admission.d.ts +117 -0
- package/dist/cloudflare/room/admission.js +559 -0
- package/dist/cloudflare/room/context.d.ts +790 -0
- package/dist/cloudflare/room/context.js +293 -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 +24 -0
- package/dist/cloudflare/room/frames.js +37 -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 +419 -0
- package/dist/cloudflare/room/presence.d.ts +64 -0
- package/dist/cloudflare/room/presence.js +202 -0
- package/dist/cloudflare/room/purge.d.ts +16 -0
- package/dist/cloudflare/room/purge.js +114 -0
- package/dist/cloudflare/room/replicas.d.ts +51 -0
- package/dist/cloudflare/room/replicas.js +145 -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 +153 -0
- package/dist/cloudflare/room/storage.js +758 -0
- package/dist/cloudflare/room/updates.d.ts +89 -0
- package/dist/cloudflare/room/updates.js +328 -0
- package/dist/cloudflare/room/validation.d.ts +61 -0
- package/dist/cloudflare/room/validation.js +227 -0
- package/dist/cloudflare/routeDocumentSocket.d.ts +29 -5
- package/dist/cloudflare/routeDocumentSocket.js +32 -10
- package/dist/collaboration/awarenessSelection.d.ts +2 -2
- package/dist/collaboration/awarenessSelection.js +2 -2
- package/dist/collaboration/history/HistoryPanel.svelte +531 -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 +89 -0
- package/dist/collaboration/history/panel.js +28 -0
- package/dist/collaboration/history/versionHighlights.d.ts +9 -0
- package/dist/collaboration/history/versionHighlights.js +17 -0
- package/dist/collaboration/index.d.ts +1 -1
- package/dist/collaboration/index.js +1 -1
- package/dist/collaboration/providers.d.ts +0 -3
- package/dist/collaboration/providers.js +6 -11
- package/dist/components/Announcer.svelte +28 -0
- package/dist/components/Announcer.svelte.d.ts +7 -0
- package/dist/components/Block.svelte +78 -0
- package/dist/components/Edytor.svelte +59 -9
- package/dist/components/Edytor.svelte.d.ts +27 -4
- package/dist/components/Suggestion.svelte +1 -1
- package/dist/crdt/attribution/attribution.d.ts +3 -3
- package/dist/crdt/data.d.ts +11 -0
- package/dist/crdt/data.js +62 -12
- 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 +199 -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 +91 -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 +61 -0
- package/dist/crdt/doc/reads.js +240 -0
- package/dist/crdt/doc/seed.d.ts +38 -0
- package/dist/crdt/doc/seed.js +107 -0
- package/dist/crdt/doc/split-merge.d.ts +12 -0
- package/dist/crdt/doc/split-merge.js +180 -0
- package/dist/crdt/doc/steps.d.ts +57 -0
- package/dist/crdt/doc/steps.js +370 -0
- package/dist/crdt/doc/types.d.ts +302 -0
- package/dist/crdt/doc/types.js +1 -0
- package/dist/crdt/document.d.ts +31 -49
- package/dist/crdt/document.js +38 -53
- package/dist/crdt/edytor-doc.d.ts +32 -520
- package/dist/crdt/edytor-doc.js +82 -2468
- package/dist/crdt/engine-api.d.ts +4 -5
- package/dist/crdt/flow.d.ts +1 -1
- package/dist/crdt/index.d.ts +42 -58
- package/dist/crdt/index.js +33 -54
- package/dist/crdt/migration/migrate.d.ts +5 -5
- package/dist/crdt/nodes.d.ts +2 -2
- package/dist/crdt/placement/display.d.ts +106 -0
- package/dist/crdt/placement/display.js +339 -0
- package/dist/crdt/placement/model.d.ts +16 -177
- package/dist/crdt/placement/model.js +7 -558
- 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 +44 -0
- package/dist/crdt/protocol.js +62 -0
- package/dist/crdt/protocols/envelope.d.ts +1 -1
- package/dist/crdt/providers/bound.d.ts +2 -0
- package/dist/crdt/providers/bound.js +9 -0
- package/dist/crdt/providers/index.d.ts +6 -6
- package/dist/crdt/providers/indexeddb.d.ts +6 -6
- package/dist/crdt/providers/indexeddb.js +1 -1
- package/dist/crdt/providers/room.d.ts +19 -3
- package/dist/crdt/providers/room.js +54 -34
- package/dist/crdt/providers/websocket.d.ts +3 -4
- package/dist/crdt/rangeDelete.d.ts +1 -1
- package/dist/crdt/semantics.d.ts +145 -12
- package/dist/crdt/semantics.js +191 -14
- package/dist/crdt/text/delete-index.d.ts +145 -0
- package/dist/crdt/text/delete-index.js +368 -0
- package/dist/crdt/text/deletes.d.ts +49 -0
- package/dist/crdt/text/deletes.js +2 -379
- package/dist/crdt/text/index/anchored.d.ts +17 -0
- package/dist/crdt/text/index/anchored.js +196 -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 +22 -0
- package/dist/crdt/text/index/fold.js +496 -0
- package/dist/crdt/text/index/layout.d.ts +21 -0
- package/dist/crdt/text/index/layout.js +124 -0
- package/dist/crdt/text/index/placement.d.ts +39 -0
- package/dist/crdt/text/index/placement.js +450 -0
- package/dist/crdt/text/index/records.d.ts +13 -0
- package/dist/crdt/text/index/records.js +140 -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 +102 -0
- package/dist/crdt/text/index/state.d.ts +213 -0
- package/dist/crdt/text/index/state.js +113 -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 +2 -0
- package/dist/crdt/text/model.d.ts +7 -53
- package/dist/crdt/text/model.js +7 -227
- package/dist/crdt/text/ranges.d.ts +20 -0
- package/dist/crdt/text/ranges.js +82 -0
- package/dist/crdt/text/runs.d.ts +32 -28
- package/dist/crdt/text/runs.js +39 -2469
- package/dist/crdt/text/streams.d.ts +45 -0
- package/dist/crdt/text/streams.js +138 -0
- package/dist/edytor.svelte.d.ts +37 -164
- package/dist/edytor.svelte.js +104 -50
- package/dist/events/beforeInputCommands.js +8 -6
- package/dist/events/onBeforeInput.js +6 -6
- package/dist/events/onCopy.js +2 -2
- package/dist/events/onDrop.js +2 -2
- package/dist/events/onKeyDown.js +4 -3
- package/dist/events/onPaste.js +5 -4
- package/dist/index.d.ts +30 -24
- package/dist/index.js +32 -23
- package/dist/kinds.d.ts +15 -3
- package/dist/kinds.js +22 -4
- package/dist/labels.d.ts +340 -0
- package/dist/labels.js +334 -0
- package/dist/plugins/blockHandles/BlockHandle.svelte +16 -7
- package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +15 -3
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +19 -3
- package/dist/plugins/blockHandles/blockHandlesPlugin.d.ts +6 -1
- package/dist/plugins/blockHandles/blockHandlesPlugin.js +4 -2
- package/dist/plugins/blockMenu/BlockMenu.svelte +133 -32
- package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +51 -9
- package/dist/plugins/blockMenu/BlockMenuController.svelte.js +102 -18
- package/dist/plugins/code/CodeHeader.svelte +68 -0
- package/dist/plugins/code/CodeHeader.svelte.d.ts +9 -0
- package/dist/plugins/code/CodePlugin.svelte +227 -224
- package/dist/plugins/code/CodePlugin.svelte.d.ts +10 -0
- package/dist/plugins/code/code.css +27 -8
- package/dist/plugins/code/languages.d.ts +65 -0
- package/dist/plugins/code/languages.js +192 -0
- package/dist/plugins/columns/ColumnResize.svelte +24 -2
- package/dist/plugins/columns/ColumnsPlugin.svelte +32 -9
- package/dist/plugins/columns/ColumnsPlugin.svelte.d.ts +8 -0
- package/dist/plugins/columns/resize.svelte.d.ts +40 -2
- package/dist/plugins/columns/resize.svelte.js +98 -24
- package/dist/plugins/find/FindBar.svelte +170 -0
- package/dist/plugins/find/FindBar.svelte.d.ts +9 -0
- package/dist/plugins/find/FindController.svelte.d.ts +67 -0
- package/dist/plugins/find/FindController.svelte.js +247 -0
- package/dist/plugins/find/FindHighlights.svelte +75 -0
- package/dist/plugins/find/FindHighlights.svelte.d.ts +9 -0
- package/dist/plugins/find/findPlugin.d.ts +28 -0
- package/dist/plugins/find/findPlugin.js +56 -0
- package/dist/plugins/find/search.d.ts +18 -0
- package/dist/plugins/find/search.js +41 -0
- package/dist/plugins/icons.js +17 -1
- package/dist/plugins/image/ImageChrome.svelte +213 -0
- package/dist/plugins/image/ImageChrome.svelte.d.ts +7 -0
- package/dist/plugins/image/ImageEmpty.svelte +54 -20
- package/dist/plugins/image/ImageEmpty.svelte.d.ts +4 -0
- package/dist/plugins/image/ImagePlugin.svelte +213 -40
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +25 -4
- package/dist/plugins/image/controls.svelte.d.ts +116 -0
- package/dist/plugins/image/controls.svelte.js +289 -0
- package/dist/plugins/image/image.d.ts +24 -1
- package/dist/plugins/image/image.js +34 -1
- package/dist/plugins/image/uploads.svelte.d.ts +50 -0
- package/dist/plugins/image/uploads.svelte.js +111 -0
- package/dist/plugins/index.d.ts +18 -4
- package/dist/plugins/index.js +15 -3
- package/dist/plugins/markdownShortcuts.js +99 -67
- package/dist/plugins/media/AudioPlugin.svelte +92 -0
- package/dist/plugins/media/AudioPlugin.svelte.d.ts +28 -0
- package/dist/plugins/media/BookmarkPlugin.svelte +194 -0
- package/dist/plugins/media/BookmarkPlugin.svelte.d.ts +50 -0
- package/dist/plugins/media/EmbedPlugin.svelte +159 -0
- package/dist/plugins/media/EmbedPlugin.svelte.d.ts +42 -0
- package/dist/plugins/media/FilePlugin.svelte +119 -0
- package/dist/plugins/media/FilePlugin.svelte.d.ts +28 -0
- package/dist/plugins/media/MediaEmpty.svelte +108 -0
- package/dist/plugins/media/MediaEmpty.svelte.d.ts +16 -0
- package/dist/plugins/media/UrlPasteMenu.svelte +83 -0
- package/dist/plugins/media/UrlPasteMenu.svelte.d.ts +7 -0
- package/dist/plugins/media/VideoPlugin.svelte +101 -0
- package/dist/plugins/media/VideoPlugin.svelte.d.ts +29 -0
- package/dist/plugins/media/media.d.ts +82 -0
- package/dist/plugins/media/media.js +225 -0
- package/dist/plugins/media/urlPaste.svelte.d.ts +81 -0
- package/dist/plugins/media/urlPaste.svelte.js +201 -0
- package/dist/plugins/mention/MentionPlugin.svelte +163 -31
- package/dist/plugins/mention/MentionPlugin.svelte.d.ts +32 -2
- package/dist/plugins/page/PageLink.svelte +117 -0
- package/dist/plugins/page/PageLink.svelte.d.ts +11 -0
- package/dist/plugins/page/PagePlugin.svelte +112 -0
- package/dist/plugins/page/PagePlugin.svelte.d.ts +43 -0
- package/dist/plugins/page/page.d.ts +54 -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 +255 -76
- 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 +43 -3
- package/dist/plugins/richtext/richTextOperations.js +71 -1
- package/dist/plugins/slashMenu/SlashMenu.svelte +109 -46
- package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +27 -24
- package/dist/plugins/slashMenu/SlashMenuController.svelte.js +48 -138
- package/dist/plugins/slashMenu/slashMenuPlugin.d.ts +5 -0
- package/dist/plugins/slashMenu/slashMenuPlugin.js +7 -25
- package/dist/plugins/suggestions/SuggestionBars.svelte +12 -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/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 +118 -0
- package/dist/plugins/toolbar/LinkCard.svelte.d.ts +7 -0
- package/dist/plugins/toolbar/Toolbar.svelte +80 -21
- package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +48 -3
- package/dist/plugins/toolbar/ToolbarController.svelte.js +131 -4
- package/dist/plugins/toolbar/toolbarPlugin.d.ts +8 -0
- package/dist/plugins/toolbar/toolbarPlugin.js +83 -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 +169 -44
- package/dist/selection/replaceSelection.d.ts +7 -1
- package/dist/selection/replaceSelection.js +20 -9
- package/dist/selection/selection.svelte.d.ts +33 -121
- package/dist/selection/selection.svelte.js +63 -15
- package/dist/session/announcer.svelte.d.ts +28 -0
- package/dist/session/announcer.svelte.js +40 -0
- package/dist/session/bindings.js +3 -1
- package/dist/session/commands.d.ts +46 -16
- package/dist/session/commands.js +138 -32
- package/dist/session/editing/text.d.ts +1 -1
- package/dist/session/history.d.ts +8 -1
- package/dist/session/history.js +10 -3
- package/dist/session/inputRules.d.ts +20 -0
- package/dist/session/inputRules.js +128 -0
- package/dist/session/keymap.d.ts +1 -1
- package/dist/session/keymap.js +2 -2
- package/dist/session/moves.d.ts +3 -2
- package/dist/session/moves.js +6 -2
- package/dist/session/navigation.js +1 -1
- package/dist/session/selection.d.ts +3 -3
- package/dist/session/suggestions.svelte.d.ts +0 -2
- package/dist/session/virtual.js +3 -2
- package/dist/surface/attributes.d.ts +13 -0
- package/dist/surface/attributes.js +24 -0
- package/dist/surface/cells.d.ts +1 -1
- package/dist/surface/popups.svelte.d.ts +28 -0
- package/dist/surface/popups.svelte.js +32 -0
- package/dist/surface/projector.svelte.js +8 -1
- package/dist/text/text.svelte.d.ts +2 -5
- package/dist/text/text.svelte.js +3 -2
- package/dist/text/text.utils.js +2 -1
- package/dist/themes/notion.css +301 -16
- package/dist/utils/json.d.ts +2 -0
- package/dist/utils/json.js +15 -0
- package/dist/utils.d.ts +10 -1
- package/dist/utils.js +22 -2
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
<p>A collaborative block editor for Svelte 5, on a Yjs v14 engine</p>
|
|
5
5
|
|
|
6
|
+
[](https://github.com/beynar/edytor/actions/workflows/ci.yml)
|
|
6
7
|
[](https://opensource.org/licenses/MIT)
|
|
7
8
|
[](https://svelte.dev)
|
|
8
9
|
|
|
@@ -15,13 +16,16 @@
|
|
|
15
16
|
|
|
16
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.
|
|
17
18
|
|
|
18
|
-
> **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.36`, `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.
|
|
19
20
|
|
|
20
21
|
## Features
|
|
21
22
|
|
|
22
|
-
- **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)).
|
|
23
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
|
+
- **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)).
|
|
24
27
|
- **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.
|
|
28
|
+
- **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)).
|
|
25
29
|
- **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.
|
|
26
30
|
- **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)).
|
|
27
31
|
- **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.
|
|
@@ -38,7 +42,7 @@ The pre-release is on npm under the `next` tag. Name the tag: a bare `edytor` is
|
|
|
38
42
|
pnpm add edytor@next
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
`svelte@^5` is a peer dependency. Do not install `yjs`: the v14 engine is vendored (`edytor/crdt`). See [installation](https://edytor.dev/docs/getting-started).
|
|
45
|
+
`svelte@^5` is a peer dependency. Do not install `yjs`: the v14 engine is vendored (`edytor/crdt`). See [installation](https://edytor.dev/docs/getting-started) and [platform support](https://edytor.dev/docs/reference/platform-support) (Chrome, Edge, Firefox and Safari; real phones are not tested yet).
|
|
42
46
|
|
|
43
47
|
## Quick start
|
|
44
48
|
|
|
@@ -78,7 +82,7 @@ pnpm add edytor@next
|
|
|
78
82
|
</div>
|
|
79
83
|
```
|
|
80
84
|
|
|
81
|
-
`<Edytor>` adds the rich text, image, arrow-move and suggestions plugins after yours, and block handles. To collaborate, name a room and a server running the [`edytor/cloudflare` room](https://edytor.dev/docs/server/quick-start):
|
|
85
|
+
An editable editor is client-only: in SvelteKit, mount it once the page has hydrated ([quick start](https://edytor.dev/docs/getting-started/quick-start#mount-it-in-a-page)). `<Edytor>` adds the rich text, image, arrow-move and suggestions plugins after yours, and block handles. To collaborate, name a room and a server running the [`edytor/cloudflare` room](https://edytor.dev/docs/server/quick-start):
|
|
82
86
|
|
|
83
87
|
```svelte
|
|
84
88
|
<Edytor
|
|
@@ -98,11 +102,11 @@ The [documentation site](https://edytor.dev/docs) is the single source for the A
|
|
|
98
102
|
- [Editor](https://edytor.dev/docs/editor/edytor-component): the component, commands, selection, history, clipboard, readonly
|
|
99
103
|
- [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)
|
|
100
104
|
- [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
|
|
101
|
-
- [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
|
|
105
|
+
- [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)
|
|
102
106
|
|
|
103
107
|
## Contributing
|
|
104
108
|
|
|
105
|
-
`AGENTS.md` describes the architecture (one owner per fact)
|
|
109
|
+
`CONTRIBUTING.md` lists the test lanes, what CI runs, and the pull request checklist; `AGENTS.md` describes the architecture (one owner per fact) and where to fix what. The docs live in `site/content/docs`; a change to public behavior updates them in the same commit.
|
|
106
110
|
|
|
107
111
|
```bash
|
|
108
112
|
pnpm install
|
|
@@ -45,18 +45,16 @@ export declare class Block {
|
|
|
45
45
|
setData: (data: Record<string, unknown>) => void;
|
|
46
46
|
get selected(): boolean;
|
|
47
47
|
get focused(): boolean;
|
|
48
|
-
/** May this block move at all
|
|
48
|
+
/** May this block move at all: `canPlace` without a destination (drag handles). */
|
|
49
49
|
get movable(): boolean;
|
|
50
50
|
/**
|
|
51
51
|
* May text-level structural commands (convert, markdown shortcut, slash
|
|
52
52
|
* menu) apply: the block is movable — or the virtual paragraph of an
|
|
53
53
|
* emptied document, which a conversion creates with its kind
|
|
54
|
-
*
|
|
55
|
-
* a container (a list) is never converted, its items are
|
|
54
|
+
* — has no role of its own and renders its own content —
|
|
55
|
+
* a container (a list) is never converted, its items are.
|
|
56
56
|
*/
|
|
57
57
|
get convertible(): boolean;
|
|
58
|
-
get firstEditableText(): Text | undefined;
|
|
59
|
-
get lastEditableText(): Text | undefined;
|
|
60
58
|
get index(): number;
|
|
61
59
|
get depth(): number;
|
|
62
60
|
get path(): number[];
|
|
@@ -79,14 +77,14 @@ export declare class Block {
|
|
|
79
77
|
/** It holds nothing: no content and no children (the emptiness Turn into reads, `holdsNothing`). */
|
|
80
78
|
get isEmpty(): boolean;
|
|
81
79
|
get isNested(): boolean;
|
|
82
|
-
/** This block's JSON — the document's one serializer (`facade.blockJSON
|
|
80
|
+
/** This block's JSON — the document's one serializer (`facade.blockJSON`). */
|
|
83
81
|
get value(): JSONBlock;
|
|
84
82
|
isChildOf(block: Block): boolean;
|
|
85
|
-
/** Whether this kind renders its own content slot — the adopted capability
|
|
83
|
+
/** Whether this kind renders its own content slot — the adopted capability. */
|
|
86
84
|
get rendersContent(): boolean;
|
|
87
85
|
/**
|
|
88
86
|
* A container: it shows only its children (a list), neither void nor an
|
|
89
|
-
* island — the document's container rule
|
|
87
|
+
* island — the document's container rule. Its items hold what it
|
|
90
88
|
* shows; it is never converted (`convertible`).
|
|
91
89
|
*/
|
|
92
90
|
get isContainer(): boolean;
|
|
@@ -100,7 +98,7 @@ export declare class Block {
|
|
|
100
98
|
/**
|
|
101
99
|
* The list this block shows in: its container when it is an item
|
|
102
100
|
* (`isListItem`), or — an item outdented out of a nested list into the
|
|
103
|
-
* item holding it
|
|
101
|
+
* item holding it — the list of the items of its kind it
|
|
104
102
|
* sits under. <kbd>Enter</kbd> in an empty one outdents it; the menus
|
|
105
103
|
* name it by the list's `itemKind`.
|
|
106
104
|
*/
|
|
@@ -114,58 +112,64 @@ export declare class Block {
|
|
|
114
112
|
get firstText(): Text | undefined;
|
|
115
113
|
/** The last text of this block's own content (see {@link firstText}). */
|
|
116
114
|
get lastText(): Text | undefined;
|
|
117
|
-
addChildBlock: (
|
|
115
|
+
addChildBlock: (payload: {
|
|
118
116
|
block: JSONBlock;
|
|
119
117
|
index: number;
|
|
120
118
|
}) => Block;
|
|
121
|
-
addChildBlocks: (
|
|
119
|
+
addChildBlocks: (payload: {
|
|
122
120
|
blocks: JSONBlock[];
|
|
123
121
|
index: number;
|
|
124
122
|
}) => Block[];
|
|
125
123
|
insertBlockAfter: (payload: {
|
|
126
124
|
block: JSONBlock;
|
|
127
|
-
}
|
|
125
|
+
}) => Block | null | undefined;
|
|
128
126
|
insertBlockBefore: (payload: {
|
|
129
127
|
block: JSONBlock;
|
|
130
|
-
}
|
|
128
|
+
}) => Block | null | undefined;
|
|
131
129
|
splitBlock: (payload: {
|
|
132
130
|
index: number;
|
|
133
131
|
text: Text;
|
|
134
|
-
}
|
|
135
|
-
duplicateBlock: (
|
|
132
|
+
}) => Block | null | undefined;
|
|
133
|
+
duplicateBlock: (payload?: {} | undefined) => Block | null | undefined;
|
|
136
134
|
removeBlock: (payload?: {
|
|
137
135
|
keepChildren?: boolean;
|
|
138
|
-
} | undefined
|
|
139
|
-
unNestBlock: (this: Block,
|
|
140
|
-
mergeBlockBackward: (
|
|
141
|
-
mergeBlockForward: (
|
|
142
|
-
nestBlock: (this: Block,
|
|
136
|
+
} | undefined) => void;
|
|
137
|
+
unNestBlock: (this: Block, payload?: {} | undefined) => Block | null;
|
|
138
|
+
mergeBlockBackward: (payload?: {} | undefined) => Block | null | undefined;
|
|
139
|
+
mergeBlockForward: (payload?: {} | undefined) => Block | null | undefined;
|
|
140
|
+
nestBlock: (this: Block, payload?: {} | undefined) => Block | null;
|
|
143
141
|
setBlock: (payload: {
|
|
144
142
|
value: Partial<JSONBlock>;
|
|
145
|
-
}
|
|
143
|
+
}) => void;
|
|
146
144
|
moveBlock: (this: Block, payload: {
|
|
147
145
|
path: number[];
|
|
148
146
|
beside?: import("./block.utils.js").BlockBeside;
|
|
149
|
-
}
|
|
147
|
+
}) => Block | null;
|
|
150
148
|
moveBlocks: (this: Block, payload: {
|
|
151
149
|
blocks: Block[];
|
|
152
150
|
path: number[];
|
|
153
151
|
beside?: import("./block.utils.js").BlockBeside;
|
|
154
|
-
}
|
|
155
|
-
pushContentIntoBlock: (
|
|
152
|
+
}) => Block[];
|
|
153
|
+
pushContentIntoBlock: (payload: {
|
|
156
154
|
value: (Text | InlineBlock)[];
|
|
157
155
|
}) => void;
|
|
158
156
|
removeInlineBlock: (payload: {
|
|
159
157
|
index: number;
|
|
160
|
-
}
|
|
158
|
+
}) => void;
|
|
161
159
|
patchData: (payload: {
|
|
162
160
|
ops: import("../crdt/index.js").DataPatch[];
|
|
163
161
|
atom?: string;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
}) => void;
|
|
163
|
+
/**
|
|
164
|
+
* Insert an inline atom: at `offset` of the block's content (block
|
|
165
|
+
* offsets, an inline atom counting 1; a caret's), or at `index` of the
|
|
166
|
+
* text segment `text`. One `addInlineBlock` operation (its payload names
|
|
167
|
+
* the segment). Answers the text segment right after the atom, where a
|
|
168
|
+
* caret goes (`null` when it was not written, `undefined` when refused).
|
|
169
|
+
*/
|
|
170
|
+
addInlineBlock: (payload: BlockOperations["addInlineBlock"] | {
|
|
171
|
+
offset: number;
|
|
167
172
|
block: JSONInlineBlock;
|
|
168
|
-
text: Text;
|
|
169
173
|
}) => Text | null | undefined;
|
|
170
174
|
normalizeContent: () => void;
|
|
171
175
|
normalizeChildren: () => void;
|
|
@@ -176,7 +180,7 @@ export declare class Block {
|
|
|
176
180
|
deleteContentAtRange: (payload: {
|
|
177
181
|
start: [number, number];
|
|
178
182
|
end: [number, number];
|
|
179
|
-
}
|
|
183
|
+
}) => void;
|
|
180
184
|
/** Mark an element inside the block's markup as non-editable chrome (a header, a caption bar). */
|
|
181
185
|
void: (node: HTMLElement) => void;
|
|
182
186
|
/**
|
|
@@ -201,12 +205,4 @@ export declare class Block {
|
|
|
201
205
|
* each entry is a text's runs or an atom, as JSON.
|
|
202
206
|
*/
|
|
203
207
|
insertParts: (index: number, parts: (JSONText[] | JSONInlineBlock)[]) => void;
|
|
204
|
-
/**
|
|
205
|
-
* Register the element the core rendered for this block (O45) and run the
|
|
206
|
-
* attach hooks. A re-rendered block (moved, re-parented) keeps its declared
|
|
207
|
-
* view state (R11): an open toggle stays open.
|
|
208
|
-
*/
|
|
209
|
-
attach: (node: HTMLElement) => {
|
|
210
|
-
destroy: () => void;
|
|
211
|
-
};
|
|
212
208
|
}
|
|
@@ -94,7 +94,7 @@ export class Block {
|
|
|
94
94
|
get focused() {
|
|
95
95
|
return this.edytor.selection.focusedBlocks.has(this) && !this.selected;
|
|
96
96
|
}
|
|
97
|
-
/** May this block move at all
|
|
97
|
+
/** May this block move at all: `canPlace` without a destination (drag handles). */
|
|
98
98
|
get movable() {
|
|
99
99
|
return this.edytor.facade.canPlace([this.id]);
|
|
100
100
|
}
|
|
@@ -102,14 +102,15 @@ export class Block {
|
|
|
102
102
|
* May text-level structural commands (convert, markdown shortcut, slash
|
|
103
103
|
* menu) apply: the block is movable — or the virtual paragraph of an
|
|
104
104
|
* emptied document, which a conversion creates with its kind
|
|
105
|
-
*
|
|
106
|
-
* a container (a list) is never converted, its items are
|
|
105
|
+
* — has no role of its own and renders its own content —
|
|
106
|
+
* a container (a list) is never converted, its items are.
|
|
107
107
|
*/
|
|
108
108
|
get convertible() {
|
|
109
109
|
const { facade } = this.edytor;
|
|
110
110
|
const placeable = this.movable || facade.virtual() === this.id;
|
|
111
111
|
return placeable && this.rendersContent && !facade.isVoid(this.id) && !facade.isIsland(this.id);
|
|
112
112
|
}
|
|
113
|
+
/** @internal */
|
|
113
114
|
get firstEditableText() {
|
|
114
115
|
// Only a RENDERED text part is editable — a container's phantom
|
|
115
116
|
// content slot holds a Text with no `node`. Scan ALL children: the
|
|
@@ -125,6 +126,7 @@ export class Block {
|
|
|
125
126
|
}
|
|
126
127
|
return undefined;
|
|
127
128
|
}
|
|
129
|
+
/** @internal */
|
|
128
130
|
get lastEditableText() {
|
|
129
131
|
const own = this.content.findLast((part) => part instanceof Text && part.node != null);
|
|
130
132
|
if (own)
|
|
@@ -207,7 +209,7 @@ export class Block {
|
|
|
207
209
|
get isNested() {
|
|
208
210
|
return (this.parent && this.parent.type !== 'root') || false;
|
|
209
211
|
}
|
|
210
|
-
/** This block's JSON — the document's one serializer (`facade.blockJSON
|
|
212
|
+
/** This block's JSON — the document's one serializer (`facade.blockJSON`). */
|
|
211
213
|
get value() {
|
|
212
214
|
if (!this.isRoot)
|
|
213
215
|
return this.edytor.facade.blockJSON(this.id);
|
|
@@ -220,13 +222,13 @@ export class Block {
|
|
|
220
222
|
return true;
|
|
221
223
|
return false;
|
|
222
224
|
}
|
|
223
|
-
/** Whether this kind renders its own content slot — the adopted capability
|
|
225
|
+
/** Whether this kind renders its own content slot — the adopted capability. */
|
|
224
226
|
get rendersContent() {
|
|
225
227
|
return this.edytor.document.rendersContent(this.type);
|
|
226
228
|
}
|
|
227
229
|
/**
|
|
228
230
|
* A container: it shows only its children (a list), neither void nor an
|
|
229
|
-
* island — the document's container rule
|
|
231
|
+
* island — the document's container rule. Its items hold what it
|
|
230
232
|
* shows; it is never converted (`convertible`).
|
|
231
233
|
*/
|
|
232
234
|
get isContainer() {
|
|
@@ -249,7 +251,7 @@ export class Block {
|
|
|
249
251
|
/**
|
|
250
252
|
* The list this block shows in: its container when it is an item
|
|
251
253
|
* (`isListItem`), or — an item outdented out of a nested list into the
|
|
252
|
-
* item holding it
|
|
254
|
+
* item holding it — the list of the items of its kind it
|
|
253
255
|
* sits under. <kbd>Enter</kbd> in an empty one outdents it; the menus
|
|
254
256
|
* name it by the list's `itemKind`.
|
|
255
257
|
*/
|
|
@@ -292,7 +294,20 @@ export class Block {
|
|
|
292
294
|
pushContentIntoBlock = batch('pushContentIntoBlock', pushContentIntoBlock);
|
|
293
295
|
removeInlineBlock = batch('removeInlineBlock', removeInlineBlock, prepareRemoveInline);
|
|
294
296
|
patchData = batch('patchData', patchData, preparePatch);
|
|
295
|
-
|
|
297
|
+
#addInline = batch('addInlineBlock', addInlineBlock, undefined, textAfterAtom);
|
|
298
|
+
/**
|
|
299
|
+
* Insert an inline atom: at `offset` of the block's content (block
|
|
300
|
+
* offsets, an inline atom counting 1; a caret's), or at `index` of the
|
|
301
|
+
* text segment `text`. One `addInlineBlock` operation (its payload names
|
|
302
|
+
* the segment). Answers the text segment right after the atom, where a
|
|
303
|
+
* caret goes (`null` when it was not written, `undefined` when refused).
|
|
304
|
+
*/
|
|
305
|
+
addInlineBlock = (payload) => {
|
|
306
|
+
if (!('offset' in payload))
|
|
307
|
+
return this.#addInline(payload);
|
|
308
|
+
const at = this.textAtOffset(Math.max(0, payload.offset));
|
|
309
|
+
return at ? this.#addInline({ index: at.offset, text: at.text, block: payload.block }) : null;
|
|
310
|
+
};
|
|
296
311
|
normalizeContent = batch('normalizeContent', normalizeContent);
|
|
297
312
|
normalizeChildren = batch('normalizeChildren', normalizeChildren);
|
|
298
313
|
/** @deprecated `edytor.suggestions.add({ end: block.id }, …)`. */
|
|
@@ -373,6 +388,7 @@ export class Block {
|
|
|
373
388
|
* Register the element the core rendered for this block (O45) and run the
|
|
374
389
|
* attach hooks. A re-rendered block (moved, re-parented) keeps its declared
|
|
375
390
|
* view state (R11): an open toggle stays open.
|
|
391
|
+
* @internal
|
|
376
392
|
*/
|
|
377
393
|
attach = (node) => {
|
|
378
394
|
const names = this.definition.viewState ?? [];
|
|
@@ -122,6 +122,19 @@ export type BlockOperations = {
|
|
|
122
122
|
content: readonly JSONBlock[];
|
|
123
123
|
};
|
|
124
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* Find and replace (`plugins/find`): each match's text replaced by
|
|
127
|
+
* `replacement`, one plan, one undo step (its steps: a
|
|
128
|
+
* `deleteContentAtRange` and an `insertText` per match).
|
|
129
|
+
*/
|
|
130
|
+
replaceMatches: {
|
|
131
|
+
matches: {
|
|
132
|
+
block: string;
|
|
133
|
+
offset: number;
|
|
134
|
+
length: number;
|
|
135
|
+
}[];
|
|
136
|
+
replacement: string;
|
|
137
|
+
};
|
|
125
138
|
deleteContentAtRange: {
|
|
126
139
|
start: [number, number];
|
|
127
140
|
end: [number, number];
|
|
@@ -153,7 +166,12 @@ export type BlockOperations = {
|
|
|
153
166
|
* and answers the op's document result; `resolve` turns it into wrappers
|
|
154
167
|
* after the commit patched them.
|
|
155
168
|
*/
|
|
156
|
-
export declare function batch<T extends (...args: any[]) => any, O extends keyof BlockOperations, R = ReturnType<T>>(operation: O, func: T, prepare?: (payload: BlockOperations[O]) => Prepared, resolve?: (this: any, out: ReturnType<T> | undefined, payload: Parameters<T>[0]) => R): (...args: Parameters<T
|
|
169
|
+
export declare function batch<T extends (...args: any[]) => any, O extends keyof BlockOperations, R = ReturnType<T>>(operation: O, func: T, prepare?: (payload: BlockOperations[O]) => Prepared, resolve?: (this: any, out: ReturnType<T> | undefined, payload: Parameters<T>[0]) => R): (...args: PayloadOf<Parameters<T>>) => R;
|
|
170
|
+
/**
|
|
171
|
+
* A mutator's public parameters: its payload alone (optional when the op's
|
|
172
|
+
* is). The plan the dispatcher passes the op is not the caller's.
|
|
173
|
+
*/
|
|
174
|
+
export type PayloadOf<A extends unknown[]> = A extends [] ? [] : A extends [infer P, ...unknown[]] ? [payload: P] : A extends [(infer P)?, ...unknown[]] ? [payload?: P] : [];
|
|
157
175
|
/**
|
|
158
176
|
* The handle of block `id` (null: refused at preparation, or gone; undefined:
|
|
159
177
|
* the command did not run). Inside an outer transaction too: the index shows
|
|
@@ -12,7 +12,8 @@ import { InlineBlock } from './inlineBlock.svelte.js';
|
|
|
12
12
|
export function batch(operation, func, prepare, resolve) {
|
|
13
13
|
return function (...[payload]) {
|
|
14
14
|
const out = this.edytor.dispatcher.dispatch(operation, payload, { block: this }, (p, plan) => func.call(this, p, plan), prepare && ((p) => prepare.call(this, p)));
|
|
15
|
-
|
|
15
|
+
const value = resolve ? resolve.call(this, out, payload) : out;
|
|
16
|
+
return this.edytor.dispatcher.answer(value);
|
|
16
17
|
};
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
@@ -0,0 +1,47 @@
|
|
|
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;
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
};
|
|
@@ -3,7 +3,7 @@ import type { InlineBlockDefinition } from '../plugins.js';
|
|
|
3
3
|
import type { JSONInlineBlock } from '../utils/json.js';
|
|
4
4
|
import type { Block } from './block.svelte.js';
|
|
5
5
|
/**
|
|
6
|
-
* An id-only inline-atom handle
|
|
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
8
|
* that renders it (a Surface fact).
|
|
9
9
|
*/
|
|
@@ -31,7 +31,4 @@ export declare class InlineBlock {
|
|
|
31
31
|
/** The atom is shown by a live block. */
|
|
32
32
|
get isInDocument(): boolean;
|
|
33
33
|
get value(): JSONInlineBlock;
|
|
34
|
-
attach: (node: HTMLElement) => {
|
|
35
|
-
destroy: () => void;
|
|
36
|
-
};
|
|
37
34
|
}
|
|
@@ -3,7 +3,7 @@ import { propsProxy } from '../session/props.js';
|
|
|
3
3
|
const INLINE_EDGE_CARET_THRESHOLD_PX = 4;
|
|
4
4
|
const isTextPart = (part) => part !== undefined && !(part instanceof InlineBlock);
|
|
5
5
|
/**
|
|
6
|
-
* An id-only inline-atom handle
|
|
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
8
|
* that renders it (a Surface fact).
|
|
9
9
|
*/
|
|
@@ -61,6 +61,7 @@ export class InlineBlock {
|
|
|
61
61
|
get value() {
|
|
62
62
|
return { id: this.id, type: this.type, data: { ...this.#item?.data } };
|
|
63
63
|
}
|
|
64
|
+
/** @internal */
|
|
64
65
|
attach = (node) => {
|
|
65
66
|
node.setAttribute('contenteditable', 'false');
|
|
66
67
|
node.dataset.edytorId = this.id;
|
|
@@ -15,8 +15,10 @@ export declare const tagOf: (type: string, kind: BlockDefinition, data: Values)
|
|
|
15
15
|
* catalogue kind's tag per preset (a content-less container takes its
|
|
16
16
|
* default child's tag, one child per text line), a value-less mark's
|
|
17
17
|
* `tag`, and each record's `parse` hook first (aliases, sanitized values).
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* A void kind with a `parse` hook (an image, an embed, a video) is found
|
|
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. Unknown
|
|
21
|
+
* elements degrade to text runs; whitespace collapses as HTML renders it. `null` when the HTML carries nothing (`flow.shape`, F-P10).
|
|
20
22
|
*/
|
|
21
23
|
export declare const flowOfHtml: (kinds: ImportKinds, html: string | undefined) => Flow | null;
|
|
22
24
|
export {};
|