@dxos/ui-editor 0.10.0 → 0.11.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/dist/lib/chunk-diff.mjs +935 -0
- package/dist/lib/chunk-diff.mjs.map +1 -0
- package/dist/lib/headless.mjs +2 -0
- package/dist/lib/index.mjs +9937 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/types.mjs +18 -0
- package/dist/lib/types.mjs.map +1 -0
- package/dist/types/src/extensions/{bookmarks.d.ts → behavior/bookmarks.d.ts} +3 -0
- package/dist/types/src/extensions/behavior/bookmarks.d.ts.map +1 -0
- package/dist/types/src/extensions/behavior/dnd.d.ts.map +1 -0
- package/dist/types/src/extensions/behavior/index.d.ts +6 -0
- package/dist/types/src/extensions/behavior/index.d.ts.map +1 -0
- package/dist/types/src/extensions/{listener.d.ts → behavior/listener.d.ts} +3 -0
- package/dist/types/src/extensions/behavior/listener.d.ts.map +1 -0
- package/dist/types/src/extensions/{spacing.d.ts → behavior/spacing.d.ts} +3 -0
- package/dist/types/src/extensions/behavior/spacing.d.ts.map +1 -0
- package/dist/types/src/extensions/behavior/submit.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/automerge/automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/automerge/automerge.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/cursor.d.ts +1 -1
- package/dist/types/src/extensions/collab/automerge/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/defs.d.ts +3 -1
- package/dist/types/src/extensions/collab/automerge/defs.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/automerge/index.d.ts +3 -0
- package/dist/types/src/extensions/collab/automerge/index.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/automerge/sync.d.ts.map +1 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/update-automerge.d.ts +4 -0
- package/dist/types/src/extensions/collab/automerge/update-automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/update-codemirror.d.ts +4 -0
- package/dist/types/src/extensions/collab/automerge/update-codemirror.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/awareness/awareness-provider.d.ts.map +1 -0
- package/dist/types/src/extensions/{awareness → collab/awareness}/awareness.d.ts +4 -1
- package/dist/types/src/extensions/collab/awareness/awareness.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/awareness/index.d.ts.map +1 -0
- package/dist/types/src/extensions/collab/index.d.ts +3 -0
- package/dist/types/src/extensions/collab/index.d.ts.map +1 -0
- package/dist/types/src/extensions/completion/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/{autocomplete → completion}/index.d.ts +1 -0
- package/dist/types/src/extensions/completion/index.d.ts.map +1 -0
- package/dist/types/src/extensions/{autocomplete → completion}/match.d.ts +2 -2
- package/dist/types/src/extensions/completion/match.d.ts.map +1 -0
- package/dist/types/src/extensions/{mention.d.ts → completion/mention.d.ts} +3 -0
- package/dist/types/src/extensions/completion/mention.d.ts.map +1 -0
- package/dist/types/src/extensions/completion/placeholder.d.ts.map +1 -0
- package/dist/types/src/extensions/{autocomplete → completion}/typeahead.d.ts +2 -2
- package/dist/types/src/extensions/completion/typeahead.d.ts.map +1 -0
- package/dist/types/src/extensions/{factories.d.ts → core/factories.d.ts} +23 -2
- package/dist/types/src/extensions/core/factories.d.ts.map +1 -0
- package/dist/types/src/extensions/core/factories.test.d.ts.map +1 -0
- package/dist/types/src/extensions/core/index.d.ts +3 -0
- package/dist/types/src/extensions/core/index.d.ts.map +1 -0
- package/dist/types/src/extensions/{modes.d.ts → core/modes.d.ts} +3 -0
- package/dist/types/src/extensions/core/modes.d.ts.map +1 -0
- package/dist/types/src/extensions/{debug.d.ts → debug/debug.d.ts} +3 -0
- package/dist/types/src/extensions/debug/debug.d.ts.map +1 -0
- package/dist/types/src/extensions/debug/index.d.ts +2 -0
- package/dist/types/src/extensions/debug/index.d.ts.map +1 -0
- package/dist/types/src/extensions/{annotations.d.ts → decoration/annotations.d.ts} +1 -1
- package/dist/types/src/extensions/decoration/annotations.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/assistant.d.ts +27 -0
- package/dist/types/src/extensions/decoration/assistant.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/fader.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/hashtag.d.ts +6 -0
- package/dist/types/src/extensions/decoration/hashtag.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/index.d.ts +8 -0
- package/dist/types/src/extensions/decoration/index.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/marker.d.ts.map +1 -0
- package/dist/types/src/extensions/{pos.d.ts → decoration/pos.d.ts} +40 -14
- package/dist/types/src/extensions/decoration/pos.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/pos.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{replacer.d.ts → decoration/replacer.d.ts} +8 -8
- package/dist/types/src/extensions/decoration/replacer.d.ts.map +1 -0
- package/dist/types/src/extensions/decoration/replacer.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{blast.d.ts → demo/blast.d.ts} +3 -0
- package/dist/types/src/extensions/demo/blast.d.ts.map +1 -0
- package/dist/types/src/extensions/demo/index.d.ts +3 -0
- package/dist/types/src/extensions/demo/index.d.ts.map +1 -0
- package/dist/types/src/extensions/demo/snippets.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +10 -33
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/language/index.d.ts +5 -0
- package/dist/types/src/extensions/language/index.d.ts.map +1 -0
- package/dist/types/src/extensions/language/json/index.d.ts +2 -0
- package/dist/types/src/extensions/language/json/index.d.ts.map +1 -0
- package/dist/types/src/extensions/language/json/json.d.ts +12 -0
- package/dist/types/src/extensions/language/json/json.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/action.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/bundle.d.ts.map +1 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/changes.d.ts +1 -1
- package/dist/types/src/extensions/language/markdown/changes.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/changes.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/debug.d.ts +3 -0
- package/dist/types/src/extensions/language/markdown/debug.d.ts.map +1 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/decorate.d.ts +5 -1
- package/dist/types/src/extensions/language/markdown/decorate.d.ts.map +1 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/formatting.d.ts +11 -2
- package/dist/types/src/extensions/language/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/formatting.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/highlight.d.ts +16 -12
- package/dist/types/src/extensions/language/markdown/highlight.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/image.test.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/index.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/link.d.ts +25 -0
- package/dist/types/src/extensions/language/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/link.test.d.ts +2 -0
- package/dist/types/src/extensions/language/markdown/link.test.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/parser.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/styles.d.ts +3 -0
- package/dist/types/src/extensions/language/markdown/styles.d.ts.map +1 -0
- package/dist/types/src/extensions/language/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/language/mermaid/index.d.ts +2 -0
- package/dist/types/src/extensions/language/mermaid/index.d.ts.map +1 -0
- package/dist/types/src/extensions/language/mermaid/mermaid.d.ts +18 -0
- package/dist/types/src/extensions/language/mermaid/mermaid.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/extended-markdown.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/extended-markdown.test.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/index.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/stub.d.ts +76 -0
- package/dist/types/src/extensions/language/xml/stub.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/widgets/anchor.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/widgets/index.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/xml-block-decoration.d.ts +48 -0
- package/dist/types/src/extensions/language/xml/xml-block-decoration.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/xml-formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/{tags → language/xml}/xml-tags.d.ts +12 -1
- package/dist/types/src/extensions/language/xml/xml-tags.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/xml-tags.test.d.ts +2 -0
- package/dist/types/src/extensions/language/xml/xml-tags.test.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/xml-util.d.ts.map +1 -0
- package/dist/types/src/extensions/language/xml/xml-util.test.d.ts.map +1 -0
- package/dist/types/src/extensions/review/change-bar.d.ts +29 -0
- package/dist/types/src/extensions/review/change-bar.d.ts.map +1 -0
- package/dist/types/src/extensions/{comments.d.ts → review/comments.d.ts} +56 -38
- package/dist/types/src/extensions/review/comments.d.ts.map +1 -0
- package/dist/types/src/extensions/review/comments.test.d.ts +2 -0
- package/dist/types/src/extensions/review/comments.test.d.ts.map +1 -0
- package/dist/types/src/extensions/review/diff.d.ts +131 -0
- package/dist/types/src/extensions/review/diff.d.ts.map +1 -0
- package/dist/types/src/extensions/review/diff.test.d.ts +2 -0
- package/dist/types/src/extensions/review/diff.test.d.ts.map +1 -0
- package/dist/types/src/extensions/review/index.d.ts +7 -0
- package/dist/types/src/extensions/review/index.d.ts.map +1 -0
- package/dist/types/src/extensions/review/suggest.d.ts +89 -0
- package/dist/types/src/extensions/review/suggest.d.ts.map +1 -0
- package/dist/types/src/extensions/review/suggest.test.d.ts +2 -0
- package/dist/types/src/extensions/review/suggest.test.d.ts.map +1 -0
- package/dist/types/src/extensions/review/suggestions-overlay.d.ts +25 -0
- package/dist/types/src/extensions/review/suggestions-overlay.d.ts.map +1 -0
- package/dist/types/src/extensions/review/suggestions-overlay.test.d.ts +2 -0
- package/dist/types/src/extensions/review/suggestions-overlay.test.d.ts.map +1 -0
- package/dist/types/src/extensions/review/track-changes.d.ts +27 -0
- package/dist/types/src/extensions/review/track-changes.d.ts.map +1 -0
- package/dist/types/src/extensions/review/track-changes.test.d.ts +2 -0
- package/dist/types/src/extensions/review/track-changes.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{busy.d.ts → state/busy.d.ts} +1 -0
- package/dist/types/src/extensions/state/busy.d.ts.map +1 -0
- package/dist/types/src/extensions/{focus.d.ts → state/focus.d.ts} +4 -0
- package/dist/types/src/extensions/state/focus.d.ts.map +1 -0
- package/dist/types/src/extensions/state/index.d.ts +5 -0
- package/dist/types/src/extensions/state/index.d.ts.map +1 -0
- package/dist/types/src/extensions/state/modal.d.ts.map +1 -0
- package/dist/types/src/extensions/{selection.d.ts → state/selection.d.ts} +1 -1
- package/dist/types/src/extensions/state/selection.d.ts.map +1 -0
- package/dist/types/src/extensions/state/selection.test.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/index.d.ts +4 -0
- package/dist/types/src/extensions/streaming/index.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/pending/index.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/pending/pending-text-stream.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/pending/pending-text-stream.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{pending → streaming/pending}/pending-text.d.ts +1 -0
- package/dist/types/src/extensions/streaming/pending/pending-text.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/pending/pending-text.test.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/scrolling/auto-scroll.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/scrolling/crawler.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/scrolling/index.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/scrolling/scroll-past-end.d.ts +4 -0
- package/dist/types/src/extensions/streaming/scrolling/scroll-past-end.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/scrolling/scrollbar-autohide.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/scrolling/scroller.d.ts.map +1 -0
- package/dist/types/src/extensions/{typewriter.d.ts → streaming/typewriter.d.ts} +12 -12
- package/dist/types/src/extensions/streaming/typewriter.d.ts.map +1 -0
- package/dist/types/src/extensions/streaming/typewriter.test.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/blocks.d.ts +52 -0
- package/dist/types/src/extensions/structure/blocks/blocks.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/blocks.test.d.ts +2 -0
- package/dist/types/src/extensions/structure/blocks/blocks.test.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/drag.d.ts +57 -0
- package/dist/types/src/extensions/structure/blocks/drag.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/index.d.ts +5 -0
- package/dist/types/src/extensions/structure/blocks/index.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/selection.d.ts +47 -0
- package/dist/types/src/extensions/structure/blocks/selection.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/selection.test.d.ts +2 -0
- package/dist/types/src/extensions/structure/blocks/selection.test.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/blocks/types.d.ts +17 -0
- package/dist/types/src/extensions/structure/blocks/types.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/folding/folding.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/folding/index.d.ts +3 -0
- package/dist/types/src/extensions/structure/folding/index.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/folding/turns.d.ts +55 -0
- package/dist/types/src/extensions/structure/folding/turns.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/folding/turns.test.d.ts +2 -0
- package/dist/types/src/extensions/structure/folding/turns.test.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/index.d.ts +4 -0
- package/dist/types/src/extensions/structure/index.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/commands.d.ts +31 -0
- package/dist/types/src/extensions/structure/outliner/commands.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/dnd.d.ts +43 -0
- package/dist/types/src/extensions/structure/outliner/dnd.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/dnd.test.d.ts +2 -0
- package/dist/types/src/extensions/structure/outliner/dnd.test.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/editor.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/editor.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/index.d.ts +1 -0
- package/dist/types/src/extensions/structure/outliner/index.d.ts.map +1 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/menu.d.ts +1 -0
- package/dist/types/src/extensions/structure/outliner/menu.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/outliner.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/outliner.test.d.ts.map +1 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/tree.d.ts +1 -1
- package/dist/types/src/extensions/structure/outliner/tree.d.ts.map +1 -0
- package/dist/types/src/extensions/structure/outliner/tree.test.d.ts.map +1 -0
- package/dist/types/src/headless.d.ts +4 -0
- package/dist/types/src/headless.d.ts.map +1 -0
- package/dist/types/src/styles/theme.d.ts +1 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/util/util.d.ts +2 -0
- package/dist/types/src/util/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +48 -42
- package/src/defaults.ts +1 -1
- package/src/extensions/{bookmarks.ts → behavior/bookmarks.ts} +24 -14
- package/src/extensions/behavior/index.ts +9 -0
- package/src/extensions/{listener.ts → behavior/listener.ts} +4 -1
- package/src/extensions/{spacing.ts → behavior/spacing.ts} +8 -2
- package/src/extensions/{submit.ts → behavior/submit.ts} +2 -10
- package/src/extensions/{automerge → collab/automerge}/automerge.test.tsx +4 -4
- package/src/extensions/{automerge → collab/automerge}/automerge.ts +7 -4
- package/src/extensions/{automerge → collab/automerge}/cursor.ts +1 -1
- package/src/extensions/{automerge → collab/automerge}/defs.ts +4 -1
- package/src/extensions/{automerge → collab/automerge}/index.ts +1 -0
- package/src/extensions/{automerge → collab/automerge}/sync.ts +1 -2
- package/src/extensions/{automerge → collab/automerge}/update-automerge.ts +4 -0
- package/src/extensions/{automerge → collab/automerge}/update-codemirror.ts +5 -1
- package/src/extensions/{awareness → collab/awareness}/awareness-provider.ts +3 -4
- package/src/extensions/{awareness → collab/awareness}/awareness.ts +19 -16
- package/src/extensions/collab/index.ts +6 -0
- package/src/extensions/{autocomplete → completion}/autocomplete.ts +7 -5
- package/src/extensions/{autocomplete → completion}/index.ts +2 -1
- package/src/extensions/{autocomplete → completion}/match.ts +2 -2
- package/src/extensions/{mention.ts → completion/mention.ts} +3 -0
- package/src/extensions/{autocomplete → completion}/placeholder.ts +1 -1
- package/src/extensions/completion/typeahead.ts +97 -0
- package/src/extensions/{factories.ts → core/factories.ts} +35 -13
- package/src/extensions/core/index.ts +6 -0
- package/src/extensions/{modes.ts → core/modes.ts} +4 -1
- package/src/extensions/{debug.ts → debug/debug.ts} +3 -0
- package/src/extensions/debug/index.ts +5 -0
- package/src/extensions/{annotations.ts → decoration/annotations.ts} +12 -10
- package/src/extensions/decoration/assistant.ts +225 -0
- package/src/extensions/{fader.ts → decoration/fader.ts} +17 -19
- package/src/extensions/{hashtag.ts → decoration/hashtag.ts} +35 -28
- package/src/extensions/decoration/index.ts +11 -0
- package/src/extensions/{marker.ts → decoration/marker.ts} +18 -18
- package/src/extensions/{pos.test.ts → decoration/pos.test.ts} +57 -1
- package/src/extensions/{pos.ts → decoration/pos.ts} +165 -31
- package/src/extensions/{blast.ts → demo/blast.ts} +3 -0
- package/src/extensions/demo/index.ts +6 -0
- package/src/extensions/{snippets.ts → demo/snippets.ts} +5 -1
- package/src/extensions/index.ts +10 -33
- package/src/extensions/language/index.ts +8 -0
- package/src/extensions/language/json/index.ts +5 -0
- package/src/extensions/{json.ts → language/json/json.ts} +11 -6
- package/src/extensions/{markdown → language/markdown}/action.ts +1 -1
- package/src/extensions/{markdown → language/markdown}/bundle.ts +7 -1
- package/src/extensions/{markdown → language/markdown}/changes.test.ts +2 -2
- package/src/extensions/{markdown → language/markdown}/changes.ts +2 -2
- package/src/extensions/{markdown → language/markdown}/debug.ts +3 -0
- package/src/extensions/{markdown → language/markdown}/decorate.ts +96 -85
- package/src/extensions/{markdown → language/markdown}/formatting.test.ts +88 -1
- package/src/extensions/{markdown → language/markdown}/formatting.ts +193 -74
- package/src/extensions/{markdown → language/markdown}/highlight.ts +42 -41
- package/src/extensions/{markdown → language/markdown}/image.test.ts +1 -1
- package/src/extensions/{markdown → language/markdown}/image.ts +6 -6
- package/src/extensions/language/markdown/link.test.ts +58 -0
- package/src/extensions/language/markdown/link.ts +109 -0
- package/src/extensions/{markdown → language/markdown}/parser.test.ts +0 -28
- package/src/extensions/{markdown → language/markdown}/styles.ts +38 -7
- package/src/extensions/{markdown → language/markdown}/table.ts +5 -5
- package/src/extensions/language/mermaid/index.ts +5 -0
- package/src/extensions/language/mermaid/mermaid.ts +44 -0
- package/src/extensions/{tags → language/xml}/DESIGN.md +3 -3
- package/src/extensions/{tags → language/xml}/extended-markdown.test.ts +2 -1
- package/src/extensions/{tags → language/xml}/extended-markdown.ts +2 -4
- package/src/extensions/language/xml/stub.ts +233 -0
- package/src/extensions/language/xml/xml-block-decoration.ts +165 -0
- package/src/extensions/{tags → language/xml}/xml-formatting.ts +54 -38
- package/src/extensions/language/xml/xml-tags.test.ts +588 -0
- package/src/extensions/{tags → language/xml}/xml-tags.ts +165 -66
- package/src/extensions/{tags → language/xml}/xml-util.test.ts +2 -2
- package/src/extensions/review/change-bar.ts +94 -0
- package/src/extensions/review/comments.test.ts +72 -0
- package/src/extensions/{comments.ts → review/comments.ts} +395 -267
- package/src/extensions/review/diff.test.ts +405 -0
- package/src/extensions/review/diff.ts +502 -0
- package/src/extensions/review/index.ts +10 -0
- package/src/extensions/review/suggest.test.ts +170 -0
- package/src/extensions/review/suggest.ts +512 -0
- package/src/extensions/review/suggestions-overlay.test.ts +58 -0
- package/src/extensions/review/suggestions-overlay.ts +50 -0
- package/src/extensions/review/track-changes.test.ts +101 -0
- package/src/extensions/review/track-changes.ts +215 -0
- package/src/extensions/{busy.ts → state/busy.ts} +1 -0
- package/src/extensions/{focus.ts → state/focus.ts} +4 -0
- package/src/extensions/state/index.ts +8 -0
- package/src/extensions/{selection.ts → state/selection.ts} +3 -3
- package/src/extensions/streaming/index.ts +7 -0
- package/src/extensions/{pending → streaming/pending}/pending-text-stream.ts +10 -3
- package/src/extensions/{pending → streaming/pending}/pending-text.test.ts +1 -1
- package/src/extensions/{pending → streaming/pending}/pending-text.ts +20 -19
- package/src/extensions/{scrolling → streaming/scrolling}/auto-scroll.ts +9 -6
- package/src/extensions/{scrolling → streaming/scrolling}/scroll-past-end.ts +1 -0
- package/src/extensions/{scrolling → streaming/scrolling}/scrollbar-autohide.ts +13 -11
- package/src/extensions/{typewriter.ts → streaming/typewriter.ts} +46 -47
- package/src/extensions/structure/blocks/DESIGN.md +134 -0
- package/src/extensions/structure/blocks/blocks.test.ts +147 -0
- package/src/extensions/structure/blocks/blocks.ts +219 -0
- package/src/extensions/structure/blocks/drag.ts +996 -0
- package/src/extensions/structure/blocks/index.ts +8 -0
- package/src/extensions/structure/blocks/selection.test.ts +56 -0
- package/src/extensions/structure/blocks/selection.ts +279 -0
- package/src/extensions/structure/blocks/types.ts +22 -0
- package/src/extensions/{folding.ts → structure/folding/folding.ts} +12 -10
- package/src/extensions/structure/folding/index.ts +6 -0
- package/src/extensions/structure/folding/turns.test.ts +72 -0
- package/src/extensions/structure/folding/turns.ts +209 -0
- package/src/extensions/structure/index.ts +7 -0
- package/src/extensions/structure/outliner/DESIGN.md +183 -0
- package/src/extensions/structure/outliner/SPEC.mdl +305 -0
- package/src/extensions/{outliner → structure/outliner}/commands.ts +125 -42
- package/src/extensions/structure/outliner/dnd.test.ts +142 -0
- package/src/extensions/structure/outliner/dnd.ts +375 -0
- package/src/extensions/structure/outliner/editor.test.ts +85 -0
- package/src/extensions/{outliner → structure/outliner}/editor.ts +14 -9
- package/src/extensions/{outliner → structure/outliner}/index.ts +1 -0
- package/src/extensions/{outliner → structure/outliner}/menu.ts +48 -25
- package/src/extensions/structure/outliner/outliner.test.ts +193 -0
- package/src/extensions/structure/outliner/outliner.ts +183 -0
- package/src/extensions/{outliner → structure/outliner}/tree.test.ts +2 -2
- package/src/extensions/{outliner → structure/outliner}/tree.ts +1 -1
- package/src/headless.ts +13 -0
- package/src/styles/theme.ts +3 -1
- package/src/util/util.ts +3 -0
- package/dist/lib/browser/index.mjs +0 -9594
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/types/index.mjs +0 -33
- package/dist/lib/browser/types/index.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -9596
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/types/index.mjs +0 -35
- package/dist/lib/node-esm/types/index.mjs.map +0 -7
- package/dist/types/src/extensions/annotations.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/index.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/match.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +0 -1
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/defs.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/index.d.ts +0 -2
- package/dist/types/src/extensions/automerge/index.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/sync.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +0 -1
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness/index.d.ts.map +0 -1
- package/dist/types/src/extensions/blast.d.ts.map +0 -1
- package/dist/types/src/extensions/blocks.d.ts +0 -2
- package/dist/types/src/extensions/blocks.d.ts.map +0 -1
- package/dist/types/src/extensions/bookmarks.d.ts.map +0 -1
- package/dist/types/src/extensions/busy.d.ts.map +0 -1
- package/dist/types/src/extensions/comments.d.ts.map +0 -1
- package/dist/types/src/extensions/debug.d.ts.map +0 -1
- package/dist/types/src/extensions/dnd.d.ts.map +0 -1
- package/dist/types/src/extensions/factories.d.ts.map +0 -1
- package/dist/types/src/extensions/factories.test.d.ts.map +0 -1
- package/dist/types/src/extensions/fader.d.ts.map +0 -1
- package/dist/types/src/extensions/focus.d.ts.map +0 -1
- package/dist/types/src/extensions/folding.d.ts.map +0 -1
- package/dist/types/src/extensions/hashtag.d.ts +0 -3
- package/dist/types/src/extensions/hashtag.d.ts.map +0 -1
- package/dist/types/src/extensions/json.d.ts +0 -7
- package/dist/types/src/extensions/json.d.ts.map +0 -1
- package/dist/types/src/extensions/listener.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/action.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/changes.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/changes.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/debug.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/image.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/image.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/index.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/link.d.ts +0 -7
- package/dist/types/src/extensions/markdown/link.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/parser.test.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/styles.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/table.d.ts.map +0 -1
- package/dist/types/src/extensions/marker.d.ts.map +0 -1
- package/dist/types/src/extensions/mention.d.ts.map +0 -1
- package/dist/types/src/extensions/modal.d.ts.map +0 -1
- package/dist/types/src/extensions/modes.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/commands.d.ts +0 -10
- package/dist/types/src/extensions/outliner/commands.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/editor.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/editor.test.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/index.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/menu.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/outliner.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/outliner.test.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/selection.d.ts +0 -12
- package/dist/types/src/extensions/outliner/selection.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/tree.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner/tree.test.d.ts.map +0 -1
- package/dist/types/src/extensions/pending/index.d.ts.map +0 -1
- package/dist/types/src/extensions/pending/pending-text-stream.d.ts.map +0 -1
- package/dist/types/src/extensions/pending/pending-text-stream.test.d.ts.map +0 -1
- package/dist/types/src/extensions/pending/pending-text.d.ts.map +0 -1
- package/dist/types/src/extensions/pending/pending-text.test.d.ts.map +0 -1
- package/dist/types/src/extensions/pos.d.ts.map +0 -1
- package/dist/types/src/extensions/pos.test.d.ts.map +0 -1
- package/dist/types/src/extensions/replacer.d.ts.map +0 -1
- package/dist/types/src/extensions/replacer.test.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling/auto-scroll.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling/crawler.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling/index.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling/scroll-past-end.d.ts +0 -3
- package/dist/types/src/extensions/scrolling/scroll-past-end.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling/scrollbar-autohide.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling/scroller.d.ts.map +0 -1
- package/dist/types/src/extensions/selection.d.ts.map +0 -1
- package/dist/types/src/extensions/selection.test.d.ts.map +0 -1
- package/dist/types/src/extensions/snippets.d.ts.map +0 -1
- package/dist/types/src/extensions/spacing.d.ts.map +0 -1
- package/dist/types/src/extensions/state.d.ts +0 -2
- package/dist/types/src/extensions/state.d.ts.map +0 -1
- package/dist/types/src/extensions/submit.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/index.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/stub.d.ts +0 -35
- package/dist/types/src/extensions/tags/stub.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/widgets/anchor.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/widgets/index.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-block-decoration.d.ts +0 -31
- package/dist/types/src/extensions/tags/xml-block-decoration.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-formatting.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-util.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/xml-util.test.d.ts.map +0 -1
- package/dist/types/src/extensions/typewriter.d.ts.map +0 -1
- package/dist/types/src/extensions/typewriter.test.d.ts.map +0 -1
- package/src/extensions/autocomplete/typeahead.ts +0 -87
- package/src/extensions/blocks.ts +0 -131
- package/src/extensions/markdown/link.ts +0 -49
- package/src/extensions/outliner/editor.test.ts +0 -33
- package/src/extensions/outliner/outliner.test.ts +0 -99
- package/src/extensions/outliner/outliner.ts +0 -166
- package/src/extensions/outliner/selection.ts +0 -50
- package/src/extensions/state.ts +0 -7
- package/src/extensions/tags/stub.ts +0 -80
- package/src/extensions/tags/xml-block-decoration.ts +0 -123
- package/dist/types/src/extensions/{dnd.d.ts → behavior/dnd.d.ts} +0 -0
- package/dist/types/src/extensions/{submit.d.ts → behavior/submit.d.ts} +0 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/automerge.d.ts +0 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/automerge.test.d.ts +0 -0
- package/dist/types/src/extensions/{automerge → collab/automerge}/sync.d.ts +0 -0
- package/dist/types/src/extensions/{awareness → collab/awareness}/awareness-provider.d.ts +0 -0
- package/dist/types/src/extensions/{awareness → collab/awareness}/index.d.ts +0 -0
- package/dist/types/src/extensions/{autocomplete → completion}/autocomplete.d.ts +0 -0
- package/dist/types/src/extensions/{autocomplete → completion}/placeholder.d.ts +0 -0
- package/dist/types/src/extensions/{factories.test.d.ts → core/factories.test.d.ts} +0 -0
- package/dist/types/src/extensions/{fader.d.ts → decoration/fader.d.ts} +0 -0
- package/dist/types/src/extensions/{marker.d.ts → decoration/marker.d.ts} +0 -0
- package/dist/types/src/extensions/{pos.test.d.ts → decoration/pos.test.d.ts} +0 -0
- package/dist/types/src/extensions/{replacer.test.d.ts → decoration/replacer.test.d.ts} +0 -0
- package/dist/types/src/extensions/{snippets.d.ts → demo/snippets.d.ts} +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/action.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/bundle.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/changes.test.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/formatting.test.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/image.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/image.test.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/index.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/parser.test.d.ts +0 -0
- package/dist/types/src/extensions/{markdown → language/markdown}/table.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/extended-markdown.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/extended-markdown.test.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/index.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/widgets/anchor.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/widgets/index.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/xml-formatting.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/xml-util.d.ts +0 -0
- package/dist/types/src/extensions/{tags → language/xml}/xml-util.test.d.ts +0 -0
- package/dist/types/src/extensions/{modal.d.ts → state/modal.d.ts} +0 -0
- package/dist/types/src/extensions/{selection.test.d.ts → state/selection.test.d.ts} +0 -0
- package/dist/types/src/extensions/{pending → streaming/pending}/index.d.ts +0 -0
- package/dist/types/src/extensions/{pending → streaming/pending}/pending-text-stream.d.ts +0 -0
- package/dist/types/src/extensions/{pending → streaming/pending}/pending-text-stream.test.d.ts +0 -0
- package/dist/types/src/extensions/{pending → streaming/pending}/pending-text.test.d.ts +0 -0
- package/dist/types/src/extensions/{scrolling → streaming/scrolling}/auto-scroll.d.ts +0 -0
- package/dist/types/src/extensions/{scrolling → streaming/scrolling}/crawler.d.ts +0 -0
- package/dist/types/src/extensions/{scrolling → streaming/scrolling}/index.d.ts +0 -0
- package/dist/types/src/extensions/{scrolling → streaming/scrolling}/scrollbar-autohide.d.ts +0 -0
- package/dist/types/src/extensions/{scrolling → streaming/scrolling}/scroller.d.ts +0 -0
- package/dist/types/src/extensions/{typewriter.test.d.ts → streaming/typewriter.test.d.ts} +0 -0
- package/dist/types/src/extensions/{folding.d.ts → structure/folding/folding.d.ts} +0 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/editor.d.ts +0 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/editor.test.d.ts +0 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/outliner.d.ts +0 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/outliner.test.d.ts +0 -0
- package/dist/types/src/extensions/{outliner → structure/outliner}/tree.test.d.ts +0 -0
- package/src/extensions/{dnd.ts → behavior/dnd.ts} +29 -29
- package/src/extensions/{awareness → collab/awareness}/index.ts +0 -0
- package/src/extensions/{factories.test.ts → core/factories.test.ts} +0 -0
- package/src/extensions/{replacer.test.ts → decoration/replacer.test.ts} +0 -0
- package/src/extensions/{replacer.ts → decoration/replacer.ts} +25 -25
- /package/src/extensions/{markdown → language/markdown}/index.ts +0 -0
- /package/src/extensions/{tags → language/xml}/index.ts +0 -0
- /package/src/extensions/{tags → language/xml}/testing/text.md +0 -0
- /package/src/extensions/{tags → language/xml}/testing/text.txt +0 -0
- /package/src/extensions/{tags → language/xml}/widgets/anchor.ts +0 -0
- /package/src/extensions/{tags → language/xml}/widgets/index.ts +0 -0
- /package/src/extensions/{tags → language/xml}/xml-util.ts +0 -0
- /package/src/extensions/{modal.ts → state/modal.ts} +0 -0
- /package/src/extensions/{selection.test.ts → state/selection.test.ts} +0 -0
- /package/src/extensions/{pending → streaming/pending}/index.ts +0 -0
- /package/src/extensions/{pending → streaming/pending}/pending-text-stream.test.ts +0 -0
- /package/src/extensions/{scrolling → streaming/scrolling}/crawler.ts +0 -0
- /package/src/extensions/{scrolling → streaming/scrolling}/index.ts +0 -0
- /package/src/extensions/{scrolling → streaming/scrolling}/scroller.ts +0 -0
- /package/src/extensions/{typewriter.test.ts → streaming/typewriter.test.ts} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { syntaxTree } from '@codemirror/language';
|
|
5
|
+
import { syntaxTree, syntaxTreeAvailable } from '@codemirror/language';
|
|
6
6
|
import { type EditorState, type Extension, Prec, RangeSetBuilder, StateEffect, StateField } from '@codemirror/state';
|
|
7
7
|
import {
|
|
8
8
|
Decoration,
|
|
@@ -17,9 +17,9 @@ import { type FunctionComponent } from 'react';
|
|
|
17
17
|
|
|
18
18
|
import { log } from '@dxos/log';
|
|
19
19
|
|
|
20
|
-
import { type Range } from '
|
|
21
|
-
import { decorationSetToArray } from '
|
|
22
|
-
import { crawlerLineEffect } from '
|
|
20
|
+
import { type Range } from '../../../types';
|
|
21
|
+
import { decorationSetToArray, escapeRegExpSource } from '../../../util';
|
|
22
|
+
import { crawlerLineEffect } from '../../streaming/scrolling';
|
|
23
23
|
import { StubWidget, type XmlWidgetNotifier } from './stub';
|
|
24
24
|
import { nodeToJson } from './xml-util';
|
|
25
25
|
|
|
@@ -52,10 +52,10 @@ export type XmlEventHandler<TEvent = any> = (event: TEvent) => void;
|
|
|
52
52
|
*/
|
|
53
53
|
export type XmlWidgetProps<TProps = any, TContext = any> = TProps & {
|
|
54
54
|
_tag: string;
|
|
55
|
+
view?: EditorView;
|
|
55
56
|
range: { from: number; to: number };
|
|
56
57
|
children?: any[];
|
|
57
58
|
context?: TContext;
|
|
58
|
-
view?: EditorView;
|
|
59
59
|
onEvent?: XmlEventHandler;
|
|
60
60
|
};
|
|
61
61
|
|
|
@@ -104,6 +104,13 @@ export type XmlWidgetDef = {
|
|
|
104
104
|
* Block widgets are created for Image nodes; inline widgets for Link nodes.
|
|
105
105
|
*/
|
|
106
106
|
urlSchemes?: string[];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Reserved block height (px) derived from the widget's props (e.g. parsed from the image label),
|
|
110
|
+
* used to size the placeholder and CodeMirror's viewport estimate before the React content mounts.
|
|
111
|
+
* Only meaningful for block widgets.
|
|
112
|
+
*/
|
|
113
|
+
estimatedHeight?: (props: XmlWidgetProps) => number | undefined;
|
|
107
114
|
};
|
|
108
115
|
|
|
109
116
|
export type XmlWidgetRegistry = Record<string, XmlWidgetDef>;
|
|
@@ -117,9 +124,6 @@ export const getXmlTextChild = (children: any[]): string | null => {
|
|
|
117
124
|
const xmlWidgetId = (explicit: unknown, fallback: string): string =>
|
|
118
125
|
typeof explicit === 'string' && explicit.length > 0 ? explicit : fallback;
|
|
119
126
|
|
|
120
|
-
/** Escapes a string for safe embedding in RegExp source (tag names from the registry). */
|
|
121
|
-
const escapeRegExpSource = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
122
|
-
|
|
123
127
|
/**
|
|
124
128
|
* Update context.
|
|
125
129
|
*/
|
|
@@ -130,6 +134,12 @@ export const xmlTagContextEffect = StateEffect.define<any>();
|
|
|
130
134
|
*/
|
|
131
135
|
export const xmlTagResetEffect = StateEffect.define();
|
|
132
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Force a full decoration rebuild without a document change — dispatched once background parsing of a
|
|
139
|
+
* long document completes, so blocks past the initial parse window are decorated without needing an edit.
|
|
140
|
+
*/
|
|
141
|
+
export const xmlTagRebuildEffect = StateEffect.define();
|
|
142
|
+
|
|
133
143
|
/**
|
|
134
144
|
* Update widget.
|
|
135
145
|
*/
|
|
@@ -153,6 +163,44 @@ export type XmlWidgetState = {
|
|
|
153
163
|
|
|
154
164
|
export type { XmlWidgetNotifier };
|
|
155
165
|
|
|
166
|
+
export type XmlTagsOptions = {
|
|
167
|
+
/** Tag registry. */
|
|
168
|
+
registry?: XmlWidgetRegistry;
|
|
169
|
+
|
|
170
|
+
/** Tags to bookmark for navigation. */
|
|
171
|
+
bookmarks?: string[];
|
|
172
|
+
|
|
173
|
+
/** Called when widgets are mounted or unmounted. */
|
|
174
|
+
setWidgets?: (widgets: XmlWidgetState[]) => void;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Implements custom XML tags via CodeMirror-native Widgets and portaled React/Solid components.
|
|
179
|
+
*
|
|
180
|
+
* Basic mechanism:
|
|
181
|
+
* - Decorations are created from XML tags that matched the provided Widget registry.
|
|
182
|
+
* - Native widgets are rendered inline.
|
|
183
|
+
* - React/Solid widgets are rendered in portals outside of the editor via the StubWidget.
|
|
184
|
+
* - Widget state can be update via effects.
|
|
185
|
+
* - NOTE: Widget state may be updated BEFORE the widget is mounted.
|
|
186
|
+
*/
|
|
187
|
+
export const xmlTags = ({ registry, setWidgets, bookmarks }: XmlTagsOptions = {}): Extension => {
|
|
188
|
+
const debug = registry ? Object.values(registry).some((def) => def.debug) : false;
|
|
189
|
+
const notifier = createWidgetMap(setWidgets, debug);
|
|
190
|
+
const widgetDecorationsField = createWidgetDecorationsField(registry, notifier);
|
|
191
|
+
|
|
192
|
+
return [
|
|
193
|
+
widgetContextStateField,
|
|
194
|
+
widgetStateMapStateField,
|
|
195
|
+
widgetDecorationsField,
|
|
196
|
+
createWidgetUpdatePlugin(widgetDecorationsField, notifier),
|
|
197
|
+
createParseCompletionPlugin(),
|
|
198
|
+
createNavigationEffectPlugin(widgetDecorationsField, bookmarks),
|
|
199
|
+
bookmarks?.length ? Prec.highest(keyHandlers) : [],
|
|
200
|
+
debug ? createScrollJumpMonitor() : [],
|
|
201
|
+
];
|
|
202
|
+
};
|
|
203
|
+
|
|
156
204
|
/**
|
|
157
205
|
* Context state.
|
|
158
206
|
*/
|
|
@@ -175,76 +223,115 @@ const widgetContextStateField = StateField.define<any>({
|
|
|
175
223
|
const widgetStateMapStateField = StateField.define<XmlWidgetStateMap>({
|
|
176
224
|
create: () => ({}),
|
|
177
225
|
update: (map, tr) => {
|
|
226
|
+
// Reduce over every effect: a transaction may carry several updates (or a reset followed by them),
|
|
227
|
+
// and returning on the first would silently drop the rest.
|
|
228
|
+
let next = map;
|
|
178
229
|
for (const effect of tr.effects) {
|
|
179
230
|
if (effect.is(xmlTagResetEffect)) {
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (effect.is(xmlTagUpdateEffect)) {
|
|
231
|
+
next = {};
|
|
232
|
+
} else if (effect.is(xmlTagUpdateEffect)) {
|
|
184
233
|
// Update accumulated widget props by id.
|
|
185
234
|
const { id, value } = effect.value;
|
|
186
235
|
log('widget updated', { id, value });
|
|
187
|
-
|
|
188
|
-
return { ...map, [id]: state };
|
|
236
|
+
next = { ...next, [id]: typeof value === 'function' ? value(next[id]) : value };
|
|
189
237
|
}
|
|
190
238
|
}
|
|
191
239
|
|
|
192
|
-
return
|
|
240
|
+
return next;
|
|
193
241
|
},
|
|
194
242
|
});
|
|
195
243
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Debug-only: flag large single-event scroll deltas (the "jump") so they can be correlated with the
|
|
246
|
+
* widget lifecycle trace. A smooth user scroll produces small per-event deltas; a jump-to-top is one
|
|
247
|
+
* big negative delta to near-zero.
|
|
248
|
+
*/
|
|
249
|
+
const createScrollJumpMonitor = () => {
|
|
250
|
+
let last = -1;
|
|
251
|
+
return EditorView.domEventHandlers({
|
|
252
|
+
scroll: (_event, view) => {
|
|
253
|
+
const top = view.scrollDOM.scrollTop;
|
|
254
|
+
if (last >= 0 && Math.abs(top - last) > 600) {
|
|
255
|
+
log.warn('xml-tags: scroll jump', {
|
|
256
|
+
from: Math.round(last),
|
|
257
|
+
to: Math.round(top),
|
|
258
|
+
delta: Math.round(top - last),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
last = top;
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
};
|
|
202
265
|
|
|
203
|
-
|
|
204
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Re-decorate once the whole document has parsed. `StateField.create` (and incremental rebuilds) only
|
|
268
|
+
* see the syntax tree parsed so far, so a block past CodeMirror's initial background-parse window is
|
|
269
|
+
* not decorated until some later transaction — previously it appeared only after the first edit. This
|
|
270
|
+
* dispatches a one-shot rebuild when the full tree becomes available (re-armed on each edit).
|
|
271
|
+
*/
|
|
272
|
+
const createParseCompletionPlugin = () => {
|
|
273
|
+
let rebuiltForLength = -1;
|
|
274
|
+
return EditorView.updateListener.of((update) => {
|
|
275
|
+
if (update.docChanged) {
|
|
276
|
+
rebuiltForLength = -1;
|
|
277
|
+
}
|
|
278
|
+
const length = update.state.doc.length;
|
|
279
|
+
if (rebuiltForLength !== length && syntaxTreeAvailable(update.state, length)) {
|
|
280
|
+
rebuiltForLength = length;
|
|
281
|
+
// Defer: cannot dispatch during an update.
|
|
282
|
+
queueMicrotask(() => update.view.dispatch({ effects: xmlTagRebuildEffect.of(null) }));
|
|
283
|
+
}
|
|
284
|
+
});
|
|
205
285
|
};
|
|
206
286
|
|
|
207
287
|
/**
|
|
208
|
-
*
|
|
288
|
+
* Re-applies the accumulated widget state at mount time.
|
|
209
289
|
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
* - NOTE: Widget state may be updated BEFORE the widget is mounted.
|
|
290
|
+
* A widget's props are baked when its decoration is built, but state can be dispatched before the
|
|
291
|
+
* widget mounts — rehydration after a document reset targets widgets that are still outside
|
|
292
|
+
* CodeMirror's viewport, and `xmlTagUpdateEffect` alone rebuilds no decorations. Such a widget would
|
|
293
|
+
* otherwise mount with the stale props it was built with, since `StubWidget.eq` (id equality) stops a
|
|
294
|
+
* later rebuild from replacing the instance.
|
|
216
295
|
*/
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
return [
|
|
222
|
-
widgetContextStateField,
|
|
223
|
-
widgetStateMapStateField,
|
|
224
|
-
widgetDecorationsField,
|
|
225
|
-
createWidgetUpdatePlugin(widgetDecorationsField, notifier),
|
|
226
|
-
createNavigationEffectPlugin(widgetDecorationsField, bookmarks),
|
|
227
|
-
bookmarks?.length ? Prec.highest(keyHandlers) : [],
|
|
228
|
-
];
|
|
296
|
+
const withCurrentWidgetState = (state: XmlWidgetState): XmlWidgetState => {
|
|
297
|
+
const view: EditorView | undefined = state.props?.view;
|
|
298
|
+
const widgetState = view?.state.field(widgetStateMapStateField, false)?.[state.id];
|
|
299
|
+
return widgetState ? { ...state, props: { ...state.props, ...widgetState } } : state;
|
|
229
300
|
};
|
|
230
301
|
|
|
231
302
|
/**
|
|
232
303
|
* Manages the collection of widgets.
|
|
233
304
|
*/
|
|
234
|
-
const createWidgetMap = (setWidgets?: (widgets: XmlWidgetState[]) => void): XmlWidgetNotifier => {
|
|
305
|
+
const createWidgetMap = (setWidgets?: (widgets: XmlWidgetState[]) => void, debug = false): XmlWidgetNotifier => {
|
|
235
306
|
const widgets = new Map<string, XmlWidgetState>();
|
|
236
307
|
|
|
237
308
|
// TODO(burdon): Batch updates?
|
|
238
309
|
const notifier = {
|
|
239
|
-
mounted: (
|
|
240
|
-
|
|
310
|
+
mounted: (rawState: XmlWidgetState) => {
|
|
311
|
+
const state = withCurrentWidgetState(rawState);
|
|
312
|
+
const isNew = !widgets.has(state.id);
|
|
241
313
|
widgets.set(state.id, state);
|
|
314
|
+
// Only a genuinely new id changes the portal set (blank-frame culprit); re-parents just re-notify.
|
|
315
|
+
if (debug && isNew) {
|
|
316
|
+
log.info('widget-map: mounted', { id: state.id, count: widgets.size });
|
|
317
|
+
}
|
|
318
|
+
setWidgets?.([...widgets.values()]);
|
|
319
|
+
},
|
|
320
|
+
updated: (id: string, widgetState: any) => {
|
|
321
|
+
const current = widgets.get(id);
|
|
322
|
+
if (!current || !widgetState) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
widgets.set(id, { ...current, props: { ...current.props, ...widgetState } });
|
|
242
327
|
setWidgets?.([...widgets.values()]);
|
|
243
328
|
},
|
|
244
329
|
unmounted: (id: string) => {
|
|
245
|
-
const state = widgets.get(id);
|
|
246
|
-
log('widget unmounted', { id, tag: state?.props._tag });
|
|
247
330
|
widgets.delete(id);
|
|
331
|
+
// A cull drops the portal for a frame before it re-mounts — this is the blank-space window.
|
|
332
|
+
if (debug) {
|
|
333
|
+
log.info('widget-map: unmounted', { id, count: widgets.size });
|
|
334
|
+
}
|
|
248
335
|
setWidgets?.([...widgets.values()]);
|
|
249
336
|
},
|
|
250
337
|
reconcile: (liveIds: Set<string>) => {
|
|
@@ -256,6 +343,9 @@ const createWidgetMap = (setWidgets?: (widgets: XmlWidgetState[]) => void): XmlW
|
|
|
256
343
|
}
|
|
257
344
|
}
|
|
258
345
|
if (changed) {
|
|
346
|
+
if (debug) {
|
|
347
|
+
log.info('widget-map: reconcile pruned', { live: [...liveIds], count: widgets.size });
|
|
348
|
+
}
|
|
259
349
|
setWidgets?.([...widgets.values()]);
|
|
260
350
|
}
|
|
261
351
|
},
|
|
@@ -382,22 +472,11 @@ const createWidgetUpdatePlugin = (
|
|
|
382
472
|
notifier.reconcile(liveIds);
|
|
383
473
|
}
|
|
384
474
|
|
|
385
|
-
//
|
|
475
|
+
// Re-render widgets whose state changed. Widgets not yet mounted pick their state up at mount
|
|
476
|
+
// time instead (see `withCurrentWidgetState`).
|
|
386
477
|
for (const effect of update.transactions.flatMap((tr) => tr.effects)) {
|
|
387
478
|
if (effect.is(xmlTagUpdateEffect)) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
// Find and render widget.
|
|
391
|
-
for (const range of decorationSetToArray(decorations)) {
|
|
392
|
-
const deco = range.value;
|
|
393
|
-
const widget = deco?.spec?.widget;
|
|
394
|
-
|
|
395
|
-
// NOTE: If the widget has not yet been mounted, then the root will be null.
|
|
396
|
-
if (widget && widget instanceof StubWidget && widget.id === effect.value.id && widget.root) {
|
|
397
|
-
const props = { ...widget.props, ...widgetState };
|
|
398
|
-
notifier.mounted({ id: widget.id, props, root: widget.root, Component: widget.Component });
|
|
399
|
-
}
|
|
400
|
-
}
|
|
479
|
+
notifier.updated(effect.value.id, widgetStateMap[effect.value.id]);
|
|
401
480
|
}
|
|
402
481
|
}
|
|
403
482
|
}
|
|
@@ -435,6 +514,16 @@ const createWidgetDecorationsField = (registry: XmlWidgetRegistry = {}, notifier
|
|
|
435
514
|
}
|
|
436
515
|
return { from: 0, decorations: Decoration.none };
|
|
437
516
|
}
|
|
517
|
+
// Full rebuild once background parsing has advanced (no document change).
|
|
518
|
+
if (effect.is(xmlTagRebuildEffect)) {
|
|
519
|
+
return buildDecorations(tr.state, { from: 0, to: tr.state.doc.length }, registry, notifier, urlSchemeMap);
|
|
520
|
+
}
|
|
521
|
+
// Widget props capture the context at build time and `StubWidget.eq` compares ids, so a context
|
|
522
|
+
// set after the first build would otherwise never reach a widget — leaving its callbacks bound to
|
|
523
|
+
// `undefined` for the life of the document.
|
|
524
|
+
if (effect.is(xmlTagContextEffect)) {
|
|
525
|
+
return buildDecorations(tr.state, { from: 0, to: tr.state.doc.length }, registry, notifier, urlSchemeMap);
|
|
526
|
+
}
|
|
438
527
|
}
|
|
439
528
|
|
|
440
529
|
if (tr.docChanged) {
|
|
@@ -499,6 +588,11 @@ const buildDecorations = (
|
|
|
499
588
|
let last = range.from;
|
|
500
589
|
let streamingFrom: number | undefined;
|
|
501
590
|
|
|
591
|
+
// Per-dxn occurrence counter for position-independent url-scheme widget ids. Keying on document
|
|
592
|
+
// position would change the id on every keystroke above the widget (full rebuild), remounting the
|
|
593
|
+
// portal and flashing the embed; occurrence order is stable because edits above force a full rebuild.
|
|
594
|
+
const dxnOccurrences = new Map<string, number>();
|
|
595
|
+
|
|
502
596
|
tree.iterate({
|
|
503
597
|
from: range.from,
|
|
504
598
|
to: range.to,
|
|
@@ -532,11 +626,13 @@ const buildDecorations = (
|
|
|
532
626
|
...widgetState,
|
|
533
627
|
} satisfies XmlWidgetProps;
|
|
534
628
|
|
|
535
|
-
// Create widget.
|
|
629
|
+
// Create widget. Known-height block widgets get their reserved height so StubWidget's
|
|
630
|
+
// fixed-height keep-alive applies to Component element tags too, not just url-scheme widgets.
|
|
631
|
+
const blockHeight = block ? def.estimatedHeight?.(props) : undefined;
|
|
536
632
|
const widget: WidgetType | undefined = factory
|
|
537
633
|
? (factory(props) ?? undefined)
|
|
538
634
|
: Component
|
|
539
|
-
? new StubWidget(widgetId, Component, props, notifier, false, !!block)
|
|
635
|
+
? new StubWidget(widgetId, Component, props, notifier, false, !!block, blockHeight, def.debug)
|
|
540
636
|
: undefined;
|
|
541
637
|
|
|
542
638
|
// Add decoration.
|
|
@@ -589,7 +685,9 @@ const buildDecorations = (
|
|
|
589
685
|
const [tag, def] = matched;
|
|
590
686
|
const label = state.sliceDoc(markNodes[0].to, markNodes[1].from);
|
|
591
687
|
const nodeRange = { from: node.node.from, to: node.node.to };
|
|
592
|
-
const
|
|
688
|
+
const occurrence = dxnOccurrences.get(dxn) ?? 0;
|
|
689
|
+
dxnOccurrences.set(dxn, occurrence + 1);
|
|
690
|
+
const widgetId = `cm-url-${dxn}-${occurrence}`;
|
|
593
691
|
const widgetState = widgetStateMap[widgetId];
|
|
594
692
|
const props: XmlWidgetProps = {
|
|
595
693
|
id: widgetId,
|
|
@@ -602,10 +700,11 @@ const buildDecorations = (
|
|
|
602
700
|
suggest: isBlock,
|
|
603
701
|
...widgetState,
|
|
604
702
|
};
|
|
703
|
+
const blockHeight = isBlock ? def.estimatedHeight?.(props) : undefined;
|
|
605
704
|
const widget: WidgetType | undefined = def.factory
|
|
606
705
|
? (def.factory(props) ?? undefined)
|
|
607
706
|
: def.Component
|
|
608
|
-
? new StubWidget(widgetId, def.Component, props, notifier, false, isBlock)
|
|
707
|
+
? new StubWidget(widgetId, def.Component, props, notifier, false, isBlock, blockHeight, def.debug)
|
|
609
708
|
: undefined;
|
|
610
709
|
if (widget) {
|
|
611
710
|
builder.add(
|
|
@@ -667,7 +766,7 @@ const buildDecorations = (
|
|
|
667
766
|
const widget: WidgetType | undefined = def.factory
|
|
668
767
|
? (def.factory(mergedProps) ?? undefined)
|
|
669
768
|
: def.Component
|
|
670
|
-
? new StubWidget(widgetId, def.Component, mergedProps, notifier, true)
|
|
769
|
+
? new StubWidget(widgetId, def.Component, mergedProps, notifier, true, undefined, undefined, def.debug)
|
|
671
770
|
: undefined;
|
|
672
771
|
|
|
673
772
|
if (widget) {
|
|
@@ -10,7 +10,7 @@ import { trim } from '@dxos/util';
|
|
|
10
10
|
|
|
11
11
|
import { extendedMarkdown } from './extended-markdown';
|
|
12
12
|
import TEXT from './testing/text.md?raw';
|
|
13
|
-
import { xmlTags } from './xml-tags';
|
|
13
|
+
import { type XmlWidgetRegistry, xmlTags } from './xml-tags';
|
|
14
14
|
import { type Tag, nodeToJson } from './xml-util';
|
|
15
15
|
|
|
16
16
|
type ParsedElement = Tag & {
|
|
@@ -22,7 +22,7 @@ type ParsedElement = Tag & {
|
|
|
22
22
|
* Helper to extract all parsed XML elements from a document.
|
|
23
23
|
* Checks completeness by verifying the Element node has a CloseTag child.
|
|
24
24
|
*/
|
|
25
|
-
const parseElements = (doc: string, registry:
|
|
25
|
+
const parseElements = (doc: string, registry: XmlWidgetRegistry = {}): ParsedElement[] => {
|
|
26
26
|
const state = EditorState.create({
|
|
27
27
|
doc,
|
|
28
28
|
extensions: [extendedMarkdown({ registry }), xmlTags({ registry })],
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type EditorState, type Extension, Facet, RangeSet } from '@codemirror/state';
|
|
6
|
+
import { EditorView, GutterMarker, gutter } from '@codemirror/view';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A change-bar gutter marker: a vertical bar tinted with the author's colour. Full line height by
|
|
10
|
+
* default; `rows` caps it to that many text rows (in `lh` units) — a BLOCK-insert proposal renders
|
|
11
|
+
* as a widget occupying the top rows of its host line, and the bar must cover the proposal's rows
|
|
12
|
+
* without tinting the host line's own text below it.
|
|
13
|
+
*/
|
|
14
|
+
export class ChangeBarMarker extends GutterMarker {
|
|
15
|
+
#colour: string;
|
|
16
|
+
#rows?: number;
|
|
17
|
+
#offsetRows?: number;
|
|
18
|
+
|
|
19
|
+
constructor(colour: string, rows?: number, offsetRows?: number) {
|
|
20
|
+
super();
|
|
21
|
+
this.#colour = colour;
|
|
22
|
+
this.#rows = rows;
|
|
23
|
+
this.#offsetRows = offsetRows;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override eq(other: ChangeBarMarker): boolean {
|
|
27
|
+
return other.#colour === this.#colour && other.#rows === this.#rows && other.#offsetRows === this.#offsetRows;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override toDOM(): HTMLElement {
|
|
31
|
+
const bar = document.createElement('div');
|
|
32
|
+
bar.className = 'cm-change-bar';
|
|
33
|
+
// Attribution colour is per-author (dynamic); the bar geometry lives in the theme class.
|
|
34
|
+
bar.style.background = this.#colour;
|
|
35
|
+
if (this.#rows !== undefined) {
|
|
36
|
+
bar.style.height = `calc(${this.#rows}lh)`;
|
|
37
|
+
}
|
|
38
|
+
// A proposal that STARTS with a newline renders its text below the break; shift the bar with it.
|
|
39
|
+
if (this.#offsetRows) {
|
|
40
|
+
bar.style.marginTop = `calc(${this.#offsetRows}lh)`;
|
|
41
|
+
}
|
|
42
|
+
return bar;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Per-line change-bar markers for one suggestion source, derived from editor state. Contributed by the
|
|
48
|
+
* suggestion extensions (`trackChanges`, `suggestions`) so each can colour its own lines by author.
|
|
49
|
+
*/
|
|
50
|
+
export type ChangeBarProvider = (state: EditorState) => RangeSet<GutterMarker>;
|
|
51
|
+
|
|
52
|
+
const changeBarTheme = EditorView.baseTheme({
|
|
53
|
+
'& .cm-change-bar-gutter': {
|
|
54
|
+
width: '3px',
|
|
55
|
+
paddingInline: '1px',
|
|
56
|
+
},
|
|
57
|
+
'& .cm-change-bar': {
|
|
58
|
+
width: '3px',
|
|
59
|
+
height: '100%',
|
|
60
|
+
borderRadius: '1px',
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Providers of per-line change bars. `enables` adds the single shared gutter (+ theme) once when any
|
|
66
|
+
* provider is present — identical extension instances dedupe — so own edits (`trackChanges`) and foreign
|
|
67
|
+
* suggestions (`suggestions`) share one bar column rather than stacking separate gutters. The gutter is
|
|
68
|
+
* built inside `enables` so its `markers` can read this same facet.
|
|
69
|
+
*/
|
|
70
|
+
const changeBarProviders = Facet.define<ChangeBarProvider>({
|
|
71
|
+
enables: (self) => [
|
|
72
|
+
gutter({
|
|
73
|
+
class: 'cm-change-bar-gutter',
|
|
74
|
+
// Merge every contributor's per-line markers into the shared gutter (sorted so co-located markers
|
|
75
|
+
// from different sources interleave rather than throw).
|
|
76
|
+
markers: (view) => {
|
|
77
|
+
const sets = view.state.facet(self).map((provider) => provider(view.state));
|
|
78
|
+
return sets.length ? RangeSet.join(sets) : RangeSet.empty;
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
changeBarTheme,
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
/** Contribute per-line change bars to the shared author-coloured gutter (see {@link ChangeBarMarker}). */
|
|
86
|
+
export const changeBars = (provider: ChangeBarProvider): Extension => changeBarProviders.of(provider);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Keeps the change-bar column mounted with no markers. Hosts that toggle review overlays install this
|
|
90
|
+
* once alongside their compartments, so entering/leaving Suggesting reconfigures marker providers
|
|
91
|
+
* inside an existing gutter instead of adding and removing the column — which shifted the text and
|
|
92
|
+
* flickered on every mode switch.
|
|
93
|
+
*/
|
|
94
|
+
export const changeBarGutter: Extension = changeBarProviders.of(() => RangeSet.empty);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { EditorView } from '@codemirror/view';
|
|
6
|
+
import { describe, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { comments, createComment } from './comments';
|
|
9
|
+
|
|
10
|
+
describe('createComment', () => {
|
|
11
|
+
test('collapses the selection to its start after creating a comment', ({ expect }) => {
|
|
12
|
+
const created: { cursor: string; from: number }[] = [];
|
|
13
|
+
const view = new EditorView({
|
|
14
|
+
doc: 'The quick brown fox jumps over the lazy dog.',
|
|
15
|
+
extensions: [comments({ id: 'test', onCreate: ({ cursor, from }) => created.push({ cursor, from }) })],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Select "quick".
|
|
19
|
+
view.dispatch({ selection: { anchor: 4, head: 9 } });
|
|
20
|
+
const result = createComment(view);
|
|
21
|
+
|
|
22
|
+
expect(result).to.eq(true);
|
|
23
|
+
expect(created).to.have.length(1);
|
|
24
|
+
// The text selection is collapsed to the start of the commented range.
|
|
25
|
+
expect(view.state.selection.main.empty).to.eq(true);
|
|
26
|
+
expect(view.state.selection.main.head).to.eq(4);
|
|
27
|
+
|
|
28
|
+
view.destroy();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('expands a bare cursor to the word under it', ({ expect }) => {
|
|
32
|
+
const created: { from: number }[] = [];
|
|
33
|
+
const view = new EditorView({
|
|
34
|
+
doc: 'The quick brown fox.',
|
|
35
|
+
extensions: [comments({ id: 'test', onCreate: ({ from }) => created.push({ from }) })],
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Cursor inside "quick", no range: the comment expands to the whole word.
|
|
39
|
+
view.dispatch({ selection: { anchor: 6 } });
|
|
40
|
+
expect(createComment(view)).to.eq(true);
|
|
41
|
+
expect(created).to.have.length(1);
|
|
42
|
+
expect(created[0].from).to.eq(4);
|
|
43
|
+
|
|
44
|
+
view.destroy();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('is a no-op when there is no word or range under the caret', ({ expect }) => {
|
|
48
|
+
const view = new EditorView({
|
|
49
|
+
doc: ' ',
|
|
50
|
+
extensions: [comments({ id: 'test', onCreate: () => {} })],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
view.dispatch({ selection: { anchor: 1 } });
|
|
54
|
+
expect(createComment(view)).to.eq(false);
|
|
55
|
+
|
|
56
|
+
view.destroy();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('is prohibited when readonly (e.g. a suggestion branch)', ({ expect }) => {
|
|
60
|
+
const created: unknown[] = [];
|
|
61
|
+
const view = new EditorView({
|
|
62
|
+
doc: 'The quick brown fox.',
|
|
63
|
+
extensions: [comments({ id: 'test', readonly: true, onCreate: () => created.push(1) })],
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
view.dispatch({ selection: { anchor: 4, head: 9 } });
|
|
67
|
+
expect(createComment(view)).to.eq(false);
|
|
68
|
+
expect(created).to.have.length(0);
|
|
69
|
+
|
|
70
|
+
view.destroy();
|
|
71
|
+
});
|
|
72
|
+
});
|