@dxos/react-ui-editor 0.8.4-main.3a94e84 → 0.8.4-main.3c1ae3b
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/dist/lib/browser/{chunk-22UMM3QJ.mjs → chunk-HL3YF6WC.mjs} +2 -2
- package/dist/lib/browser/chunk-HL3YF6WC.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +4541 -2844
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node-esm/{chunk-YXYQPV6R.mjs → chunk-YJZGD3LY.mjs} +2 -2
- package/dist/lib/node-esm/chunk-YJZGD3LY.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +4541 -2844
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/components/Editor/Editor.d.ts +37 -15
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
- package/dist/types/src/components/Editor/Editor.stories.d.ts +20 -0
- package/dist/types/src/components/Editor/Editor.stories.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/EditorContent.d.ts +29 -0
- package/dist/types/src/components/EditorContent/EditorContent.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts +26 -0
- package/dist/types/src/components/EditorContent/EditorContent.stories.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/controller.d.ts +10 -0
- package/dist/types/src/components/EditorContent/controller.d.ts.map +1 -0
- package/dist/types/src/components/EditorContent/index.d.ts +3 -0
- package/dist/types/src/components/EditorContent/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +36 -0
- package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/index.d.ts +7 -0
- package/dist/types/src/components/EditorMenuProvider/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts +4 -0
- package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts +28 -0
- package/dist/types/src/components/EditorMenuProvider/menu.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts +47 -0
- package/dist/types/src/components/EditorMenuProvider/popover.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts +34 -0
- package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -0
- package/dist/types/src/components/EditorMenuProvider/util.d.ts +8 -0
- package/dist/types/src/components/EditorMenuProvider/util.d.ts.map +1 -0
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts +16 -0
- package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -0
- package/dist/types/src/components/EditorPreviewProvider/index.d.ts +2 -0
- package/dist/types/src/components/EditorPreviewProvider/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +26 -2
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/actions.d.ts +39 -0
- package/dist/types/src/components/EditorToolbar/actions.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/headings.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts +2 -1
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts +11 -0
- package/dist/types/src/components/EditorToolbar/useEditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +3 -3
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +4 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/defaults.d.ts +0 -2
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts +17 -0
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/index.d.ts +5 -0
- package/dist/types/src/extensions/autocomplete/index.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/match.d.ts +13 -0
- package/dist/types/src/extensions/autocomplete/match.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts +20 -0
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts +10 -0
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +10 -19
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts +3 -3
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/autoscroll.d.ts +20 -0
- package/dist/types/src/extensions/autoscroll.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts +4 -4
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/extensions/blocks.d.ts +2 -0
- package/dist/types/src/extensions/blocks.d.ts.map +1 -0
- package/dist/types/src/extensions/bookmarks.d.ts +12 -0
- package/dist/types/src/extensions/bookmarks.d.ts.map +1 -0
- package/dist/types/src/extensions/comments.d.ts +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +15 -16
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/focus.d.ts.map +1 -1
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +10 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/json.d.ts +1 -1
- package/dist/types/src/extensions/json.d.ts.map +1 -1
- package/dist/types/src/extensions/listener.d.ts +8 -6
- package/dist/types/src/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +8 -2
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +9 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +2 -4
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/modal.d.ts +7 -0
- package/dist/types/src/extensions/modal.d.ts.map +1 -0
- package/dist/types/src/extensions/modes.d.ts +1 -1
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/menu.d.ts +8 -0
- package/dist/types/src/extensions/outliner/menu.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/outliner.d.ts +1 -1
- package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/selection.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/tree.d.ts +2 -2
- package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -1
- package/dist/types/src/extensions/preview/preview.d.ts +8 -8
- package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
- package/dist/types/src/extensions/replacer.d.ts +21 -0
- package/dist/types/src/extensions/replacer.d.ts.map +1 -0
- package/dist/types/src/extensions/replacer.test.d.ts +2 -0
- package/dist/types/src/extensions/replacer.test.d.ts.map +1 -0
- package/dist/types/src/extensions/scrolling.d.ts +78 -0
- package/dist/types/src/extensions/scrolling.d.ts.map +1 -0
- package/dist/types/src/extensions/state.d.ts +2 -0
- package/dist/types/src/extensions/state.d.ts.map +1 -0
- package/dist/types/src/extensions/submit.d.ts +10 -0
- package/dist/types/src/extensions/submit.d.ts.map +1 -0
- package/dist/types/src/extensions/tab.d.ts +4 -0
- package/dist/types/src/extensions/tab.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/extended-markdown.d.ts +10 -0
- package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts +2 -0
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/index.d.ts +4 -0
- package/dist/types/src/extensions/tags/index.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/streamer.d.ts +12 -0
- package/dist/types/src/extensions/tags/streamer.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts +97 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-util.d.ts +10 -0
- package/dist/types/src/extensions/tags/xml-util.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +5 -9
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/stories/CommandDialog.stories.d.ts +14 -0
- package/dist/types/src/stories/CommandDialog.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Comments.stories.d.ts +22 -10
- package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts +39 -3
- package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Experimental.stories.d.ts +23 -13
- package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Markdown.stories.d.ts +33 -43
- package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Outliner.stories.d.ts +15 -21
- package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Popover.stories.d.ts +20 -0
- package/dist/types/src/stories/Popover.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Preview.stories.d.ts +23 -7
- package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Tags.stories.d.ts +16 -0
- package/dist/types/src/stories/Tags.stories.d.ts.map +1 -0
- package/dist/types/src/stories/TextEditor.stories.d.ts +38 -52
- package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/components/EditorStory.d.ts +15 -12
- package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
- package/dist/types/src/stories/components/util.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +1 -1
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts +6 -3
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -1
- package/dist/types/src/types/types.d.ts +2 -2
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util/cursor.d.ts.map +1 -1
- package/dist/types/src/util/debug.d.ts +5 -1
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/decorations.d.ts +4 -0
- package/dist/types/src/util/decorations.d.ts.map +1 -0
- package/dist/types/src/util/dom.d.ts +2 -12
- package/dist/types/src/util/dom.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/react.d.ts +1 -1
- package/dist/types/src/util/react.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +74 -68
- package/src/components/Editor/Editor.stories.tsx +89 -0
- package/src/components/Editor/Editor.tsx +160 -25
- package/src/components/EditorContent/EditorContent.stories.tsx +70 -0
- package/src/components/EditorContent/EditorContent.tsx +70 -0
- package/src/components/EditorContent/controller.ts +50 -0
- package/src/components/EditorContent/index.ts +6 -0
- package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +233 -0
- package/src/components/EditorMenuProvider/index.ts +11 -0
- package/src/components/EditorMenuProvider/menu-presets.ts +123 -0
- package/src/components/EditorMenuProvider/menu.ts +71 -0
- package/src/components/EditorMenuProvider/popover.ts +287 -0
- package/src/components/EditorMenuProvider/useEditorMenu.ts +175 -0
- package/src/components/EditorMenuProvider/util.ts +31 -0
- package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +82 -0
- package/src/components/EditorPreviewProvider/index.ts +5 -0
- package/src/components/EditorToolbar/EditorToolbar.tsx +116 -96
- package/src/components/EditorToolbar/actions.ts +86 -0
- package/src/components/EditorToolbar/blocks.ts +22 -24
- package/src/components/EditorToolbar/formatting.ts +23 -25
- package/src/components/EditorToolbar/headings.ts +17 -9
- package/src/components/EditorToolbar/image.ts +9 -5
- package/src/components/EditorToolbar/index.ts +3 -7
- package/src/components/EditorToolbar/search.ts +9 -5
- package/src/components/EditorToolbar/useEditorToolbar.ts +20 -0
- package/src/components/EditorToolbar/view-mode.ts +12 -6
- package/src/components/index.ts +8 -2
- package/src/defaults.ts +2 -17
- package/src/extensions/autocomplete/autocomplete.ts +151 -0
- package/src/extensions/autocomplete/index.ts +8 -0
- package/src/extensions/autocomplete/match.ts +46 -0
- package/src/extensions/{command → autocomplete}/placeholder.ts +22 -18
- package/src/extensions/{command → autocomplete}/typeahead.ts +8 -50
- package/src/extensions/automerge/automerge.stories.tsx +34 -26
- package/src/extensions/automerge/automerge.ts +31 -11
- package/src/extensions/automerge/cursor.ts +1 -1
- package/src/extensions/automerge/defs.ts +1 -1
- package/src/extensions/automerge/sync.ts +9 -5
- package/src/extensions/automerge/update-automerge.ts +2 -2
- package/src/extensions/autoscroll.ts +163 -0
- package/src/extensions/awareness/awareness-provider.ts +12 -12
- package/src/extensions/awareness/awareness.ts +2 -2
- package/src/extensions/blocks.ts +131 -0
- package/src/extensions/bookmarks.ts +75 -0
- package/src/extensions/comments.ts +20 -14
- package/src/extensions/dnd.ts +1 -1
- package/src/extensions/factories.ts +64 -46
- package/src/extensions/focus.ts +5 -4
- package/src/extensions/folding.tsx +3 -6
- package/src/extensions/hashtag.tsx +2 -2
- package/src/extensions/index.ts +10 -1
- package/src/extensions/json.ts +1 -1
- package/src/extensions/listener.ts +14 -20
- package/src/extensions/markdown/action.ts +2 -1
- package/src/extensions/markdown/bundle.ts +40 -6
- package/src/extensions/markdown/changes.ts +1 -1
- package/src/extensions/markdown/decorate.ts +95 -64
- package/src/extensions/markdown/formatting.test.ts +6 -6
- package/src/extensions/markdown/formatting.ts +11 -13
- package/src/extensions/markdown/highlight.ts +13 -13
- package/src/extensions/markdown/image.ts +5 -6
- package/src/extensions/markdown/link.ts +3 -0
- package/src/extensions/markdown/table.ts +13 -7
- package/src/extensions/mention.ts +1 -1
- package/src/extensions/modal.ts +24 -0
- package/src/extensions/modes.ts +2 -2
- package/src/extensions/{command/floating-menu.ts → outliner/menu.ts} +16 -21
- package/src/extensions/outliner/outliner.test.ts +3 -2
- package/src/extensions/outliner/outliner.ts +8 -7
- package/src/extensions/outliner/selection.ts +1 -1
- package/src/extensions/outliner/tree.test.ts +3 -2
- package/src/extensions/outliner/tree.ts +2 -2
- package/src/extensions/preview/index.ts +1 -1
- package/src/extensions/preview/preview.ts +69 -69
- package/src/extensions/replacer.test.ts +75 -0
- package/src/extensions/replacer.ts +93 -0
- package/src/extensions/scrolling.ts +189 -0
- package/src/extensions/selection.ts +3 -3
- package/src/extensions/state.ts +7 -0
- package/src/extensions/submit.ts +62 -0
- package/src/extensions/tab.ts +29 -0
- package/src/extensions/tags/extended-markdown.test.ts +263 -0
- package/src/extensions/tags/extended-markdown.ts +78 -0
- package/src/extensions/tags/index.ts +7 -0
- package/src/extensions/tags/streamer.ts +243 -0
- package/src/extensions/tags/xml-tags.ts +500 -0
- package/src/extensions/tags/xml-util.ts +94 -0
- package/src/extensions/typewriter.ts +1 -1
- package/src/hooks/useTextEditor.ts +31 -43
- package/src/stories/CommandDialog.stories.tsx +83 -0
- package/src/stories/Comments.stories.tsx +17 -14
- package/src/stories/EditorToolbar.stories.tsx +21 -20
- package/src/stories/Experimental.stories.tsx +17 -13
- package/src/stories/Markdown.stories.tsx +26 -22
- package/src/stories/Outliner.stories.tsx +51 -39
- package/src/stories/Popover.stories.tsx +162 -0
- package/src/stories/Preview.stories.tsx +56 -51
- package/src/stories/Tags.stories.tsx +95 -0
- package/src/stories/TextEditor.stories.tsx +43 -67
- package/src/stories/components/EditorStory.tsx +40 -29
- package/src/stories/components/util.tsx +40 -8
- package/src/styles/markdown.ts +2 -2
- package/src/styles/theme.ts +229 -209
- package/src/translations.ts +1 -1
- package/src/types/types.ts +1 -1
- package/src/util/cursor.ts +2 -1
- package/src/util/debug.ts +7 -2
- package/src/util/decorations.ts +21 -0
- package/src/util/dom.ts +5 -27
- package/src/util/index.ts +1 -0
- package/src/util/react.tsx +1 -1
- package/dist/lib/browser/chunk-22UMM3QJ.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -6
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YXYQPV6R.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -8
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/components/EditorToolbar/lists.d.ts +0 -19
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +0 -1
- package/dist/types/src/components/EditorToolbar/util.d.ts +0 -51
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +0 -1
- package/dist/types/src/components/Popover/CommandMenu.d.ts +0 -34
- package/dist/types/src/components/Popover/CommandMenu.d.ts.map +0 -1
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts +0 -21
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +0 -1
- package/dist/types/src/components/Popover/RefPopover.d.ts +0 -34
- package/dist/types/src/components/Popover/RefPopover.d.ts.map +0 -1
- package/dist/types/src/components/Popover/index.d.ts +0 -4
- package/dist/types/src/components/Popover/index.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete.d.ts +0 -13
- package/dist/types/src/extensions/autocomplete.d.ts.map +0 -1
- package/dist/types/src/extensions/command/action.d.ts +0 -17
- package/dist/types/src/extensions/command/action.d.ts.map +0 -1
- package/dist/types/src/extensions/command/command-menu.d.ts +0 -20
- package/dist/types/src/extensions/command/command-menu.d.ts.map +0 -1
- package/dist/types/src/extensions/command/command.d.ts +0 -6
- package/dist/types/src/extensions/command/command.d.ts.map +0 -1
- package/dist/types/src/extensions/command/floating-menu.d.ts +0 -7
- package/dist/types/src/extensions/command/floating-menu.d.ts.map +0 -1
- package/dist/types/src/extensions/command/hint.d.ts +0 -24
- package/dist/types/src/extensions/command/hint.d.ts.map +0 -1
- package/dist/types/src/extensions/command/index.d.ts +0 -7
- package/dist/types/src/extensions/command/index.d.ts.map +0 -1
- package/dist/types/src/extensions/command/placeholder.d.ts +0 -10
- package/dist/types/src/extensions/command/placeholder.d.ts.map +0 -1
- package/dist/types/src/extensions/command/state.d.ts +0 -16
- package/dist/types/src/extensions/command/state.d.ts.map +0 -1
- package/dist/types/src/extensions/command/typeahead.d.ts +0 -22
- package/dist/types/src/extensions/command/typeahead.d.ts.map +0 -1
- package/dist/types/src/extensions/command/useCommandMenu.d.ts +0 -26
- package/dist/types/src/extensions/command/useCommandMenu.d.ts.map +0 -1
- package/dist/types/src/stories/Command.stories.d.ts +0 -7
- package/dist/types/src/stories/Command.stories.d.ts.map +0 -1
- package/dist/types/src/stories/CommandMenu.stories.d.ts +0 -13
- package/dist/types/src/stories/CommandMenu.stories.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -2
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/util.d.ts +0 -2
- package/dist/types/src/testing/util.d.ts.map +0 -1
- package/src/components/EditorToolbar/lists.ts +0 -59
- package/src/components/EditorToolbar/util.ts +0 -65
- package/src/components/Popover/CommandMenu.tsx +0 -279
- package/src/components/Popover/RefDropdownMenu.tsx +0 -85
- package/src/components/Popover/RefPopover.tsx +0 -99
- package/src/components/Popover/index.ts +0 -7
- package/src/extensions/autocomplete.ts +0 -69
- package/src/extensions/command/action.ts +0 -56
- package/src/extensions/command/command-menu.ts +0 -210
- package/src/extensions/command/command.ts +0 -34
- package/src/extensions/command/hint.ts +0 -102
- package/src/extensions/command/index.ts +0 -10
- package/src/extensions/command/state.ts +0 -89
- package/src/extensions/command/useCommandMenu.ts +0 -118
- package/src/stories/Command.stories.tsx +0 -97
- package/src/stories/CommandMenu.stories.tsx +0 -159
- package/src/testing/index.ts +0 -5
- package/src/testing/util.ts +0 -5
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { StateEffect } from '@codemirror/state';
|
|
6
|
+
import { EditorView, ViewPlugin } from '@codemirror/view';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configuration options for smooth scrolling behavior.
|
|
10
|
+
*/
|
|
11
|
+
export type SmoothScrollOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* Additional offset from the target line in pixels.
|
|
14
|
+
* Positive values scroll past the line, negative values stop before it.
|
|
15
|
+
* @default 0
|
|
16
|
+
*/
|
|
17
|
+
offset?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Position of the target line in the viewport.
|
|
20
|
+
* - 'start': Line appears at the start (top) of the screen
|
|
21
|
+
* - 'end': Line appears at the end (bottom) of the screen
|
|
22
|
+
* @default 'start'
|
|
23
|
+
*/
|
|
24
|
+
position?: 'start' | 'end';
|
|
25
|
+
/**
|
|
26
|
+
* Whether to use smooth scrolling.
|
|
27
|
+
* @default 'smooth'
|
|
28
|
+
*/
|
|
29
|
+
behavior?: ScrollBehavior;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parameters for the scroll to line effect.
|
|
34
|
+
*/
|
|
35
|
+
export type ScrollToLineParams = {
|
|
36
|
+
/**
|
|
37
|
+
* The line number to scroll to (1-based).
|
|
38
|
+
*/
|
|
39
|
+
line: number;
|
|
40
|
+
/**
|
|
41
|
+
* Optional configuration to override default scroll behavior.
|
|
42
|
+
*/
|
|
43
|
+
options?: SmoothScrollOptions;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* StateEffect for triggering smooth scroll to a specific line.
|
|
48
|
+
*/
|
|
49
|
+
export const scrollToLineEffect = StateEffect.define<ScrollToLineParams>();
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Extension that provides smooth scrolling to specific lines in the editor.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // Add to editor extensions.
|
|
57
|
+
* const extensions = [
|
|
58
|
+
* smoothScroll()
|
|
59
|
+
* ];
|
|
60
|
+
*
|
|
61
|
+
* // Trigger scroll to line 42.
|
|
62
|
+
* view.dispatch({
|
|
63
|
+
* effects: scrollToLineEffect.of({ line: 42 })
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* // Scroll with custom options.
|
|
67
|
+
* view.dispatch({
|
|
68
|
+
* effects: scrollToLineEffect.of({ line: 100, options: { offset: -50 } })
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Scroll so line appears at end (bottom) of screen.
|
|
72
|
+
* view.dispatch({
|
|
73
|
+
* effects: scrollToLineEffect.of({ line: 50, options: { position: 'end' } })
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export const smoothScroll = ({ offset = 0, position = 'start' }: Partial<SmoothScrollOptions> = {}) => {
|
|
78
|
+
// ViewPlugin to manage scroll animations.
|
|
79
|
+
const scrollPlugin = ViewPlugin.fromClass(
|
|
80
|
+
class SmoothScrollPlugin {
|
|
81
|
+
constructor(private readonly view: EditorView) {}
|
|
82
|
+
|
|
83
|
+
// No-op.
|
|
84
|
+
destroy() {}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Perform smooth scroll to the specified line.
|
|
88
|
+
*/
|
|
89
|
+
scrollToLine(lineNumber: number, options: SmoothScrollOptions) {
|
|
90
|
+
const { offset: animOffset = 0, position: animPosition, behavior } = options;
|
|
91
|
+
const doc = this.view.state.doc;
|
|
92
|
+
const scroller = this.view.scrollDOM;
|
|
93
|
+
|
|
94
|
+
// Convert 1-based line number to 0-based.
|
|
95
|
+
const targetLine = Math.max(0, lineNumber - 1);
|
|
96
|
+
if (behavior === 'instant') {
|
|
97
|
+
requestAnimationFrame(() => {
|
|
98
|
+
this.view.dispatch({
|
|
99
|
+
selection: { anchor: doc.line(targetLine + 1).from },
|
|
100
|
+
scrollIntoView: true,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Get the position of the target line.
|
|
107
|
+
if (targetLine >= doc.lines) {
|
|
108
|
+
// Line doesn't exist, scroll to end.
|
|
109
|
+
const targetScrollTop = scroller.scrollHeight - scroller.clientHeight + (animOffset || 0);
|
|
110
|
+
this.animateScroll(scroller, targetScrollTop);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const lineStart = doc.line(targetLine + 1).from;
|
|
115
|
+
const coords = this.view.coordsAtPos(lineStart);
|
|
116
|
+
if (!coords) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Calculate target scroll position based on position option.
|
|
121
|
+
const currentScrollTop = scroller.scrollTop;
|
|
122
|
+
const scrollerRect = scroller.getBoundingClientRect();
|
|
123
|
+
const maxScrollTop = scroller.scrollHeight - scroller.clientHeight;
|
|
124
|
+
|
|
125
|
+
let targetScrollTop: number;
|
|
126
|
+
if (animPosition === 'end') {
|
|
127
|
+
// Position line at end (bottom) of viewport.
|
|
128
|
+
// Calculate how far down we need to scroll so the line's bottom aligns with viewport bottom.
|
|
129
|
+
targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + animOffset;
|
|
130
|
+
} else {
|
|
131
|
+
// Default: position line at start (top) of viewport.
|
|
132
|
+
targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + animOffset;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Clamp to valid scroll range.
|
|
136
|
+
const clampedScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
|
|
137
|
+
this.animateScroll(scroller, clampedScrollTop);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Animate scroll using browser's built-in smooth scrolling.
|
|
142
|
+
*/
|
|
143
|
+
private animateScroll(element: HTMLElement, targetScrollTop: number) {
|
|
144
|
+
if (Math.abs(targetScrollTop - element.scrollTop) < 1) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Use browser's built-in smooth scrolling.
|
|
149
|
+
element.scrollTo({
|
|
150
|
+
top: targetScrollTop,
|
|
151
|
+
behavior: 'smooth',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return [
|
|
158
|
+
scrollPlugin,
|
|
159
|
+
|
|
160
|
+
// Update listener to handle scroll effects.
|
|
161
|
+
EditorView.updateListener.of((update) => {
|
|
162
|
+
update.transactions.forEach((transaction) => {
|
|
163
|
+
for (const effect of transaction.effects) {
|
|
164
|
+
if (effect.is(scrollToLineEffect)) {
|
|
165
|
+
const { line, options = {} } = effect.value;
|
|
166
|
+
const plugin = update.view.plugin(scrollPlugin);
|
|
167
|
+
if (plugin) {
|
|
168
|
+
plugin.scrollToLine(line, { offset, position, ...options });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}),
|
|
174
|
+
];
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Helper function to scroll to a specific line.
|
|
179
|
+
* This is a convenience function that can be used directly with an EditorView.
|
|
180
|
+
*
|
|
181
|
+
* @param view - The CodeMirror EditorView instance
|
|
182
|
+
* @param line - The line number to scroll to (1-based)
|
|
183
|
+
* @param options - Optional scroll configuration
|
|
184
|
+
*/
|
|
185
|
+
export const scrollToLine = (view: EditorView, line: number, options?: SmoothScrollOptions) => {
|
|
186
|
+
view.dispatch({
|
|
187
|
+
effects: scrollToLineEffect.of({ line, options }),
|
|
188
|
+
});
|
|
189
|
+
};
|
|
@@ -7,7 +7,7 @@ import { EditorView, keymap } from '@codemirror/view';
|
|
|
7
7
|
|
|
8
8
|
import { debounce } from '@dxos/async';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
|
-
import {
|
|
10
|
+
import { isTruthy } from '@dxos/util';
|
|
11
11
|
|
|
12
12
|
import { singleValueFacet } from '../util';
|
|
13
13
|
|
|
@@ -86,7 +86,7 @@ export const selectionState = ({ getState, setState }: Partial<EditorStateStore>
|
|
|
86
86
|
getState &&
|
|
87
87
|
keymap.of([
|
|
88
88
|
{
|
|
89
|
-
key: '
|
|
89
|
+
key: 'Ctrl-r', // TODO(burdon): Setting to jump back to selection.
|
|
90
90
|
run: (view) => {
|
|
91
91
|
const state = getState(view.state.facet(documentId));
|
|
92
92
|
if (state) {
|
|
@@ -96,5 +96,5 @@ export const selectionState = ({ getState, setState }: Partial<EditorStateStore>
|
|
|
96
96
|
},
|
|
97
97
|
},
|
|
98
98
|
]),
|
|
99
|
-
].filter(
|
|
99
|
+
].filter(isTruthy);
|
|
100
100
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Extension, Prec } from '@codemirror/state';
|
|
6
|
+
import { keymap } from '@codemirror/view';
|
|
7
|
+
|
|
8
|
+
export type SubmitOptions = {
|
|
9
|
+
fireIfEmpty?: boolean;
|
|
10
|
+
onSubmit?: (text: string) => boolean | void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Handles Enter and Shift-Enter.
|
|
15
|
+
*/
|
|
16
|
+
export const submit = ({ fireIfEmpty = false, onSubmit }: SubmitOptions = {}): Extension => {
|
|
17
|
+
return [
|
|
18
|
+
Prec.highest(
|
|
19
|
+
keymap.of([
|
|
20
|
+
{
|
|
21
|
+
key: 'Enter',
|
|
22
|
+
preventDefault: true,
|
|
23
|
+
run: (view) => {
|
|
24
|
+
const text = view.state.doc.toString().trim();
|
|
25
|
+
if (onSubmit && (fireIfEmpty || text.length > 0)) {
|
|
26
|
+
const reset = onSubmit(text);
|
|
27
|
+
if (reset) {
|
|
28
|
+
// Clear the document after calling onEnter.
|
|
29
|
+
view.dispatch({
|
|
30
|
+
changes: {
|
|
31
|
+
from: 0,
|
|
32
|
+
to: view.state.doc.length,
|
|
33
|
+
insert: '',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return true;
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
key: 'Shift-Enter',
|
|
44
|
+
preventDefault: true,
|
|
45
|
+
run: (view) => {
|
|
46
|
+
view.dispatch({
|
|
47
|
+
changes: {
|
|
48
|
+
from: view.state.selection.main.head,
|
|
49
|
+
insert: '\n',
|
|
50
|
+
},
|
|
51
|
+
selection: {
|
|
52
|
+
anchor: view.state.selection.main.head + 1,
|
|
53
|
+
head: view.state.selection.main.head + 1,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
return true;
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
]),
|
|
60
|
+
),
|
|
61
|
+
];
|
|
62
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Extension } from '@codemirror/state';
|
|
6
|
+
import { keymap } from '@codemirror/view';
|
|
7
|
+
import { type useFocusFinders } from '@fluentui/react-tabster';
|
|
8
|
+
|
|
9
|
+
export const tab = ({
|
|
10
|
+
findNextFocusable,
|
|
11
|
+
findPrevFocusable,
|
|
12
|
+
// findFirstFocusable,
|
|
13
|
+
// findLastFocusable,
|
|
14
|
+
}: ReturnType<typeof useFocusFinders>): Extension => {
|
|
15
|
+
return keymap.of([
|
|
16
|
+
{
|
|
17
|
+
key: 'Tab',
|
|
18
|
+
preventDefault: true,
|
|
19
|
+
run: (view) => {
|
|
20
|
+
findNextFocusable(view.dom)?.focus();
|
|
21
|
+
return true;
|
|
22
|
+
},
|
|
23
|
+
shift: (view) => {
|
|
24
|
+
findPrevFocusable(view.dom)?.focus();
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
]);
|
|
29
|
+
};
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { syntaxTree } from '@codemirror/language';
|
|
6
|
+
import { EditorState } from '@codemirror/state';
|
|
7
|
+
import { type SyntaxNode } from '@lezer/common';
|
|
8
|
+
import { describe, test } from 'vitest';
|
|
9
|
+
|
|
10
|
+
import { trim } from '@dxos/util';
|
|
11
|
+
|
|
12
|
+
import { extendedMarkdown } from './extended-markdown';
|
|
13
|
+
import { nodeToJson } from './xml-util';
|
|
14
|
+
|
|
15
|
+
describe('extended-markdown', () => {
|
|
16
|
+
const createEditorState = (doc: string) => {
|
|
17
|
+
return EditorState.create({
|
|
18
|
+
doc,
|
|
19
|
+
extensions: [extendedMarkdown()],
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Flaky.
|
|
24
|
+
test.skip('tree', async ({ expect }) => {
|
|
25
|
+
const doc = trim`
|
|
26
|
+
<prompt>
|
|
27
|
+
Hello
|
|
28
|
+
</prompt>
|
|
29
|
+
|
|
30
|
+
Hi there!
|
|
31
|
+
|
|
32
|
+
What can I do for you?
|
|
33
|
+
|
|
34
|
+
<suggestion>Summarize tools</suggestion>
|
|
35
|
+
|
|
36
|
+
<choice>
|
|
37
|
+
<option>Summarize tools</option>
|
|
38
|
+
<option>Retry</option>
|
|
39
|
+
</choice>
|
|
40
|
+
|
|
41
|
+
<toolkit />
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const state = createEditorState(doc);
|
|
45
|
+
|
|
46
|
+
const nodes: SyntaxNode[] = [];
|
|
47
|
+
const tree = syntaxTree(state);
|
|
48
|
+
tree.iterate({
|
|
49
|
+
enter: (node) => {
|
|
50
|
+
if (node.type.name === 'Element') {
|
|
51
|
+
nodes.push(node.node);
|
|
52
|
+
return false; // Stop traversal.
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
expect(nodes).toHaveLength(4);
|
|
58
|
+
expect(
|
|
59
|
+
nodes.map((node) => ({
|
|
60
|
+
content: doc.slice(node.from, node.to),
|
|
61
|
+
data: nodeToJson(state, node.node),
|
|
62
|
+
})),
|
|
63
|
+
).toEqual([
|
|
64
|
+
{
|
|
65
|
+
content: '<prompt>\n Hello\n</prompt>',
|
|
66
|
+
data: {
|
|
67
|
+
_tag: 'prompt',
|
|
68
|
+
children: ['Hello'],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
content: '<suggestion>Summarize tools</suggestion>',
|
|
73
|
+
data: {
|
|
74
|
+
_tag: 'suggestion',
|
|
75
|
+
children: ['Summarize tools'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
content: '<choice>\n <option>Summarize tools</option>\n <option>Retry</option>\n</choice>',
|
|
80
|
+
data: {
|
|
81
|
+
_tag: 'choice',
|
|
82
|
+
children: [
|
|
83
|
+
{
|
|
84
|
+
_tag: 'option',
|
|
85
|
+
children: ['Summarize tools'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
_tag: 'option',
|
|
89
|
+
children: ['Retry'],
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
content: '<toolkit />',
|
|
96
|
+
data: {
|
|
97
|
+
_tag: 'toolkit',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
]);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('setext heading disabled', () => {
|
|
104
|
+
const doc = trim`
|
|
105
|
+
This should NOT be a heading
|
|
106
|
+
=
|
|
107
|
+
|
|
108
|
+
Another line that should NOT be a heading
|
|
109
|
+
-
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
const state = createEditorState(doc);
|
|
113
|
+
const tree = syntaxTree(state);
|
|
114
|
+
|
|
115
|
+
tree.iterate({
|
|
116
|
+
enter: (node) => {
|
|
117
|
+
if (node.type.name === 'SetextHeading') {
|
|
118
|
+
throw new Error('SetextHeading should be disabled!');
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
//
|
|
125
|
+
// TODO(burdon): All tests below should test the tree.
|
|
126
|
+
//
|
|
127
|
+
|
|
128
|
+
test('should parse standard markdown elements', ({ expect }) => {
|
|
129
|
+
const doc = trim`
|
|
130
|
+
# Heading 1
|
|
131
|
+
## Heading 2
|
|
132
|
+
### Heading 3
|
|
133
|
+
|
|
134
|
+
This is a paragraph with **bold** and *italic* text.
|
|
135
|
+
|
|
136
|
+
\`\`\`javascript
|
|
137
|
+
const code = 'block';
|
|
138
|
+
\`\`\`
|
|
139
|
+
`;
|
|
140
|
+
|
|
141
|
+
const state = createEditorState(doc);
|
|
142
|
+
const tree = state.sliceDoc(0, state.doc.length);
|
|
143
|
+
|
|
144
|
+
// Verify the document is parsed without errors.
|
|
145
|
+
expect(tree).toBe(doc);
|
|
146
|
+
expect(state.doc.lines).toBeGreaterThan(1);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('should parse custom XML tags', ({ expect }) => {
|
|
150
|
+
const doc = trim`
|
|
151
|
+
# Document with Custom Tags
|
|
152
|
+
|
|
153
|
+
<prompt>This is a custom prompt block</prompt>
|
|
154
|
+
|
|
155
|
+
Regular paragraph text.
|
|
156
|
+
|
|
157
|
+
<prompt />
|
|
158
|
+
|
|
159
|
+
Regular paragraph text.
|
|
160
|
+
|
|
161
|
+
<prompt>
|
|
162
|
+
Multi-line
|
|
163
|
+
prompt content
|
|
164
|
+
</prompt>
|
|
165
|
+
`;
|
|
166
|
+
|
|
167
|
+
const state = createEditorState(doc);
|
|
168
|
+
const tree = state.sliceDoc(0, state.doc.length);
|
|
169
|
+
|
|
170
|
+
// Verify the document contains custom tags.
|
|
171
|
+
expect(tree).toContain('<prompt>');
|
|
172
|
+
expect(tree).toContain('<prompt />');
|
|
173
|
+
expect(tree).toContain('</prompt>');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('should handle mixed markdown and XML content', ({ expect }) => {
|
|
177
|
+
const doc = trim`
|
|
178
|
+
# Mixed Content
|
|
179
|
+
|
|
180
|
+
This is a paragraph with a <prompt>inline prompt</prompt> tag.
|
|
181
|
+
|
|
182
|
+
## Section 2
|
|
183
|
+
|
|
184
|
+
<prompt>
|
|
185
|
+
This prompt contains **markdown** formatting
|
|
186
|
+
</prompt>
|
|
187
|
+
|
|
188
|
+
\`\`\`
|
|
189
|
+
<prompt>This should not be parsed as XML inside code block</prompt>
|
|
190
|
+
\`\`\`
|
|
191
|
+
`;
|
|
192
|
+
|
|
193
|
+
const state = createEditorState(doc);
|
|
194
|
+
const tree = state.sliceDoc(0, state.doc.length);
|
|
195
|
+
|
|
196
|
+
// Verify mixed content is preserved.
|
|
197
|
+
expect(tree).toBe(doc);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('should not parse XML tags in code blocks', ({ expect }) => {
|
|
201
|
+
const doc = trim`
|
|
202
|
+
\`\`\`xml
|
|
203
|
+
<prompt>This is inside a code block</prompt>
|
|
204
|
+
\`\`\`
|
|
205
|
+
|
|
206
|
+
\`<prompt>inline code</prompt>\`
|
|
207
|
+
`;
|
|
208
|
+
|
|
209
|
+
const state = createEditorState(doc);
|
|
210
|
+
const tree = state.sliceDoc(0, state.doc.length);
|
|
211
|
+
|
|
212
|
+
// Verify code blocks are preserved as-is.
|
|
213
|
+
expect(tree).toContain('```xml');
|
|
214
|
+
expect(tree).toContain('<prompt>This is inside a code block</prompt>');
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test('should handle nested and complex structures', ({ expect }) => {
|
|
218
|
+
const doc = trim`
|
|
219
|
+
# Complex Document
|
|
220
|
+
|
|
221
|
+
<prompt>
|
|
222
|
+
First prompt with some content
|
|
223
|
+
</prompt>
|
|
224
|
+
|
|
225
|
+
## Lists and Prompts
|
|
226
|
+
|
|
227
|
+
- Item 1
|
|
228
|
+
- Item 2 with <prompt>embedded prompt</prompt>
|
|
229
|
+
- Item 3
|
|
230
|
+
|
|
231
|
+
<prompt>
|
|
232
|
+
Another prompt after the list
|
|
233
|
+
</prompt>
|
|
234
|
+
|
|
235
|
+
### Code Example
|
|
236
|
+
|
|
237
|
+
\`\`\`typescript
|
|
238
|
+
const example = '<prompt>not parsed</prompt>';
|
|
239
|
+
\`\`\`
|
|
240
|
+
`;
|
|
241
|
+
|
|
242
|
+
const state = createEditorState(doc);
|
|
243
|
+
const tree = state.sliceDoc(0, state.doc.length);
|
|
244
|
+
|
|
245
|
+
// Verify complex structures are handled.
|
|
246
|
+
expect(tree).toBe(doc);
|
|
247
|
+
expect(tree).toMatch(/Item 2 with <prompt>embedded prompt<\/prompt>/);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test('should handle empty and edge cases', ({ expect }) => {
|
|
251
|
+
const emptyDoc = '';
|
|
252
|
+
const emptyState = createEditorState(emptyDoc);
|
|
253
|
+
expect(emptyState.doc.length).toBe(0);
|
|
254
|
+
|
|
255
|
+
const onlyPromptDoc = '<prompt>Only prompt content</prompt>';
|
|
256
|
+
const onlyPromptState = createEditorState(onlyPromptDoc);
|
|
257
|
+
expect(onlyPromptState.sliceDoc(0)).toBe(onlyPromptDoc);
|
|
258
|
+
|
|
259
|
+
const unclosedPromptDoc = '<prompt>Unclosed prompt';
|
|
260
|
+
const unclosedState = createEditorState(unclosedPromptDoc);
|
|
261
|
+
expect(unclosedState.sliceDoc(0)).toBe(unclosedPromptDoc);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { xmlLanguage } from '@codemirror/lang-xml';
|
|
6
|
+
import { type Extension } from '@codemirror/state';
|
|
7
|
+
import { type ParseWrapper, parseMixed } from '@lezer/common';
|
|
8
|
+
|
|
9
|
+
import { createMarkdownExtensions } from '../markdown';
|
|
10
|
+
|
|
11
|
+
import { type XmlWidgetRegistry } from './xml-tags';
|
|
12
|
+
|
|
13
|
+
export type ExtendedMarkdownOptions = {
|
|
14
|
+
registry?: XmlWidgetRegistry;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Extended markdown parser with mixed parser for custom rendering of XML tags.
|
|
19
|
+
*/
|
|
20
|
+
export const extendedMarkdown = ({ registry }: ExtendedMarkdownOptions = {}): Extension => {
|
|
21
|
+
return [
|
|
22
|
+
createMarkdownExtensions({
|
|
23
|
+
extensions: [
|
|
24
|
+
{
|
|
25
|
+
wrap: mixedParser(registry),
|
|
26
|
+
parseBlock: [
|
|
27
|
+
// Disable SetextHeading since it causes flickering when parsing/rendering tasks in chunks.
|
|
28
|
+
{
|
|
29
|
+
name: 'SetextHeading',
|
|
30
|
+
parse: () => false,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
}),
|
|
36
|
+
];
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Configure mixed parser to recognize custom tags.
|
|
41
|
+
*/
|
|
42
|
+
const mixedParser = (registry?: XmlWidgetRegistry): ParseWrapper => {
|
|
43
|
+
const customTags = Object.keys(registry ?? {});
|
|
44
|
+
const tagPattern = new RegExp(`<(${customTags.join('|')})`);
|
|
45
|
+
|
|
46
|
+
return parseMixed((node, input) => {
|
|
47
|
+
switch (node.name) {
|
|
48
|
+
// Ignore XML inside of fenced and inline code.
|
|
49
|
+
case 'FencedCode':
|
|
50
|
+
case 'InlineCode': {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Parse multi-line HTML blocks.
|
|
55
|
+
// case 'XMLBlock':
|
|
56
|
+
case 'HTMLBlock': {
|
|
57
|
+
return {
|
|
58
|
+
parser: xmlLanguage.parser,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Parse paragraphs that contain custom XML tags.
|
|
63
|
+
// TODO(burdon): Entire paragraph should be parsed as XML.
|
|
64
|
+
case 'Paragraph': {
|
|
65
|
+
const content = input.read(node.from, node.to);
|
|
66
|
+
if (tagPattern.test(content)) {
|
|
67
|
+
return {
|
|
68
|
+
parser: xmlLanguage.parser,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return null;
|
|
77
|
+
});
|
|
78
|
+
};
|