edytor 2.0.0 → 4.0.0
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 +19 -4
- package/dist/block/block.svelte.js +2 -4
- package/dist/clipboard/htmlFlow.d.ts +20 -7
- package/dist/clipboard/htmlFlow.js +23 -15
- package/dist/clipboard/serializeClipboardFragment.d.ts +37 -4
- package/dist/clipboard/serializeClipboardFragment.js +6 -4
- package/dist/clipboard/textBlocks.d.ts +8 -0
- package/dist/clipboard/textBlocks.js +6 -2
- package/dist/cloudflare/DocumentRoom.d.ts +13 -9
- package/dist/cloudflare/DocumentRoom.js +10 -6
- package/dist/cloudflare/room/admission.js +3 -3
- package/dist/cloudflare/room/context.d.ts +28 -27
- package/dist/cloudflare/room/context.js +2 -2
- package/dist/cloudflare/room/purge.d.ts +6 -3
- package/dist/cloudflare/room/purge.js +44 -19
- package/dist/cloudflare/room/updates.d.ts +3 -4
- package/dist/cloudflare/room/updates.js +6 -8
- package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
- package/dist/cloudflare/routeDocumentSocket.js +53 -0
- package/dist/collaboration/comments/client.d.ts +1 -1
- package/dist/collaboration/comments/client.js +1 -1
- package/dist/collaboration/remoteSelection.js +3 -3
- package/dist/components/Edytor.svelte +2 -10
- package/dist/components/Edytor.svelte.d.ts +1 -3
- package/dist/crdt/admission.d.ts +5 -10
- package/dist/crdt/admission.js +5 -11
- package/dist/crdt/attribution/attribution.d.ts +31 -12
- package/dist/crdt/attribution/attribution.js +56 -18
- package/dist/crdt/attribution/block.d.ts +3 -3
- package/dist/crdt/attribution/block.js +7 -8
- package/dist/crdt/attribution/index.d.ts +1 -1
- package/dist/crdt/attribution/index.js +1 -1
- package/dist/crdt/data.d.ts +62 -31
- package/dist/crdt/data.js +211 -103
- package/dist/crdt/doc/delete.d.ts +1 -1
- package/dist/crdt/doc/delete.js +13 -30
- package/dist/crdt/doc/funnel.d.ts +7 -6
- package/dist/crdt/doc/funnel.js +39 -33
- package/dist/crdt/doc/gate.d.ts +3 -20
- package/dist/crdt/doc/gate.js +2 -41
- package/dist/crdt/doc/history.d.ts +25 -9
- package/dist/crdt/doc/history.js +152 -42
- package/dist/crdt/doc/layout.js +11 -22
- package/dist/crdt/doc/meta.js +12 -17
- package/dist/crdt/doc/moves.d.ts +1 -1
- package/dist/crdt/doc/moves.js +52 -32
- package/dist/crdt/doc/reads.js +2 -2
- package/dist/crdt/doc/seed.js +2 -2
- package/dist/crdt/doc/split-merge.js +12 -15
- package/dist/crdt/doc/steps.d.ts +25 -13
- package/dist/crdt/doc/steps.js +52 -122
- package/dist/crdt/doc/types.d.ts +21 -9
- package/dist/crdt/document.d.ts +21 -19
- package/dist/crdt/document.js +26 -23
- package/dist/crdt/edytor-doc.d.ts +66 -68
- package/dist/crdt/edytor-doc.js +21 -20
- package/dist/crdt/engine-api.d.ts +33 -1
- package/dist/crdt/engine.d.ts +0 -1
- package/dist/crdt/engine.js +1 -4
- package/dist/crdt/flow.d.ts +1 -1
- package/dist/crdt/flow.js +25 -27
- package/dist/crdt/index.d.ts +29 -28
- package/dist/crdt/index.js +3 -3
- package/dist/crdt/placement/display.d.ts +5 -30
- package/dist/crdt/placement/display.js +39 -144
- package/dist/crdt/placement/keys.d.ts +58 -0
- package/dist/crdt/placement/keys.js +90 -0
- package/dist/crdt/placement/model.d.ts +119 -118
- package/dist/crdt/placement/model.js +242 -142
- package/dist/crdt/placement/resolve.d.ts +123 -35
- package/dist/crdt/placement/resolve.js +187 -153
- package/dist/crdt/placement/slots.d.ts +134 -0
- package/dist/crdt/placement/slots.js +152 -0
- package/dist/crdt/protocol.d.ts +2 -2
- package/dist/crdt/protocol.js +2 -2
- package/dist/crdt/providers/index.d.ts +1 -1
- package/dist/crdt/providers/room.d.ts +26 -11
- package/dist/crdt/providers/room.js +77 -27
- package/dist/crdt/providers/websocket.d.ts +1 -1
- package/dist/crdt/providers/websocket.js +33 -32
- package/dist/crdt/purge.d.ts +17 -8
- package/dist/crdt/purge.js +236 -126
- package/dist/crdt/restore.d.ts +2 -2
- package/dist/crdt/restore.js +18 -34
- package/dist/crdt/schema.d.ts +22 -21
- package/dist/crdt/schema.js +29 -23
- package/dist/crdt/semantics.js +3 -1
- package/dist/crdt/storage.d.ts +1 -1
- package/dist/crdt/storage.js +1 -1
- package/dist/crdt/structs.d.ts +15 -15
- package/dist/crdt/structs.js +8 -22
- package/dist/crdt/text/index/cache.js +4 -0
- package/dist/crdt/text/index/claims.js +12 -0
- package/dist/crdt/text/index/fold.d.ts +2 -3
- package/dist/crdt/text/index/fold.js +194 -44
- package/dist/crdt/text/index/layout.js +5 -8
- package/dist/crdt/text/index/placement.d.ts +26 -18
- package/dist/crdt/text/index/placement.js +404 -138
- package/dist/crdt/text/index/records.d.ts +3 -3
- package/dist/crdt/text/index/records.js +24 -31
- package/dist/crdt/text/index/shared.d.ts +11 -3
- package/dist/crdt/text/index/shared.js +12 -3
- package/dist/crdt/text/index/state.d.ts +21 -17
- package/dist/crdt/text/index/state.js +15 -17
- package/dist/crdt/text/index/streams.d.ts +10 -5
- package/dist/crdt/text/index/streams.js +78 -27
- package/dist/crdt/text/items.d.ts +10 -3
- package/dist/crdt/text/items.js +7 -0
- package/dist/crdt/text/model.d.ts +77 -62
- package/dist/crdt/text/model.js +84 -169
- package/dist/crdt/text/ranges.d.ts +1 -1
- package/dist/crdt/text/ranges.js +3 -3
- package/dist/crdt/text/rows.d.ts +13 -7
- package/dist/crdt/text/rows.js +24 -7
- package/dist/crdt/text/runs.d.ts +17 -12
- package/dist/crdt/text/runs.js +24 -7
- package/dist/crdt/text/streams.d.ts +26 -13
- package/dist/crdt/text/streams.js +41 -14
- package/dist/crdt/vendor/yjs/UPSTREAM.md +568 -21
- package/dist/crdt/vendor/yjs/dts/global.d.ts +2 -0
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +7 -0
- package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +194 -10
- package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +6 -3
- package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +5 -18
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +15 -1
- package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +14 -6
- package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +33 -6
- package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +1 -65
- package/dist/crdt/vendor/yjs/dts/utils/marks.d.ts +6 -1
- package/dist/crdt/vendor/yjs/dts/ynode.d.ts +43 -7
- package/dist/crdt/vendor/yjs/global.d.ts +2 -0
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +10 -0
- package/dist/crdt/vendor/yjs/src/structs/Item.js +610 -51
- package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +18 -9
- package/dist/crdt/vendor/yjs/src/utils/Doc.js +5 -3
- package/dist/crdt/vendor/yjs/src/utils/StructStore.js +5 -0
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +36 -13
- package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +88 -18
- package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +119 -32
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +13 -1
- package/dist/crdt/vendor/yjs/src/utils/ids.js +7 -7
- package/dist/crdt/vendor/yjs/src/utils/marks.js +193 -8
- package/dist/crdt/vendor/yjs/src/utils/redo.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/updates.js +3 -3
- package/dist/crdt/vendor/yjs/src/ynode.js +177 -12
- package/dist/dnd/autoScroll.d.ts +15 -7
- package/dist/dnd/autoScroll.js +10 -15
- package/dist/dnd/dropIndicator.js +2 -5
- package/dist/dnd/external.d.ts +6 -0
- package/dist/dnd/external.js +17 -0
- package/dist/dnd/geometry.d.ts +2 -0
- package/dist/dnd/geometry.js +3 -4
- package/dist/dnd/placement.d.ts +1 -1
- package/dist/dnd/pragmatic.d.ts +3 -1
- package/dist/dnd/pragmatic.js +12 -2
- package/dist/dnd/vendor/pragmatic/UPSTREAM.md +51 -18
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +0 -2
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +4 -22
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter-types.d.ts +26 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.d.ts +30 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.js +203 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-items.js +13 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-types.js +9 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/is-an-available-type.js +19 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +4 -16
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +1 -8
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +5 -6
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +2 -3
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.d.ts +1 -1
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +6 -24
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.d.ts +2 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js +5 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.d.ts +3 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js +12 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/native-types.d.ts +12 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window-in-safari.js +10 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window.js +55 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js +8 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +0 -4
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +16 -72
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +1 -9
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +4 -29
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +2 -3
- package/dist/edytor.svelte.d.ts +2 -5
- package/dist/edytor.svelte.js +21 -32
- package/dist/events/beforeInputCommands.js +2 -2
- package/dist/events/onBeforeInput.js +1 -1
- package/dist/events/onDrop.d.ts +0 -6
- package/dist/events/onDrop.js +10 -23
- package/dist/events/onInput.d.ts +0 -12
- package/dist/events/onInput.js +1 -67
- package/dist/events/onPageHide.d.ts +3 -0
- package/dist/events/onPageHide.js +16 -0
- package/dist/export/forms.d.ts +627 -0
- package/dist/export/forms.js +749 -0
- package/dist/export/index.d.ts +170 -0
- package/dist/export/index.js +161 -0
- package/dist/export/markdown.d.ts +41 -0
- package/dist/export/markdown.js +585 -0
- package/dist/export/markdownWriter.d.ts +9 -0
- package/dist/export/markdownWriter.js +133 -0
- package/dist/export/mdx.d.ts +15 -0
- package/dist/export/mdx.js +33 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/kinds.js +1 -1
- package/dist/plugins/anchored.svelte.d.ts +21 -25
- package/dist/plugins/anchored.svelte.js +23 -39
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +24 -32
- package/dist/plugins/blockHandles/dragPreview.d.ts +26 -7
- package/dist/plugins/blockHandles/dragPreview.js +33 -0
- package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +5 -0
- package/dist/plugins/blockMenu/BlockMenuController.svelte.js +7 -2
- package/dist/plugins/blockMenu/blockMenuPlugin.js +5 -50
- package/dist/plugins/chrome.d.ts +27 -5
- package/dist/plugins/chrome.js +24 -9
- package/dist/plugins/code/CodePlugin.svelte +12 -9
- package/dist/plugins/code/header.svelte.js +7 -11
- package/dist/plugins/code/languageMenu.svelte.d.ts +5 -2
- package/dist/plugins/code/languageMenu.svelte.js +13 -20
- package/dist/plugins/columns/ColumnsPlugin.svelte +7 -20
- package/dist/plugins/columns/resize.svelte.d.ts +2 -3
- package/dist/plugins/columns/resize.svelte.js +2 -5
- package/dist/plugins/comments/CommentsController.svelte.d.ts +6 -0
- package/dist/plugins/comments/CommentsController.svelte.js +20 -0
- package/dist/plugins/equation/EquationPlugin.svelte +12 -22
- package/dist/plugins/equation/equation.svelte.d.ts +7 -15
- package/dist/plugins/equation/equation.svelte.js +13 -50
- package/dist/plugins/equation/tex.d.ts +17 -0
- package/dist/plugins/equation/tex.js +42 -0
- package/dist/plugins/fileDrop.d.ts +38 -23
- package/dist/plugins/fileDrop.js +82 -76
- package/dist/plugins/find/FindController.svelte.d.ts +5 -0
- package/dist/plugins/find/FindController.svelte.js +14 -14
- package/dist/plugins/find/findPlugin.js +1 -15
- package/dist/plugins/image/ImageChrome.svelte +8 -2
- package/dist/plugins/image/ImagePlugin.svelte +15 -52
- package/dist/plugins/image/controls.svelte.js +16 -2
- package/dist/plugins/image/toolbar.svelte.d.ts +5 -4
- package/dist/plugins/image/toolbar.svelte.js +21 -31
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/list.svelte.d.ts +9 -0
- package/dist/plugins/list.svelte.js +18 -0
- package/dist/plugins/marquee/marqueePlugin.js +0 -4
- package/dist/plugins/media/AudioPlugin.svelte +1 -1
- package/dist/plugins/media/BookmarkPlugin.svelte +6 -97
- package/dist/plugins/media/EmbedPlugin.svelte +5 -90
- package/dist/plugins/media/EmptySlot.svelte +36 -20
- package/dist/plugins/media/EmptySlot.svelte.d.ts +6 -15
- package/dist/plugins/media/FilePlugin.svelte +1 -19
- package/dist/plugins/media/MediaEmpty.svelte +2 -55
- package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
- package/dist/plugins/media/SourceBlock.svelte +142 -52
- package/dist/plugins/media/SourceBlock.svelte.d.ts +10 -4
- package/dist/plugins/media/VideoPlugin.svelte +1 -1
- package/dist/plugins/media/empty.svelte.js +2 -7
- package/dist/plugins/media/media.d.ts +2 -63
- package/dist/plugins/media/media.js +1 -194
- package/dist/plugins/media/sources.d.ts +60 -0
- package/dist/plugins/media/sources.js +165 -0
- package/dist/plugins/media/urlPaste.svelte.d.ts +2 -1
- package/dist/plugins/media/urlPaste.svelte.js +12 -21
- package/dist/plugins/mention/MentionPlugin.svelte +8 -35
- package/dist/plugins/page/PagePlugin.svelte +2 -9
- package/dist/plugins/page/page.js +1 -1
- package/dist/plugins/pageLink/PageLinkPlugin.svelte +6 -13
- package/dist/plugins/richtext/RichTextPlugin.svelte +85 -197
- package/dist/plugins/richtext/body.js +1 -1
- package/dist/plugins/richtext/calloutIcons.svelte.d.ts +2 -2
- package/dist/plugins/richtext/calloutIcons.svelte.js +5 -7
- package/dist/plugins/richtext/richTextOperations.d.ts +1 -19
- package/dist/plugins/richtext/richTextOperations.js +3 -49
- package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -0
- package/dist/plugins/slashMenu/SlashMenuController.svelte.js +7 -0
- package/dist/plugins/slashMenu/slashMenuPlugin.js +5 -14
- package/dist/plugins/table/TableChrome.svelte +2 -3
- package/dist/plugins/table/TablePlugin.svelte +20 -54
- package/dist/plugins/table/chrome.svelte.d.ts +5 -2
- package/dist/plugins/table/chrome.svelte.js +30 -54
- package/dist/plugins/table/table.js +3 -3
- package/dist/plugins/toc/TocPlugin.svelte +2 -4
- package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +7 -0
- package/dist/plugins/toolbar/ToolbarController.svelte.js +20 -13
- package/dist/plugins/toolbar/toolbarPlugin.js +19 -53
- package/dist/plugins/triggers/TriggerController.svelte.d.ts +7 -2
- package/dist/plugins/triggers/TriggerController.svelte.js +11 -4
- package/dist/plugins/triggers/place.js +1 -2
- package/dist/plugins/triggers/triggers.d.ts +6 -1
- package/dist/plugins/triggers/triggers.js +12 -13
- package/dist/plugins/uploads.svelte.d.ts +5 -2
- package/dist/plugins/uploads.svelte.js +25 -15
- package/dist/plugins.d.ts +26 -0
- package/dist/plugins.js +0 -24
- package/dist/selection/replaceSelection.js +2 -2
- package/dist/selection/selection.svelte.d.ts +4 -10
- package/dist/selection/selection.svelte.js +7 -11
- package/dist/session/bindings.js +1 -1
- package/dist/session/commands.d.ts +7 -11
- package/dist/session/commands.js +13 -19
- package/dist/session/inputRules.js +1 -1
- package/dist/session/navigation.js +1 -1
- package/dist/session/suggestions.svelte.d.ts +0 -11
- package/dist/session/suggestions.svelte.js +15 -3
- package/dist/session/uploads.d.ts +8 -8
- package/dist/surface/lines.js +1 -3
- package/dist/surface/observer.svelte.d.ts +17 -1
- package/dist/surface/observer.svelte.js +74 -19
- package/dist/surface/overlay.d.ts +0 -14
- package/dist/surface/overlay.js +0 -25
- package/dist/surface/projector.svelte.d.ts +15 -3
- package/dist/surface/projector.svelte.js +60 -9
- package/dist/text/text.svelte.js +3 -13
- package/dist/utils/sanitize.d.ts +38 -0
- package/dist/utils/sanitize.js +82 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +5 -0
- package/package.json +19 -2
- package/dist/crdt/placement/rank.d.ts +0 -87
- package/dist/crdt/placement/rank.js +0 -332
- package/dist/crdt/placement/source.d.ts +0 -43
- package/dist/crdt/placement/source.js +0 -66
- package/dist/crdt/text/delete-index.d.ts +0 -129
- package/dist/crdt/text/delete-index.js +0 -365
- package/dist/crdt/text/deletes.d.ts +0 -76
- package/dist/crdt/text/deletes.js +0 -362
- package/dist/crdt/text/index/anchored.d.ts +0 -17
- package/dist/crdt/text/index/anchored.js +0 -197
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +0 -3
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +0 -16
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +0 -3
- package/dist/plugins/code/LanguageMenu.svelte +0 -25
- package/dist/plugins/code/LanguageMenu.svelte.d.ts +0 -9
- package/dist/plugins/equation/EquationEditor.svelte +0 -27
- package/dist/plugins/equation/EquationEditor.svelte.d.ts +0 -9
- package/dist/plugins/image/ImageToolbarHost.svelte +0 -37
- package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +0 -9
- package/dist/plugins/richtext/CalloutIconPicker.svelte +0 -26
- package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +0 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<svelte:options runes />
|
|
2
2
|
|
|
3
3
|
<script module lang="ts">
|
|
4
|
+
import { pageLinkForms } from '../../export/forms.js';
|
|
4
5
|
import './pageLink.css';
|
|
5
6
|
import type { Snippet } from 'svelte';
|
|
6
7
|
import type {
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
import type { Edytor } from '../../edytor.svelte.js';
|
|
13
14
|
import type { TextAnchor } from '../../selection/selection.svelte.js';
|
|
14
15
|
import type { TriggerMenuController } from '../triggers/TriggerController.svelte.js';
|
|
15
|
-
import { withRulesAndTriggers } from '../triggers/triggers.js';
|
|
16
|
+
import { placeAtom, withRulesAndTriggers } from '../triggers/triggers.js';
|
|
16
17
|
import { pageLinkEnglish, labelsOf } from '../../labels.js';
|
|
17
18
|
import { sanitizeLinkHref } from '../richtext/richTextOperations.js';
|
|
18
19
|
|
|
@@ -150,7 +151,7 @@
|
|
|
150
151
|
prevent(() => {
|
|
151
152
|
edytor.dispatcher.run('insertFromPaste', () => {
|
|
152
153
|
edytor.insertText(text.parent.id, text.segStart + yStart, item);
|
|
153
|
-
edytor.dispatcher.
|
|
154
|
+
edytor.dispatcher.caretIn(text, yStart + item.length);
|
|
154
155
|
});
|
|
155
156
|
if (edytor.dispatcher.last?.status === 'applied')
|
|
156
157
|
swapPasted(edytor, start, item, page, options);
|
|
@@ -175,11 +176,8 @@
|
|
|
175
176
|
: {}),
|
|
176
177
|
inlineBlocks: {
|
|
177
178
|
pageLink: {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const title = (data as Partial<PageLinkData> | undefined)?.title;
|
|
181
|
-
return typeof title === 'string' ? title : '';
|
|
182
|
-
}
|
|
179
|
+
...pageLinkForms(),
|
|
180
|
+
snippet: pageLink
|
|
183
181
|
}
|
|
184
182
|
}
|
|
185
183
|
},
|
|
@@ -191,12 +189,7 @@
|
|
|
191
189
|
label: (page: PageLinkItem) => page.title,
|
|
192
190
|
key: (page: PageLinkItem) => page.id,
|
|
193
191
|
menu: options.menu,
|
|
194
|
-
onPick: (page: PageLinkItem,
|
|
195
|
-
const atom = atomOf(page, options);
|
|
196
|
-
const written = edytor.insertInline(block.id, from, atom).status === 'applied';
|
|
197
|
-
if (written) caret(from + 1);
|
|
198
|
-
return written;
|
|
199
|
-
}
|
|
192
|
+
onPick: (page: PageLinkItem, ctx) => placeAtom(ctx, atomOf(page, options))
|
|
200
193
|
}
|
|
201
194
|
]
|
|
202
195
|
}
|
|
@@ -11,28 +11,44 @@
|
|
|
11
11
|
openLink,
|
|
12
12
|
pastedLink,
|
|
13
13
|
richTextOperations,
|
|
14
|
-
sanitizeLinkHref,
|
|
15
|
-
sanitizeCssColorValue,
|
|
16
14
|
typedLink,
|
|
17
15
|
type RichTextMark
|
|
18
16
|
} from './richTextOperations.js';
|
|
19
17
|
import { marksForInsertion } from '../../session/editing/text.js';
|
|
20
18
|
import { firstUriListEntry } from '../../events/dataTransferPayload.js';
|
|
21
19
|
import { flipToggles, shownSelectionBlocks } from '../../selection/replaceSelection.js';
|
|
22
|
-
import { mediaKinds, richTextKinds
|
|
20
|
+
import { mediaKinds, richTextKinds } from '../../crdt/semantics.js';
|
|
23
21
|
import { richTextEnglish, keywordsOf, labelsOf, type RichTextLabels } from '../../labels.js';
|
|
24
22
|
import TodoCheckbox from './TodoCheckbox.svelte';
|
|
25
23
|
import EmptyBody from './EmptyBody.svelte';
|
|
26
24
|
import CalloutIcon from './CalloutIcon.svelte';
|
|
27
25
|
import RichTextControl from './RichTextControl.svelte';
|
|
28
|
-
import {
|
|
29
|
-
DEFAULT_CALLOUT_ICON,
|
|
30
|
-
calloutHtml,
|
|
31
|
-
calloutIcons,
|
|
32
|
-
calloutPickers,
|
|
33
|
-
iconOf
|
|
34
|
-
} from './callouts.js';
|
|
26
|
+
import { DEFAULT_CALLOUT_ICON, calloutIcons, calloutPickers, iconOf } from './callouts.js';
|
|
35
27
|
import { listen } from '../../utils/listen.js';
|
|
28
|
+
import {
|
|
29
|
+
HEADING_LEVELS,
|
|
30
|
+
calloutRead,
|
|
31
|
+
calloutWrite,
|
|
32
|
+
dividerRead,
|
|
33
|
+
dividerWrite,
|
|
34
|
+
headingLevel,
|
|
35
|
+
headingRead,
|
|
36
|
+
headingWrite,
|
|
37
|
+
itemRead,
|
|
38
|
+
itemWrite,
|
|
39
|
+
numberedRead,
|
|
40
|
+
orderedRead,
|
|
41
|
+
orderedWrite,
|
|
42
|
+
quoteRead,
|
|
43
|
+
quoteWrite,
|
|
44
|
+
richTextMarkForms,
|
|
45
|
+
todoWrite,
|
|
46
|
+
toggleHeadingRead,
|
|
47
|
+
toggleHeadingWrite,
|
|
48
|
+
toggleRead,
|
|
49
|
+
unorderedRead,
|
|
50
|
+
unorderedWrite
|
|
51
|
+
} from '../../export/forms.js';
|
|
36
52
|
import { onLastLine } from '../../session/navigation.js';
|
|
37
53
|
import { bodyShows } from '../../selection/visibility.js';
|
|
38
54
|
import { openBody } from './body.js';
|
|
@@ -58,62 +74,10 @@
|
|
|
58
74
|
formatSubscript: 'subscript'
|
|
59
75
|
} as const;
|
|
60
76
|
|
|
61
|
-
const isNativeFormatInputType = (
|
|
62
|
-
inputType: string
|
|
63
|
-
): inputType is keyof typeof nativeFormatMarks => inputType in nativeFormatMarks;
|
|
64
|
-
|
|
65
|
-
/** A thematic break's clipboard forms. */
|
|
66
|
-
const rule = { html: () => '<hr>', plain: () => '---' };
|
|
67
77
|
/** A native disclosure: the browser owns `open` (declared view state). */
|
|
68
|
-
const disclosure = {
|
|
78
|
+
const disclosure = { viewState: ['open'] };
|
|
69
79
|
/** The kinds drawn as a disclosure: a toggle this view creates opens (`body.open`). */
|
|
70
80
|
const DISCLOSURES = new Set(['toggle', 'toggle-heading']);
|
|
71
|
-
/**
|
|
72
|
-
* A list's elements without list semantics (`role="none"`): a list's items
|
|
73
|
-
* are sibling blocks, never the only children of one `ul` or `ol`, so an
|
|
74
|
-
* `li` would be an orphan list item to assistive technology (WCAG 1.3.1);
|
|
75
|
-
* the tags stay for styles and the HTML export.
|
|
76
|
-
*/
|
|
77
|
-
const unlisted = (tag: 'li' | 'ul' | 'ol') => ({ tag, attributes: { role: 'none' } });
|
|
78
|
-
/**
|
|
79
|
-
* Notion's three heading levels: a missing level is h1, any other (a
|
|
80
|
-
* stored `h4`–`h6`, as HTML import reads them) h3.
|
|
81
|
-
*/
|
|
82
|
-
const headingLevel = (level: unknown) =>
|
|
83
|
-
level === 'h1' || level === 'h2' || level === 'h3' ? level : level === undefined ? 'h1' : 'h3';
|
|
84
|
-
/** An unsafe scheme drops the href (and its target): an inert anchor still carries the text. */
|
|
85
|
-
const linkAttributes = (mark: { href?: unknown; target?: string }) => {
|
|
86
|
-
const href = sanitizeLinkHref(mark?.href) ?? undefined;
|
|
87
|
-
return { href, target: href && mark.target };
|
|
88
|
-
};
|
|
89
|
-
/** A hostile color value (a `;` payload would inject declarations) drops the style. */
|
|
90
|
-
const styled = (property: string) => (value: unknown) => {
|
|
91
|
-
const safe = sanitizeCssColorValue(value);
|
|
92
|
-
return { style: safe ? `${property}: ${safe};` : undefined };
|
|
93
|
-
};
|
|
94
|
-
/**
|
|
95
|
-
* HTML import: a pasted color, sanitized, unless it is the page's
|
|
96
|
-
* default (Google Docs writes black text and transparent backgrounds on
|
|
97
|
-
* every span: they are no mark, and a black mark is unreadable in dark mode).
|
|
98
|
-
*/
|
|
99
|
-
const colorOf = (value: string, none: RegExp) =>
|
|
100
|
-
none.test(value.replace(/\s+/g, '').toLowerCase())
|
|
101
|
-
? undefined
|
|
102
|
-
: (sanitizeCssColorValue(value) ?? undefined);
|
|
103
|
-
const INHERITED = 'initial|inherit|unset|revert|currentcolor';
|
|
104
|
-
const NO_COLOR = new RegExp(
|
|
105
|
-
`^(${INHERITED}|black|windowtext|#000|#000000|rgba?\\(0,0,0(,1)?\\))$`
|
|
106
|
-
);
|
|
107
|
-
const NO_HIGHLIGHT = new RegExp(
|
|
108
|
-
`^(${INHERITED}|transparent|rgba\\(\\d+,\\d+,\\d+,0\\)|white|#fff|#ffffff|rgba?\\(255,255,255(,1)?\\))$`
|
|
109
|
-
);
|
|
110
|
-
/** HTML import: a tag alias (unless its own style says otherwise) or a style (Google Docs). */
|
|
111
|
-
const alias =
|
|
112
|
-
(tags: RegExp, property: 'fontWeight' | 'fontStyle' | 'textDecoration', value: RegExp) =>
|
|
113
|
-
(el: HTMLElement) =>
|
|
114
|
-
(tags.test(el.localName) && !el.style[property]) ||
|
|
115
|
-
value.test(el.style[property]) ||
|
|
116
|
-
undefined;
|
|
117
81
|
|
|
118
82
|
/**
|
|
119
83
|
* The kinds whose empty text names them, by placeholder (a callout's
|
|
@@ -220,6 +184,7 @@
|
|
|
220
184
|
{ callout: calloutOptions, checkbox, calloutIcon, emptyBody }: RichTextPluginOptions
|
|
221
185
|
): ReturnType<Plugin> => {
|
|
222
186
|
const { kinds, marks: words } = labels;
|
|
187
|
+
const marks = richTextMarkForms;
|
|
223
188
|
/** A new callout's icon. */
|
|
224
189
|
const icon = calloutOptions?.icon ?? DEFAULT_CALLOUT_ICON;
|
|
225
190
|
/** The block this view is retyping into a disclosure (`body.open`), until it applied. */
|
|
@@ -317,7 +282,7 @@
|
|
|
317
282
|
const end = yStart + href.length;
|
|
318
283
|
edytor.dispatcher.run('insertFromPaste', () => {
|
|
319
284
|
edytor.insertText(text.parent.id, text.segStart + yStart, href);
|
|
320
|
-
edytor.dispatcher.
|
|
285
|
+
edytor.dispatcher.caretIn(text, end);
|
|
321
286
|
});
|
|
322
287
|
if (text.stringContent.slice(yStart, end) === href)
|
|
323
288
|
operations.linkText(text, yStart, end, href);
|
|
@@ -360,7 +325,7 @@
|
|
|
360
325
|
} finally {
|
|
361
326
|
autolinking = false;
|
|
362
327
|
}
|
|
363
|
-
edytor.dispatcher.
|
|
328
|
+
edytor.dispatcher.caretIn(text, yStart + 1);
|
|
364
329
|
operations.linkText(text, found.start, end, found.href);
|
|
365
330
|
});
|
|
366
331
|
},
|
|
@@ -392,8 +357,8 @@
|
|
|
392
357
|
},
|
|
393
358
|
onBeforeInput: ({ e, prevent }) => {
|
|
394
359
|
const { inputType, data } = e;
|
|
395
|
-
if (
|
|
396
|
-
const mark = nativeFormatMarks[inputType];
|
|
360
|
+
if (inputType in nativeFormatMarks) {
|
|
361
|
+
const mark = nativeFormatMarks[inputType as keyof typeof nativeFormatMarks];
|
|
397
362
|
prevent(() => operations.setMarkAtRange(mark));
|
|
398
363
|
} else if (inputType === 'formatRemove') {
|
|
399
364
|
prevent(() => operations.removeAllMarksAtRange());
|
|
@@ -418,54 +383,17 @@
|
|
|
418
383
|
},
|
|
419
384
|
// Toolbar buttons and export wrapping follow this order (first innermost).
|
|
420
385
|
marks: {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
tag: 'u',
|
|
433
|
-
toolbar: { label: words.underline, icon: 'U' },
|
|
434
|
-
parse: alias(/^u$/, 'textDecoration', /underline/)
|
|
435
|
-
},
|
|
436
|
-
strike: {
|
|
437
|
-
tag: 's',
|
|
438
|
-
toolbar: { label: words.strike, icon: 'S' },
|
|
439
|
-
parse: alias(/^(strike|del)$/, 'textDecoration', /line-through/)
|
|
440
|
-
},
|
|
441
|
-
code: { tag: 'code', toolbar: { label: words.code, icon: '</>' } },
|
|
442
|
-
// Typing at a link's trailing edge extends it only from inside the anchor.
|
|
443
|
-
link: {
|
|
444
|
-
tag: 'a',
|
|
445
|
-
attributes: linkAttributes,
|
|
446
|
-
...richTextMarks.link,
|
|
447
|
-
parse: (el) => {
|
|
448
|
-
const href = el.localName === 'a' && sanitizeLinkHref(el.getAttribute('href'));
|
|
449
|
-
const target = el.getAttribute('target');
|
|
450
|
-
return href ? { href, ...(target ? { target } : {}) } : undefined;
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
superscript: { tag: 'sup' },
|
|
454
|
-
subscript: { tag: 'sub' },
|
|
455
|
-
color: {
|
|
456
|
-
tag: 'span',
|
|
457
|
-
attributes: styled('color'),
|
|
458
|
-
parse: (el) => colorOf(el.style.color, NO_COLOR)
|
|
459
|
-
},
|
|
460
|
-
highlight: {
|
|
461
|
-
tag: 'span',
|
|
462
|
-
attributes: styled('background-color'),
|
|
463
|
-
parse: (el) => {
|
|
464
|
-
const background = el.style.backgroundColor;
|
|
465
|
-
if (background) return colorOf(background, NO_HIGHLIGHT);
|
|
466
|
-
return el.localName === 'mark' ? 'yellow' : undefined;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
386
|
+
...marks,
|
|
387
|
+
// The toolbar's marks, by their icons.
|
|
388
|
+
...Object.fromEntries(
|
|
389
|
+
(['bold', 'italic', 'underline', 'strike', 'code'] as const).map((name, i) => [
|
|
390
|
+
name,
|
|
391
|
+
{
|
|
392
|
+
...marks[name],
|
|
393
|
+
toolbar: { label: words[name], icon: ['B', 'I', 'U', 'S', '</>'][i]! }
|
|
394
|
+
}
|
|
395
|
+
])
|
|
396
|
+
)
|
|
469
397
|
},
|
|
470
398
|
blocks: {
|
|
471
399
|
paragraph: {
|
|
@@ -475,42 +403,25 @@
|
|
|
475
403
|
])
|
|
476
404
|
},
|
|
477
405
|
heading: {
|
|
406
|
+
...headingRead,
|
|
407
|
+
...headingWrite,
|
|
478
408
|
snippet: textThenChildren,
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
{
|
|
482
|
-
label: kinds.heading1,
|
|
483
|
-
icon: '
|
|
484
|
-
keywords: ['
|
|
485
|
-
data: { level
|
|
486
|
-
markdown: ['#
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
label: kinds.heading2,
|
|
490
|
-
icon: 'H₂',
|
|
491
|
-
keywords: ['h2', 'subtitle'],
|
|
492
|
-
data: { level: 'h2' },
|
|
493
|
-
markdown: ['## ']
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
label: kinds.heading3,
|
|
497
|
-
icon: 'H₃',
|
|
498
|
-
keywords: ['h3'],
|
|
499
|
-
data: { level: 'h3' },
|
|
500
|
-
markdown: ['### ']
|
|
501
|
-
}
|
|
502
|
-
]),
|
|
503
|
-
// HTML import: h1–h3 come from the presets; h4–h6 read as h3.
|
|
504
|
-
parse: (el) => (/^h[4-6]$/.test(el.localName) ? { level: 'h3' } : undefined),
|
|
505
|
-
html: (block, content, children) => {
|
|
506
|
-
const tag = headingLevel(block.data?.level);
|
|
507
|
-
return `<${tag}>${content}</${tag}>${children}`;
|
|
508
|
-
}
|
|
409
|
+
presets: presets(
|
|
410
|
+
'heading',
|
|
411
|
+
HEADING_LEVELS.map((level, index) => ({
|
|
412
|
+
label: [kinds.heading1, kinds.heading2, kinds.heading3][index]!,
|
|
413
|
+
icon: `H${['₁', '₂', '₃'][index]}`,
|
|
414
|
+
keywords: [level, ...[['title'], ['subtitle'], []][index]!],
|
|
415
|
+
data: { level },
|
|
416
|
+
markdown: [`${'#'.repeat(index + 1)} `]
|
|
417
|
+
}))
|
|
418
|
+
)
|
|
509
419
|
},
|
|
510
420
|
'bulleted-list-item': {
|
|
421
|
+
...itemRead,
|
|
422
|
+
...itemWrite,
|
|
511
423
|
continues: true,
|
|
512
424
|
snippet: listItem,
|
|
513
|
-
element: unlisted('li'),
|
|
514
425
|
presets: presets('bulleted-list-item', [
|
|
515
426
|
{
|
|
516
427
|
label: kinds.bulletedList,
|
|
@@ -518,13 +429,13 @@
|
|
|
518
429
|
keywords: ['bullet', 'ul'],
|
|
519
430
|
markdown: ['- ', '* ', '+ ']
|
|
520
431
|
}
|
|
521
|
-
])
|
|
522
|
-
html: 'li'
|
|
432
|
+
])
|
|
523
433
|
},
|
|
524
434
|
'numbered-list-item': {
|
|
435
|
+
...numberedRead,
|
|
436
|
+
...itemWrite,
|
|
525
437
|
continues: true,
|
|
526
438
|
snippet: listItem,
|
|
527
|
-
element: unlisted('li'),
|
|
528
439
|
presets: presets('numbered-list-item', [
|
|
529
440
|
{
|
|
530
441
|
label: kinds.numberedList,
|
|
@@ -532,13 +443,10 @@
|
|
|
532
443
|
keywords: ['number', 'ol'],
|
|
533
444
|
markdown: ['1. ', 'a. ', 'i. ']
|
|
534
445
|
}
|
|
535
|
-
])
|
|
536
|
-
html: 'li',
|
|
537
|
-
// HTML import: an `li` is a bulleted item (the first `li` kind) unless its list is ordered.
|
|
538
|
-
parse: (el) =>
|
|
539
|
-
el.localName === 'li' && el.parentElement?.localName === 'ol' ? {} : undefined
|
|
446
|
+
])
|
|
540
447
|
},
|
|
541
448
|
'todo-item': {
|
|
449
|
+
...todoWrite,
|
|
542
450
|
continues: true,
|
|
543
451
|
// The app's control markup, if any, through its own snippet: the default costs no branch.
|
|
544
452
|
snippet: checkbox ? todoItemOwn : todoItem,
|
|
@@ -550,15 +458,10 @@
|
|
|
550
458
|
data: { checked: false },
|
|
551
459
|
markdown: ['[ ] ', '[] ']
|
|
552
460
|
}
|
|
553
|
-
])
|
|
554
|
-
html: (block, content, children) =>
|
|
555
|
-
`<li data-edytor-todo-item="true"><input type="checkbox"${block.data?.checked === true ? ' checked' : ''}>${content}${children}</li>`,
|
|
556
|
-
plain: (block, content, children) =>
|
|
557
|
-
[`${block.data?.checked === true ? '[x]' : '[ ]'} ${content}`.trim(), children]
|
|
558
|
-
.filter(Boolean)
|
|
559
|
-
.join('\n')
|
|
461
|
+
])
|
|
560
462
|
},
|
|
561
463
|
toggle: {
|
|
464
|
+
...toggleRead,
|
|
562
465
|
continues: true,
|
|
563
466
|
container: true,
|
|
564
467
|
snippet: emptyBody ? detailsOwn : details,
|
|
@@ -577,13 +480,14 @@
|
|
|
577
480
|
// kept); from a toggle, `#`, `##` or `###` + space; so `> # ` typed on a new
|
|
578
481
|
// line is a toggle heading 1.
|
|
579
482
|
'toggle-heading': {
|
|
483
|
+
...toggleHeadingRead,
|
|
484
|
+
...toggleHeadingWrite,
|
|
580
485
|
container: true,
|
|
581
486
|
snippet: emptyBody ? detailsOwn : details,
|
|
582
487
|
...disclosure,
|
|
583
|
-
contentElement: (data) => headingLevel(data.level),
|
|
584
488
|
presets: presets(
|
|
585
489
|
'toggle-heading',
|
|
586
|
-
|
|
490
|
+
HEADING_LEVELS.map((level, index) => {
|
|
587
491
|
const hashes = '#'.repeat(index + 1);
|
|
588
492
|
return {
|
|
589
493
|
label: [kinds.toggleHeading1, kinds.toggleHeading2, kinds.toggleHeading3][index]!,
|
|
@@ -597,28 +501,21 @@
|
|
|
597
501
|
}
|
|
598
502
|
};
|
|
599
503
|
})
|
|
600
|
-
)
|
|
601
|
-
// HTML import: a `details` whose summary holds an h1–h3 (its own export).
|
|
602
|
-
parse: (el) => {
|
|
603
|
-
if (el.localName !== 'details') return;
|
|
604
|
-
const tag = el.querySelector(':scope > summary > :is(h1, h2, h3, h4, h5, h6)');
|
|
605
|
-
return tag ? { level: headingLevel(tag.localName) } : undefined;
|
|
606
|
-
},
|
|
607
|
-
html: (block, content, children) => {
|
|
608
|
-
const tag = headingLevel(block.data?.level);
|
|
609
|
-
return `<details><summary><${tag}>${content}</${tag}></summary>${children}</details>`;
|
|
610
|
-
}
|
|
504
|
+
)
|
|
611
505
|
},
|
|
612
506
|
// Notion's callout: an icon (`data.icon`, the picker's), a title (its own
|
|
613
507
|
// text) and a content (its children, any blocks), which shows even empty
|
|
614
508
|
// (`body`): Enter at the end of the title goes into it.
|
|
615
509
|
callout: {
|
|
510
|
+
...calloutRead,
|
|
616
511
|
container: true,
|
|
617
512
|
body: true,
|
|
618
513
|
snippet: calloutIcon || emptyBody ? calloutOwn : callout,
|
|
619
514
|
presets: presets('callout', [
|
|
620
515
|
{ label: kinds.callout, icon: '✦', keywords: ['note', 'tip'], data: { icon } }
|
|
621
516
|
]),
|
|
517
|
+
// A callout without its own icon exports the view's.
|
|
518
|
+
...calloutWrite((data) => iconOf(data, edytor)),
|
|
622
519
|
// The block menu's Change icon, while the view lists a picker: the keyboard's way to it.
|
|
623
520
|
menu: (block) => {
|
|
624
521
|
const picker = calloutPickers.get(edytor);
|
|
@@ -632,47 +529,38 @@
|
|
|
632
529
|
}
|
|
633
530
|
]
|
|
634
531
|
: [];
|
|
635
|
-
}
|
|
636
|
-
// HTML import: its own export, the icon in its attribute.
|
|
637
|
-
parse: (el) => {
|
|
638
|
-
const own = el.getAttribute('data-edytor-callout');
|
|
639
|
-
return own === null ? undefined : { icon: own };
|
|
640
|
-
},
|
|
641
|
-
html: (block, content, children) =>
|
|
642
|
-
calloutHtml(iconOf(block.data, edytor), content, children)
|
|
532
|
+
}
|
|
643
533
|
},
|
|
644
534
|
quote: {
|
|
535
|
+
...quoteRead,
|
|
536
|
+
...quoteWrite,
|
|
645
537
|
container: true,
|
|
646
538
|
snippet: textThenChildren,
|
|
647
|
-
contentElement: 'blockquote',
|
|
648
539
|
// Notion: `"` + space is a quote; `>` + space is a toggle.
|
|
649
|
-
presets: presets('quote', [{ label: kinds.quote, icon: '❝', markdown: ['" '] }])
|
|
650
|
-
html: 'blockquote'
|
|
540
|
+
presets: presets('quote', [{ label: kinds.quote, icon: '❝', markdown: ['" '] }])
|
|
651
541
|
},
|
|
652
542
|
divider: {
|
|
653
543
|
...richTextKinds.divider,
|
|
654
|
-
|
|
544
|
+
...dividerRead,
|
|
545
|
+
...dividerWrite,
|
|
655
546
|
presets: presets('divider', [
|
|
656
547
|
{ label: kinds.divider, icon: '—', keywords: ['hr', 'separator'], markdown: ['---'] }
|
|
657
548
|
]),
|
|
658
|
-
empty: { content: [], children: [] }
|
|
659
|
-
...rule
|
|
549
|
+
empty: { content: [], children: [] }
|
|
660
550
|
},
|
|
661
551
|
'ordered-list': {
|
|
662
552
|
...richTextKinds['ordered-list'],
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
html: 'ol'
|
|
553
|
+
...orderedRead,
|
|
554
|
+
...orderedWrite,
|
|
555
|
+
snippet: list
|
|
667
556
|
},
|
|
668
557
|
'unordered-list': {
|
|
669
558
|
...richTextKinds['unordered-list'],
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
html: 'ul'
|
|
559
|
+
...unorderedRead,
|
|
560
|
+
...unorderedWrite,
|
|
561
|
+
snippet: list
|
|
674
562
|
},
|
|
675
|
-
'list-item': {
|
|
563
|
+
'list-item': { ...itemRead, ...itemWrite, snippet: listItem }
|
|
676
564
|
}
|
|
677
565
|
};
|
|
678
566
|
};
|
|
@@ -10,7 +10,7 @@ export const openBody = (block) => {
|
|
|
10
10
|
return edytor.dispatcher.run('openBody', () => {
|
|
11
11
|
const added = () => edytor.insertBlocks({ parent: block.id, index: 0 }, [{ type: edytor.defaultChild(block) }]);
|
|
12
12
|
const child = block.children[0] ?? edytor.idToBlock.get(added().ids[0] ?? '');
|
|
13
|
-
edytor.dispatcher.
|
|
13
|
+
edytor.dispatcher.caretIn(child?.firstText, 0);
|
|
14
14
|
return child ?? undefined;
|
|
15
15
|
});
|
|
16
16
|
};
|
|
@@ -40,6 +40,8 @@ export declare class CalloutIconPicker extends ChromeList {
|
|
|
40
40
|
constructor(edytor: Edytor,
|
|
41
41
|
/** The picker's choices. */
|
|
42
42
|
icons?: readonly string[]);
|
|
43
|
+
/** Where the picker stands: the open callout's icon (`ChromeAnchor`), which your `picker` places itself under. */
|
|
44
|
+
get anchor(): import("../chrome.js").ChromeAnchor;
|
|
43
45
|
/** Whether the picker is open (reactive). */
|
|
44
46
|
get isOpen(): boolean;
|
|
45
47
|
/** The callout it is open on (reactive). */
|
|
@@ -48,8 +50,6 @@ export declare class CalloutIconPicker extends ChromeList {
|
|
|
48
50
|
get current(): string | undefined;
|
|
49
51
|
/** The keyboard's rows: the icons, then Remove icon. */
|
|
50
52
|
protected get count(): number;
|
|
51
|
-
/** The view is readonly (reactive): the picker closes. */
|
|
52
|
-
get readonly(): boolean;
|
|
53
53
|
/** Open the picker on `block`, or close it when it is open there. */
|
|
54
54
|
toggle: (block: Block) => void;
|
|
55
55
|
/** Open the picker on the callout `block`, its icon the keyboard's row (refused in a view that may not write). */
|
|
@@ -14,7 +14,6 @@ import { takeKeys } from '../../events/onFocus.js';
|
|
|
14
14
|
import { ChromeList, holdKeys, menuKey, optionAttachment } from '../list.svelte.js';
|
|
15
15
|
import { Anchored } from '../anchored.svelte.js';
|
|
16
16
|
import { calloutPickers, iconOf } from './callouts.js';
|
|
17
|
-
import CalloutIconHost from './CalloutIconPicker.svelte';
|
|
18
17
|
import { all, listen } from '../../utils/listen.js';
|
|
19
18
|
/** The picker's choices unless `createCalloutIconsPlugin({ icons })` names others. */
|
|
20
19
|
export const CALLOUT_ICONS = [
|
|
@@ -89,6 +88,10 @@ export class CalloutIconPicker extends ChromeList {
|
|
|
89
88
|
return icon ?? node ?? null;
|
|
90
89
|
}, () => this.close(false));
|
|
91
90
|
}
|
|
91
|
+
/** Where the picker stands: the open callout's icon (`ChromeAnchor`), which your `picker` places itself under. */
|
|
92
|
+
get anchor() {
|
|
93
|
+
return this.panel.anchor;
|
|
94
|
+
}
|
|
92
95
|
/** Whether the picker is open (reactive). */
|
|
93
96
|
get isOpen() {
|
|
94
97
|
return this.target !== null;
|
|
@@ -107,10 +110,6 @@ export class CalloutIconPicker extends ChromeList {
|
|
|
107
110
|
get count() {
|
|
108
111
|
return this.icons.length + 1;
|
|
109
112
|
}
|
|
110
|
-
/** The view is readonly (reactive): the picker closes. */
|
|
111
|
-
get readonly() {
|
|
112
|
-
return this.edytor.readonly;
|
|
113
|
-
}
|
|
114
113
|
/** Open the picker on `block`, or close it when it is open there. */
|
|
115
114
|
toggle = (block) => (this.target === block.id ? this.close() : this.open(block));
|
|
116
115
|
/** Open the picker on the callout `block`, its icon the keyboard's row (refused in a view that may not write). */
|
|
@@ -129,7 +128,6 @@ export class CalloutIconPicker extends ChromeList {
|
|
|
129
128
|
return;
|
|
130
129
|
const before = this.#before;
|
|
131
130
|
this.target = null;
|
|
132
|
-
this.panel.box = null;
|
|
133
131
|
this.#before = null;
|
|
134
132
|
this.edytor.overlay.invalidate();
|
|
135
133
|
if (!keys)
|
|
@@ -209,6 +207,6 @@ export const createCalloutIconsPlugin = ({ picker: menu, icons } = {}) => (edyto
|
|
|
209
207
|
calloutPickers.set(edytor, picker);
|
|
210
208
|
return {
|
|
211
209
|
// With the menus: above the handles and the image chrome.
|
|
212
|
-
onEdytorAttached: ({ node }) => menu && picker.panel.mount(node,
|
|
210
|
+
onEdytorAttached: ({ node }) => menu && picker.panel.mount(node, menu, picker, () => picker.isOpen, 70)
|
|
213
211
|
};
|
|
214
212
|
};
|
|
@@ -6,25 +6,7 @@ export type RichTextLink = {
|
|
|
6
6
|
href: string;
|
|
7
7
|
target?: string;
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
* CSS-color sanitizer for `color`/`highlight` marks. The value lands in
|
|
11
|
-
* `style="color: {value}"` — a `;`/`{`/`}` payload escapes the property
|
|
12
|
-
* and injects arbitrary declarations (`url()` exfil, `position:fixed`
|
|
13
|
-
* overlays). Metacharacters, escape/obfuscation sequences, and
|
|
14
|
-
* resource-loading functions are rejected; real `<color>` values
|
|
15
|
-
* (`#hex`, `rgb()/hsl()/oklch()/color-mix()/var()`, named colors) pass.
|
|
16
|
-
*/
|
|
17
|
-
export declare const sanitizeCssColorValue: (value: unknown) => string | null;
|
|
18
|
-
/**
|
|
19
|
-
* Scheme allowlist for link hrefs. `javascript:`/`data:`/`vbscript:`
|
|
20
|
-
* payloads can arrive through native `insertLink`, pasted HTML, or a
|
|
21
|
-
* malicious collaborator — and Svelte renders `href` verbatim. The href is
|
|
22
|
-
* read as the browser's URL parser reads it: it strips C0 controls and
|
|
23
|
-
* spaces at both ends and tab/newline/CR anywhere (`\u0001javascript:` is
|
|
24
|
-
* `javascript:` to a browser), then resolves it against a base; only an
|
|
25
|
-
* allowed scheme, or a relative href that stays relative, passes.
|
|
26
|
-
*/
|
|
27
|
-
export declare const sanitizeLinkHref: (href: unknown) => string | null;
|
|
9
|
+
export { sanitizeCssColorValue, sanitizeLinkHref } from '../../utils/sanitize.js';
|
|
28
10
|
/**
|
|
29
11
|
* The URL a paste carries when its plain text is one link and nothing else
|
|
30
12
|
* (surrounding whitespace aside): `http:`/`https:` with a host, or
|
|
@@ -3,54 +3,8 @@ import { holdsNothing, placing } from '../../kinds.js';
|
|
|
3
3
|
import { id } from '../../utils.js';
|
|
4
4
|
import { marksForInsertion } from '../../session/editing/text.js';
|
|
5
5
|
import { selectedTextSpans, viewOf } from '../../selection/visibility.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* CSS-color sanitizer for `color`/`highlight` marks. The value lands in
|
|
9
|
-
* `style="color: {value}"` — a `;`/`{`/`}` payload escapes the property
|
|
10
|
-
* and injects arbitrary declarations (`url()` exfil, `position:fixed`
|
|
11
|
-
* overlays). Metacharacters, escape/obfuscation sequences, and
|
|
12
|
-
* resource-loading functions are rejected; real `<color>` values
|
|
13
|
-
* (`#hex`, `rgb()/hsl()/oklch()/color-mix()/var()`, named colors) pass.
|
|
14
|
-
*/
|
|
15
|
-
export const sanitizeCssColorValue = (value) => {
|
|
16
|
-
if (typeof value !== 'string')
|
|
17
|
-
return null;
|
|
18
|
-
const trimmed = value.trim();
|
|
19
|
-
if (!trimmed || trimmed.length > 128)
|
|
20
|
-
return null;
|
|
21
|
-
if (/[;{}<>\\'"`]/.test(trimmed) || /url\s*\(|expression\s*\(|\/\*|\*\//i.test(trimmed)) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
return trimmed;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Scheme allowlist for link hrefs. `javascript:`/`data:`/`vbscript:`
|
|
28
|
-
* payloads can arrive through native `insertLink`, pasted HTML, or a
|
|
29
|
-
* malicious collaborator — and Svelte renders `href` verbatim. The href is
|
|
30
|
-
* read as the browser's URL parser reads it: it strips C0 controls and
|
|
31
|
-
* spaces at both ends and tab/newline/CR anywhere (`\u0001javascript:` is
|
|
32
|
-
* `javascript:` to a browser), then resolves it against a base; only an
|
|
33
|
-
* allowed scheme, or a relative href that stays relative, passes.
|
|
34
|
-
*/
|
|
35
|
-
export const sanitizeLinkHref = (href) => {
|
|
36
|
-
// Marks arrive from untrusted sources too (synced peers, paste) —
|
|
37
|
-
// reject non-strings outright instead of throwing on `.replace`.
|
|
38
|
-
if (typeof href !== 'string')
|
|
39
|
-
return null;
|
|
40
|
-
// eslint-disable-next-line no-control-regex
|
|
41
|
-
const trimmed = href.replace(/[\t\n\r]/g, '').replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, '');
|
|
42
|
-
if (!trimmed)
|
|
43
|
-
return null;
|
|
44
|
-
try {
|
|
45
|
-
// A relative href resolves to the base's `https:`: it names no scheme of its own.
|
|
46
|
-
return SAFE_LINK_PROTOCOLS.has(new URL(trimmed, 'https://relative.invalid/').protocol)
|
|
47
|
-
? trimmed
|
|
48
|
-
: null;
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
6
|
+
export { sanitizeCssColorValue, sanitizeLinkHref } from '../../utils/sanitize.js';
|
|
7
|
+
import { sanitizeCssColorValue, sanitizeLinkHref } from '../../utils/sanitize.js';
|
|
54
8
|
/**
|
|
55
9
|
* The URL a paste carries when its plain text is one link and nothing else
|
|
56
10
|
* (surrounding whitespace aside): `http:`/`https:` with a host, or
|
|
@@ -194,7 +148,7 @@ export const richTextOperations = (edytor) => ({
|
|
|
194
148
|
if (dispatcher.plan('insertDivider', {}, prepare, block).status !== 'applied')
|
|
195
149
|
return null;
|
|
196
150
|
const text = caret ? edytor.idToBlock.get(caret)?.firstText : startText;
|
|
197
|
-
dispatcher.
|
|
151
|
+
dispatcher.caretIn(text, caret ? 0 : yStart);
|
|
198
152
|
return block;
|
|
199
153
|
},
|
|
200
154
|
removeAllMarksAtRange: () => {
|
|
@@ -19,6 +19,8 @@ export declare class SlashMenuController extends TextTriggerController {
|
|
|
19
19
|
/** The selection when a `+` opened the menu, given back when it closes unpicked. */
|
|
20
20
|
private held;
|
|
21
21
|
constructor(edytor: Edytor);
|
|
22
|
+
/** A `+`'s menu stands under the `+` (its block while the `+` is gone); a `/` menu at the caret. */
|
|
23
|
+
protected anchorRect(): DOMRect | undefined;
|
|
22
24
|
/** A `+`'s menu names its highlighted row from its own field, and tells the `+` it opened it. */
|
|
23
25
|
protected popupOf(active: string | undefined): Popup;
|
|
24
26
|
/**
|