@prosekit/extensions 0.11.3 → 0.11.5
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/commit/style.css +2 -0
- package/dist/commit/style.css.map +1 -0
- package/dist/commit/style.js +1 -0
- package/dist/{drop-indicator-B8P652g2.js → drop-indicator-D1eHOhSi.js} +6 -5
- package/dist/drop-indicator-D1eHOhSi.js.map +1 -0
- package/dist/enter-rule-RdhEA900.js +2 -1
- package/dist/enter-rule-RdhEA900.js.map +1 -0
- package/dist/gap-cursor/style.css +2 -0
- package/dist/gap-cursor/style.css.map +1 -0
- package/dist/gap-cursor/style.js +1 -0
- package/dist/{input-rule-Gji4N7Oe.js → input-rule-B17tpW4m.js} +3 -3
- package/dist/input-rule-B17tpW4m.js.map +1 -0
- package/dist/list/style.css +2 -0
- package/dist/list/style.css.map +1 -0
- package/dist/list/style.js +1 -0
- package/dist/loro/style.css +2 -0
- package/dist/loro/style.css.map +1 -0
- package/dist/loro/style.js +1 -0
- package/dist/{mark-rule-D7zaa32n.js → mark-rule-BCqIZMDu.js} +3 -3
- package/dist/mark-rule-BCqIZMDu.js.map +1 -0
- package/dist/{paste-rule-Cca3n5TA.js → paste-rule-DIEJKIje.js} +5 -15
- package/dist/paste-rule-DIEJKIje.js.map +1 -0
- package/dist/placeholder/style.css +2 -0
- package/dist/placeholder/style.css.map +1 -0
- package/dist/placeholder/style.js +1 -0
- package/dist/prosekit-extensions-autocomplete.d.ts +2 -1
- package/dist/prosekit-extensions-autocomplete.d.ts.map +1 -0
- package/dist/prosekit-extensions-autocomplete.js +2 -9
- package/dist/prosekit-extensions-autocomplete.js.map +1 -0
- package/dist/prosekit-extensions-blockquote.d.ts +2 -1
- package/dist/prosekit-extensions-blockquote.d.ts.map +1 -0
- package/dist/prosekit-extensions-blockquote.js +4 -4
- package/dist/prosekit-extensions-blockquote.js.map +1 -0
- package/dist/prosekit-extensions-bold.d.ts +2 -1
- package/dist/prosekit-extensions-bold.d.ts.map +1 -0
- package/dist/prosekit-extensions-bold.js +3 -2
- package/dist/prosekit-extensions-bold.js.map +1 -0
- package/dist/prosekit-extensions-code-block.d.ts +2 -1
- package/dist/prosekit-extensions-code-block.d.ts.map +1 -0
- package/dist/prosekit-extensions-code-block.js +5 -6
- package/dist/prosekit-extensions-code-block.js.map +1 -0
- package/dist/prosekit-extensions-code.d.ts +2 -1
- package/dist/prosekit-extensions-code.d.ts.map +1 -0
- package/dist/prosekit-extensions-code.js +3 -2
- package/dist/prosekit-extensions-code.js.map +1 -0
- package/dist/prosekit-extensions-commit.d.ts +2 -1
- package/dist/prosekit-extensions-commit.d.ts.map +1 -0
- package/dist/prosekit-extensions-commit.js +11 -13
- package/dist/prosekit-extensions-commit.js.map +1 -0
- package/dist/prosekit-extensions-doc.d.ts +2 -1
- package/dist/prosekit-extensions-doc.d.ts.map +1 -0
- package/dist/prosekit-extensions-doc.js +2 -1
- package/dist/prosekit-extensions-doc.js.map +1 -0
- package/dist/prosekit-extensions-drop-cursor.d.ts +2 -1
- package/dist/prosekit-extensions-drop-cursor.d.ts.map +1 -0
- package/dist/prosekit-extensions-drop-cursor.js +2 -1
- package/dist/prosekit-extensions-drop-cursor.js.map +1 -0
- package/dist/prosekit-extensions-drop-indicator.d.ts +2 -1
- package/dist/prosekit-extensions-drop-indicator.d.ts.map +1 -0
- package/dist/prosekit-extensions-drop-indicator.js +1 -1
- package/dist/prosekit-extensions-enter-rule.d.ts +2 -1
- package/dist/prosekit-extensions-enter-rule.d.ts.map +1 -0
- package/dist/prosekit-extensions-file.d.ts +2 -1
- package/dist/prosekit-extensions-file.d.ts.map +1 -0
- package/dist/prosekit-extensions-file.js +4 -16
- package/dist/prosekit-extensions-file.js.map +1 -0
- package/dist/prosekit-extensions-gap-cursor.d.ts +2 -2
- package/dist/prosekit-extensions-gap-cursor.d.ts.map +1 -0
- package/dist/prosekit-extensions-gap-cursor.js +2 -1
- package/dist/prosekit-extensions-gap-cursor.js.map +1 -0
- package/dist/prosekit-extensions-hard-break.d.ts +2 -1
- package/dist/prosekit-extensions-hard-break.d.ts.map +1 -0
- package/dist/prosekit-extensions-hard-break.js +2 -1
- package/dist/prosekit-extensions-hard-break.js.map +1 -0
- package/dist/prosekit-extensions-heading.d.ts +2 -1
- package/dist/prosekit-extensions-heading.d.ts.map +1 -0
- package/dist/prosekit-extensions-heading.js +5 -6
- package/dist/prosekit-extensions-heading.js.map +1 -0
- package/dist/prosekit-extensions-horizontal-rule.d.ts +2 -1
- package/dist/prosekit-extensions-horizontal-rule.d.ts.map +1 -0
- package/dist/prosekit-extensions-horizontal-rule.js +5 -6
- package/dist/prosekit-extensions-horizontal-rule.js.map +1 -0
- package/dist/prosekit-extensions-image.d.ts +2 -1
- package/dist/prosekit-extensions-image.d.ts.map +1 -0
- package/dist/prosekit-extensions-image.js +3 -3
- package/dist/prosekit-extensions-image.js.map +1 -0
- package/dist/prosekit-extensions-input-rule.d.ts +2 -1
- package/dist/prosekit-extensions-input-rule.d.ts.map +1 -0
- package/dist/prosekit-extensions-input-rule.js +1 -1
- package/dist/prosekit-extensions-italic.d.ts +2 -1
- package/dist/prosekit-extensions-italic.d.ts.map +1 -0
- package/dist/prosekit-extensions-italic.js +3 -2
- package/dist/prosekit-extensions-italic.js.map +1 -0
- package/dist/prosekit-extensions-link.d.ts +2 -1
- package/dist/prosekit-extensions-link.d.ts.map +1 -0
- package/dist/prosekit-extensions-link.js +6 -5
- package/dist/prosekit-extensions-link.js.map +1 -0
- package/dist/prosekit-extensions-list.d.ts +22 -21
- package/dist/prosekit-extensions-list.d.ts.map +1 -0
- package/dist/prosekit-extensions-list.js +6 -7
- package/dist/prosekit-extensions-list.js.map +1 -0
- package/dist/prosekit-extensions-loro.d.ts +14 -13
- package/dist/prosekit-extensions-loro.d.ts.map +1 -0
- package/dist/prosekit-extensions-loro.js +2 -1
- package/dist/prosekit-extensions-loro.js.map +1 -0
- package/dist/prosekit-extensions-mark-rule.d.ts +2 -1
- package/dist/prosekit-extensions-mark-rule.d.ts.map +1 -0
- package/dist/prosekit-extensions-mark-rule.js +1 -1
- package/dist/prosekit-extensions-mention.d.ts +2 -1
- package/dist/prosekit-extensions-mention.d.ts.map +1 -0
- package/dist/prosekit-extensions-mention.js +2 -1
- package/dist/prosekit-extensions-mention.js.map +1 -0
- package/dist/prosekit-extensions-mod-click-prevention.d.ts +2 -1
- package/dist/prosekit-extensions-mod-click-prevention.d.ts.map +1 -0
- package/dist/prosekit-extensions-mod-click-prevention.js +2 -1
- package/dist/prosekit-extensions-mod-click-prevention.js.map +1 -0
- package/dist/prosekit-extensions-paragraph.d.ts +2 -1
- package/dist/prosekit-extensions-paragraph.d.ts.map +1 -0
- package/dist/prosekit-extensions-paragraph.js +2 -1
- package/dist/prosekit-extensions-paragraph.js.map +1 -0
- package/dist/prosekit-extensions-paste-rule.d.ts +2 -1
- package/dist/prosekit-extensions-paste-rule.d.ts.map +1 -0
- package/dist/prosekit-extensions-paste-rule.js +1 -1
- package/dist/prosekit-extensions-placeholder.d.ts +2 -1
- package/dist/prosekit-extensions-placeholder.d.ts.map +1 -0
- package/dist/prosekit-extensions-placeholder.js +5 -4
- package/dist/prosekit-extensions-placeholder.js.map +1 -0
- package/dist/prosekit-extensions-readonly.d.ts +2 -1
- package/dist/prosekit-extensions-readonly.d.ts.map +1 -0
- package/dist/prosekit-extensions-readonly.js +2 -1
- package/dist/prosekit-extensions-readonly.js.map +1 -0
- package/dist/prosekit-extensions-search.d.ts +2 -1
- package/dist/prosekit-extensions-search.d.ts.map +1 -0
- package/dist/prosekit-extensions-search.js +3 -3
- package/dist/prosekit-extensions-search.js.map +1 -0
- package/dist/prosekit-extensions-strike.d.ts +2 -1
- package/dist/prosekit-extensions-strike.d.ts.map +1 -0
- package/dist/prosekit-extensions-strike.js +3 -2
- package/dist/prosekit-extensions-strike.js.map +1 -0
- package/dist/prosekit-extensions-table.d.ts +56 -114
- package/dist/prosekit-extensions-table.d.ts.map +1 -0
- package/dist/prosekit-extensions-table.js +3 -2
- package/dist/prosekit-extensions-text-align.d.ts +2 -1
- package/dist/prosekit-extensions-text-align.d.ts.map +1 -0
- package/dist/prosekit-extensions-text-align.js +2 -1
- package/dist/prosekit-extensions-text-align.js.map +1 -0
- package/dist/prosekit-extensions-text.d.ts +2 -1
- package/dist/prosekit-extensions-text.d.ts.map +1 -0
- package/dist/prosekit-extensions-text.js +2 -1
- package/dist/prosekit-extensions-text.js.map +1 -0
- package/dist/prosekit-extensions-underline.d.ts +2 -1
- package/dist/prosekit-extensions-underline.d.ts.map +1 -0
- package/dist/prosekit-extensions-underline.js +2 -1
- package/dist/prosekit-extensions-underline.js.map +1 -0
- package/dist/prosekit-extensions-virtual-selection.d.ts +2 -1
- package/dist/prosekit-extensions-virtual-selection.d.ts.map +1 -0
- package/dist/prosekit-extensions-virtual-selection.js +3 -3
- package/dist/prosekit-extensions-virtual-selection.js.map +1 -0
- package/dist/prosekit-extensions-yjs.d.ts +2 -1
- package/dist/prosekit-extensions-yjs.d.ts.map +1 -0
- package/dist/prosekit-extensions-yjs.js +2 -1
- package/dist/prosekit-extensions-yjs.js.map +1 -0
- package/dist/prosekit-extensions.d.ts +1 -1
- package/dist/prosekit-extensions.js +1 -0
- package/dist/search/style.css +2 -0
- package/dist/search/style.css.map +1 -0
- package/dist/search/style.js +1 -0
- package/dist/shiki-highlighter-chunk-DSPM0T27.d.ts +2 -1
- package/dist/shiki-highlighter-chunk-DSPM0T27.d.ts.map +1 -0
- package/dist/shiki-highlighter-chunk.js +3 -5
- package/dist/shiki-highlighter-chunk.js.map +1 -0
- package/dist/table/style.css +2 -0
- package/dist/table/style.css.map +1 -0
- package/dist/table/style.js +1 -0
- package/dist/table-Bi7WsMI3.js +297 -0
- package/dist/table-Bi7WsMI3.js.map +1 -0
- package/dist/virtual-selection/style.css +2 -0
- package/dist/virtual-selection/style.css.map +1 -0
- package/dist/virtual-selection/style.js +1 -0
- package/dist/yjs/style.css +2 -0
- package/dist/yjs/style.css.map +1 -0
- package/dist/yjs/style.js +1 -0
- package/package.json +10 -9
- package/src/autocomplete/autocomplete-helpers.ts +74 -0
- package/src/autocomplete/autocomplete-plugin.ts +186 -0
- package/src/autocomplete/autocomplete-rule.ts +117 -0
- package/src/autocomplete/autocomplete.spec.ts +132 -0
- package/src/autocomplete/autocomplete.ts +29 -0
- package/src/autocomplete/index.ts +9 -0
- package/src/blockquote/blockquote-commands.ts +32 -0
- package/src/blockquote/blockquote-input-rule.ts +14 -0
- package/src/blockquote/blockquote-keymap.spec.ts +45 -0
- package/src/blockquote/blockquote-keymap.ts +31 -0
- package/src/blockquote/blockquote-spec.ts +24 -0
- package/src/blockquote/blockquote.ts +34 -0
- package/src/blockquote/index.ts +14 -0
- package/src/bold/bold-commands.ts +23 -0
- package/src/bold/bold-input-rule.spec.ts +51 -0
- package/src/bold/bold-input-rule.ts +18 -0
- package/src/bold/bold-keymap.ts +14 -0
- package/src/bold/bold-spec.ts +53 -0
- package/src/bold/bold.ts +32 -0
- package/src/bold/index.ts +14 -0
- package/src/code/code-commands.ts +23 -0
- package/src/code/code-input-rule.ts +18 -0
- package/src/code/code-keymap.ts +14 -0
- package/src/code/code-spec.ts +28 -0
- package/src/code/code.ts +32 -0
- package/src/code/index.ts +14 -0
- package/src/code-block/code-block-commands.ts +44 -0
- package/src/code-block/code-block-highlight.ts +40 -0
- package/src/code-block/code-block-input-rule.ts +36 -0
- package/src/code-block/code-block-keymap.ts +61 -0
- package/src/code-block/code-block-shiki.ts +58 -0
- package/src/code-block/code-block-spec.spec.ts +164 -0
- package/src/code-block/code-block-spec.ts +71 -0
- package/src/code-block/code-block-types.ts +8 -0
- package/src/code-block/code-block.ts +46 -0
- package/src/code-block/index.ts +32 -0
- package/src/code-block/shiki-bundle.ts +8 -0
- package/src/code-block/shiki-highlighter-chunk.ts +84 -0
- package/src/code-block/shiki-highlighter.ts +22 -0
- package/src/code-block/shiki-parser.ts +36 -0
- package/src/commit/index.ts +330 -0
- package/src/commit/style.css +7 -0
- package/src/doc/index.ts +21 -0
- package/src/drop-cursor/drop-cursor.ts +46 -0
- package/src/drop-cursor/index.ts +5 -0
- package/src/drop-indicator/drop-indicator-facet.ts +84 -0
- package/src/drop-indicator/drop-indicator-plugin.ts +147 -0
- package/src/drop-indicator/drop-indicator.ts +37 -0
- package/src/drop-indicator/drop-target.ts +168 -0
- package/src/drop-indicator/index.ts +14 -0
- package/src/drop-indicator/types.ts +90 -0
- package/src/enter-rule/index.ts +241 -0
- package/src/file/file-drop-handler.ts +75 -0
- package/src/file/file-paste-handler.spec.ts +95 -0
- package/src/file/file-paste-handler.ts +59 -0
- package/src/file/file-upload.ts +119 -0
- package/src/file/helpers.ts +39 -0
- package/src/file/index.ts +16 -0
- package/src/gap-cursor/gap-cursor.ts +28 -0
- package/src/gap-cursor/index.ts +4 -0
- package/src/gap-cursor/style.css +25 -0
- package/src/hard-break/hard-break-commands.ts +31 -0
- package/src/hard-break/hard-break-keymap.spec.ts +45 -0
- package/src/hard-break/hard-break-keymap.ts +16 -0
- package/src/hard-break/hard-break-spec.ts +31 -0
- package/src/hard-break/hard-break.ts +32 -0
- package/src/hard-break/index.ts +13 -0
- package/src/heading/heading-commands.ts +37 -0
- package/src/heading/heading-input-rule.ts +22 -0
- package/src/heading/heading-keymap.spec.ts +53 -0
- package/src/heading/heading-keymap.ts +40 -0
- package/src/heading/heading-spec.ts +39 -0
- package/src/heading/heading-types.ts +3 -0
- package/src/heading/heading.ts +34 -0
- package/src/heading/index.ts +15 -0
- package/src/horizontal-rule/horizontal-rule-commands.spec.ts +61 -0
- package/src/horizontal-rule/horizontal-rule-commands.ts +37 -0
- package/src/horizontal-rule/horizontal-rule-input-rule.spec.ts +61 -0
- package/src/horizontal-rule/horizontal-rule-input-rule.ts +26 -0
- package/src/horizontal-rule/horizontal-rule-spec.ts +21 -0
- package/src/horizontal-rule/horizontal-rule.ts +29 -0
- package/src/horizontal-rule/index.ts +14 -0
- package/src/image/image-commands.ts +27 -0
- package/src/image/image-spec.ts +72 -0
- package/src/image/image.ts +25 -0
- package/src/image/index.ts +13 -0
- package/src/index.ts +1 -0
- package/src/input-rule/index.ts +237 -0
- package/src/italic/index.ts +14 -0
- package/src/italic/italic-commands.spec.ts +75 -0
- package/src/italic/italic-commands.ts +23 -0
- package/src/italic/italic-input-rule.spec.ts +25 -0
- package/src/italic/italic-input-rule.ts +18 -0
- package/src/italic/italic-keymap.ts +14 -0
- package/src/italic/italic-spec.ts +35 -0
- package/src/italic/italic.ts +34 -0
- package/src/link/index.spec.ts +88 -0
- package/src/link/index.ts +156 -0
- package/src/link/link-paste-rule.spec.ts +194 -0
- package/src/link/link-paste-rule.ts +22 -0
- package/src/link/link-regex.spec.ts +82 -0
- package/src/link/link-regex.ts +79 -0
- package/src/link/link-types.ts +8 -0
- package/src/list/index.ts +25 -0
- package/src/list/list-commands.ts +61 -0
- package/src/list/list-drop-indicator.ts +37 -0
- package/src/list/list-input-rules.ts +14 -0
- package/src/list/list-keymap.spec.ts +39 -0
- package/src/list/list-keymap.ts +48 -0
- package/src/list/list-plugins.ts +35 -0
- package/src/list/list-serializer.ts +38 -0
- package/src/list/list-spec.ts +60 -0
- package/src/list/list-types.spec.ts +10 -0
- package/src/list/list-types.ts +23 -0
- package/src/list/list.spec.ts +134 -0
- package/src/list/list.ts +38 -0
- package/src/list/style.css +128 -0
- package/src/loro/index.ts +17 -0
- package/src/loro/loro-commands.ts +27 -0
- package/src/loro/loro-cursor-plugin.ts +28 -0
- package/src/loro/loro-keymap.ts +23 -0
- package/src/loro/loro-sync-plugin.ts +14 -0
- package/src/loro/loro-undo-plugin.ts +12 -0
- package/src/loro/loro.ts +75 -0
- package/src/loro/style.css +33 -0
- package/src/mark-rule/apply.ts +129 -0
- package/src/mark-rule/index.ts +2 -0
- package/src/mark-rule/mark-rule.spec.ts +123 -0
- package/src/mark-rule/mark-rule.ts +48 -0
- package/src/mark-rule/range.ts +107 -0
- package/src/mark-rule/types.ts +30 -0
- package/src/mention/index.ts +90 -0
- package/src/mod-click-prevention/index.ts +35 -0
- package/src/paragraph/index.ts +7 -0
- package/src/paragraph/paragraph-commands.ts +29 -0
- package/src/paragraph/paragraph-keymap.ts +15 -0
- package/src/paragraph/paragraph-spec.ts +31 -0
- package/src/paragraph/paragraph.ts +37 -0
- package/src/paste-rule/index.ts +10 -0
- package/src/paste-rule/mark-paste-rule.spec.ts +112 -0
- package/src/paste-rule/mark-paste-rule.ts +194 -0
- package/src/paste-rule/paste-rule-plugin.ts +53 -0
- package/src/paste-rule/paste-rule.spec.ts +96 -0
- package/src/paste-rule/paste-rule.ts +60 -0
- package/src/paste-rule/split-text-by-regex.spec.ts +97 -0
- package/src/paste-rule/split-text-by-regex.ts +44 -0
- package/src/placeholder/index.ts +113 -0
- package/src/placeholder/style.css +7 -0
- package/src/readonly/index.ts +22 -0
- package/src/search/index.ts +140 -0
- package/src/search/style.css +13 -0
- package/src/strike/index.ts +101 -0
- package/src/table/index.ts +53 -0
- package/src/table/style.css +42 -0
- package/src/table/table-commands/delete-cell-selection.spec.ts +41 -0
- package/src/table/table-commands/delete-cell-selection.ts +1 -0
- package/src/table/table-commands/exit-table.spec.ts +45 -0
- package/src/table/table-commands/exit-table.ts +49 -0
- package/src/table/table-commands/insert-table.spec.ts +39 -0
- package/src/table/table-commands/insert-table.ts +80 -0
- package/src/table/table-commands/move-table-column.spec.ts +618 -0
- package/src/table/table-commands/move-table-column.ts +4 -0
- package/src/table/table-commands/move-table-row.spec.ts +380 -0
- package/src/table/table-commands/move-table-row.ts +4 -0
- package/src/table/table-commands/select-table-cell.spec.ts +34 -0
- package/src/table/table-commands/select-table-cell.ts +35 -0
- package/src/table/table-commands/select-table-column.spec.ts +33 -0
- package/src/table/table-commands/select-table-column.ts +39 -0
- package/src/table/table-commands/select-table-row.spec.ts +32 -0
- package/src/table/table-commands/select-table-row.ts +39 -0
- package/src/table/table-commands/select-table.spec.ts +36 -0
- package/src/table/table-commands/select-table.ts +50 -0
- package/src/table/table-commands.ts +110 -0
- package/src/table/table-drop-indicator.ts +40 -0
- package/src/table/table-plugins.ts +15 -0
- package/src/table/table-spec.spec.ts +113 -0
- package/src/table/table-spec.ts +109 -0
- package/src/table/table-utils.ts +16 -0
- package/src/table/table.ts +49 -0
- package/src/table/test-utils.ts +28 -0
- package/src/testing/clipboard.ts +58 -0
- package/src/testing/format-html.ts +5 -0
- package/src/testing/index.ts +161 -0
- package/src/testing/keyboard.ts +36 -0
- package/src/testing/markdown.ts +23 -0
- package/src/text/index.ts +24 -0
- package/src/text-align/index.ts +133 -0
- package/src/types/assert-type-equal.ts +8 -0
- package/src/underline/index.ts +83 -0
- package/src/virtual-selection/index.ts +100 -0
- package/src/virtual-selection/style.css +5 -0
- package/src/yjs/index.ts +22 -0
- package/src/yjs/style.css +31 -0
- package/src/yjs/yjs-commands.ts +27 -0
- package/src/yjs/yjs-cursor-plugin.ts +25 -0
- package/src/yjs/yjs-keymap.ts +23 -0
- package/src/yjs/yjs-sync-plugin.ts +23 -0
- package/src/yjs/yjs-undo-plugin.ts +87 -0
- package/src/yjs/yjs.ts +84 -0
- package/dist/table-C_qAMj5-.js +0 -734
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isApple } from '@prosekit/core'
|
|
2
|
+
import { userEvent } from '@vitest/browser/context'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @example
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* await pressKey('mod-1')
|
|
9
|
+
* await pressKey('Backspace')
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export async function pressKey(input: string) {
|
|
16
|
+
const keys = input.split('-').map((key) => {
|
|
17
|
+
if (key.toLowerCase() === 'mod') {
|
|
18
|
+
return isApple ? 'Meta' : 'Control'
|
|
19
|
+
}
|
|
20
|
+
return key
|
|
21
|
+
})
|
|
22
|
+
const seq: string[] = []
|
|
23
|
+
for (const key of keys) {
|
|
24
|
+
// Press key without releasing it
|
|
25
|
+
seq.push('{' + key + '>}')
|
|
26
|
+
}
|
|
27
|
+
for (const key of keys.toReversed()) {
|
|
28
|
+
// Release a previously pressed key
|
|
29
|
+
seq.push('{/' + key + '}')
|
|
30
|
+
}
|
|
31
|
+
return await userEvent.keyboard(seq.join(''))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function inputText(input: string) {
|
|
35
|
+
return await userEvent.keyboard(input)
|
|
36
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import rehypeParse from 'rehype-parse'
|
|
2
|
+
import rehypeRemark from 'rehype-remark'
|
|
3
|
+
import remarkHtml from 'remark-html'
|
|
4
|
+
import remarkParse from 'remark-parse'
|
|
5
|
+
import remarkStringify from 'remark-stringify'
|
|
6
|
+
import { unified } from 'unified'
|
|
7
|
+
|
|
8
|
+
export function markdownFromHTML(html: string): string {
|
|
9
|
+
return unified()
|
|
10
|
+
.use(rehypeParse)
|
|
11
|
+
.use(rehypeRemark)
|
|
12
|
+
.use(remarkStringify)
|
|
13
|
+
.processSync(html)
|
|
14
|
+
.toString()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function htmlFromMarkdown(markdown: string): string {
|
|
18
|
+
return unified()
|
|
19
|
+
.use(remarkParse)
|
|
20
|
+
.use(remarkHtml)
|
|
21
|
+
.processSync(markdown)
|
|
22
|
+
.toString()
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineNodeSpec,
|
|
3
|
+
type Extension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
import type { Attrs } from '@prosekit/pm/model'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export type TextExtension = Extension<{
|
|
11
|
+
Nodes: {
|
|
12
|
+
text: Attrs
|
|
13
|
+
}
|
|
14
|
+
}>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export function defineText(): TextExtension {
|
|
20
|
+
return defineNodeSpec({
|
|
21
|
+
name: 'text',
|
|
22
|
+
group: 'inline',
|
|
23
|
+
})
|
|
24
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineCommands,
|
|
3
|
+
defineKeymap,
|
|
4
|
+
defineNodeAttr,
|
|
5
|
+
setNodeAttrs,
|
|
6
|
+
union,
|
|
7
|
+
type Extension,
|
|
8
|
+
type PlainExtension,
|
|
9
|
+
type Union,
|
|
10
|
+
} from '@prosekit/core'
|
|
11
|
+
import type { Command } from '@prosekit/pm/state'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export interface TextAlignOptions<NodeName extends string = string> {
|
|
17
|
+
/**
|
|
18
|
+
* The names of node to add the attribute to.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
*
|
|
22
|
+
* ["paragraph", "heading"]
|
|
23
|
+
*/
|
|
24
|
+
types: NodeName[]
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The default value for the attribute.
|
|
28
|
+
*
|
|
29
|
+
* @default "left"
|
|
30
|
+
*/
|
|
31
|
+
default?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function defineTextAlignAttr<NodeName extends string>(
|
|
35
|
+
type: NodeName,
|
|
36
|
+
defaultValue: string | null,
|
|
37
|
+
) {
|
|
38
|
+
return defineNodeAttr<NodeName, 'textAlign', string | null>({
|
|
39
|
+
type,
|
|
40
|
+
attr: 'textAlign',
|
|
41
|
+
default: defaultValue,
|
|
42
|
+
splittable: true,
|
|
43
|
+
toDOM: (value: any) => (value ? ['style', `text-align:${value};`] : null),
|
|
44
|
+
parseDOM: (node: HTMLElement) => {
|
|
45
|
+
return node.style.getPropertyValue('text-align') || null
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export type TextAlignAttrsExtension<NodeName extends string> = Extension<{
|
|
54
|
+
Nodes: { [K in NodeName]: { textAlign: string | null } }
|
|
55
|
+
}>
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
function defineTextAlignAttrs<NodeName extends string>(
|
|
61
|
+
types: NodeName[],
|
|
62
|
+
defaultValue: string | null,
|
|
63
|
+
): TextAlignAttrsExtension<NodeName> {
|
|
64
|
+
return union(types.map((type) => defineTextAlignAttr(type, defaultValue)))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
export function setTextAlign({
|
|
71
|
+
types,
|
|
72
|
+
value,
|
|
73
|
+
}: {
|
|
74
|
+
types: string[]
|
|
75
|
+
value: string | null
|
|
76
|
+
}): Command {
|
|
77
|
+
return setNodeAttrs({ type: types, attrs: { textAlign: value } })
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export type TextAlignCommandsExtension = Extension<{
|
|
84
|
+
Commands: {
|
|
85
|
+
setTextAlign: [value: string | null]
|
|
86
|
+
}
|
|
87
|
+
}>
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
92
|
+
export function defineTextAlignCommands(
|
|
93
|
+
types: string[],
|
|
94
|
+
): TextAlignCommandsExtension {
|
|
95
|
+
return defineCommands({
|
|
96
|
+
setTextAlign: (value: string | null) => setTextAlign({ types, value }),
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
export function defineTextAlignKeymap(types: string[]): PlainExtension {
|
|
104
|
+
return defineKeymap({
|
|
105
|
+
'mod-shift-l': setTextAlign({ types, value: 'left' }),
|
|
106
|
+
'mod-shift-e': setTextAlign({ types, value: 'center' }),
|
|
107
|
+
'mod-shift-r': setTextAlign({ types, value: 'right' }),
|
|
108
|
+
'mod-shift-j': setTextAlign({ types, value: 'justify' }),
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @internal
|
|
114
|
+
*/
|
|
115
|
+
export type TextAlignExtension<NodeName extends string> = Union<
|
|
116
|
+
[TextAlignAttrsExtension<NodeName>, TextAlignCommandsExtension]
|
|
117
|
+
>
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Adds a `textAlign` attribute to the specified nodes. This will be rendered as
|
|
121
|
+
* a CSS `text-align` style.
|
|
122
|
+
*
|
|
123
|
+
* @public
|
|
124
|
+
*/
|
|
125
|
+
export function defineTextAlign<NodeName extends string = string>(
|
|
126
|
+
options: TextAlignOptions<NodeName>,
|
|
127
|
+
): TextAlignExtension<NodeName> {
|
|
128
|
+
return union(
|
|
129
|
+
defineTextAlignAttrs<NodeName>(options.types, options.default || 'left'),
|
|
130
|
+
defineTextAlignKeymap(options.types),
|
|
131
|
+
defineTextAlignCommands(options.types),
|
|
132
|
+
)
|
|
133
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineCommands,
|
|
3
|
+
defineKeymap,
|
|
4
|
+
defineMarkSpec,
|
|
5
|
+
toggleMark,
|
|
6
|
+
union,
|
|
7
|
+
type Extension,
|
|
8
|
+
type PlainExtension,
|
|
9
|
+
type Union,
|
|
10
|
+
} from '@prosekit/core'
|
|
11
|
+
import type { Attrs } from '@prosekit/pm/model'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export type UnderlineSpecExtension = Extension<{
|
|
17
|
+
Marks: {
|
|
18
|
+
underline: Attrs
|
|
19
|
+
}
|
|
20
|
+
}>
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export function defineUnderlineSpec(): UnderlineSpecExtension {
|
|
26
|
+
return defineMarkSpec({
|
|
27
|
+
name: 'underline',
|
|
28
|
+
parseDOM: [
|
|
29
|
+
{ tag: 'u' },
|
|
30
|
+
{ tag: 'underline' },
|
|
31
|
+
{ style: 'text-decoration=underline' },
|
|
32
|
+
{ style: 'text-decoration-line=underline' },
|
|
33
|
+
],
|
|
34
|
+
toDOM() {
|
|
35
|
+
return ['u', 0]
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export type UnderlineCommandsExtension = Extension<{
|
|
44
|
+
Commands: {
|
|
45
|
+
toggleUnderline: []
|
|
46
|
+
}
|
|
47
|
+
}>
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export function defineUnderlineCommands(): UnderlineCommandsExtension {
|
|
53
|
+
return defineCommands({
|
|
54
|
+
toggleUnderline: () => toggleMark({ type: 'underline' }),
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
export function defineUnderlineKeymap(): PlainExtension {
|
|
62
|
+
return defineKeymap({
|
|
63
|
+
'Mod-u': toggleMark({ type: 'underline' }),
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
export type UnderlineExtension = Union<
|
|
71
|
+
[UnderlineSpecExtension, UnderlineCommandsExtension]
|
|
72
|
+
>
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
export function defineUnderline(): UnderlineExtension {
|
|
78
|
+
return union(
|
|
79
|
+
defineUnderlineSpec(),
|
|
80
|
+
defineUnderlineCommands(),
|
|
81
|
+
defineUnderlineKeymap(),
|
|
82
|
+
)
|
|
83
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
definePlugin,
|
|
3
|
+
type PlainExtension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
import {
|
|
6
|
+
PluginKey,
|
|
7
|
+
ProseMirrorPlugin,
|
|
8
|
+
type EditorState,
|
|
9
|
+
type Transaction,
|
|
10
|
+
} from '@prosekit/pm/state'
|
|
11
|
+
import {
|
|
12
|
+
Decoration,
|
|
13
|
+
DecorationSet,
|
|
14
|
+
} from '@prosekit/pm/view'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export type VirtualSelectionExtension = PlainExtension
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Shows a virtual selection when the editor is not focused. When the editor is
|
|
23
|
+
* not focused, the selected inline content will be wrapped in a `<span>`
|
|
24
|
+
* element with the class `prosekit-virtual-selection`.
|
|
25
|
+
*
|
|
26
|
+
* This is useful when you want to move the focus to an element outside the
|
|
27
|
+
* editor, but still want to show the selection.
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
export function defineVirtualSelection(): VirtualSelectionExtension {
|
|
32
|
+
return definePlugin(virtualSelectionPlugin)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Show the decoration when this is true.
|
|
36
|
+
type PluginState = boolean
|
|
37
|
+
|
|
38
|
+
const key = new PluginKey<PluginState>('prosekit-virtual-selection')
|
|
39
|
+
|
|
40
|
+
function getFocusMeta(tr: Transaction): PluginState | undefined {
|
|
41
|
+
return tr.getMeta(key) as PluginState | undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function setFocusMeta(tr: Transaction, value: PluginState) {
|
|
45
|
+
return tr.setMeta(key, value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getFocusState(state: EditorState): PluginState | undefined {
|
|
49
|
+
return key.getState(state)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const virtualSelectionPlugin = new ProseMirrorPlugin<PluginState>({
|
|
53
|
+
key,
|
|
54
|
+
state: {
|
|
55
|
+
init: () => false,
|
|
56
|
+
apply: (tr, value) => {
|
|
57
|
+
return getFocusMeta(tr) ?? value
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
props: {
|
|
61
|
+
handleDOMEvents: {
|
|
62
|
+
focus: (view) => {
|
|
63
|
+
view.dispatch(setFocusMeta(view.state.tr, false))
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
blur: (view) => {
|
|
67
|
+
const { dom, root } = view
|
|
68
|
+
const activeElement = root.activeElement
|
|
69
|
+
|
|
70
|
+
// Don't show the decoration if the dom is blurred because the focus
|
|
71
|
+
// moved outside the browser window.
|
|
72
|
+
if (activeElement === dom) return
|
|
73
|
+
|
|
74
|
+
view.dispatch(setFocusMeta(view.state.tr, true))
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
decorations: (state) => {
|
|
78
|
+
const { selection, doc } = state
|
|
79
|
+
|
|
80
|
+
if (
|
|
81
|
+
selection.empty
|
|
82
|
+
|| !getFocusState(state)
|
|
83
|
+
// When `selection.visible` is false, it indicates that the selection is
|
|
84
|
+
// rendered by the editor and it's not a native browser selection. An
|
|
85
|
+
// example of this is `NodeSelection`. In this situation, since the
|
|
86
|
+
// editor already shows the selection, we don't need to display a
|
|
87
|
+
// virtual selection.
|
|
88
|
+
|| !selection.visible
|
|
89
|
+
) {
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return DecorationSet.create(doc, [
|
|
94
|
+
Decoration.inline(selection.from, selection.to, {
|
|
95
|
+
class: 'prosekit-virtual-selection',
|
|
96
|
+
}),
|
|
97
|
+
])
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
})
|
package/src/yjs/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export {
|
|
2
|
+
defineYjs,
|
|
3
|
+
type YjsExtension,
|
|
4
|
+
type YjsOptions,
|
|
5
|
+
} from './yjs'
|
|
6
|
+
export { defineYjsCommands } from './yjs-commands'
|
|
7
|
+
export {
|
|
8
|
+
defineYjsCursorPlugin,
|
|
9
|
+
type YjsCursorOptions,
|
|
10
|
+
type YjsCursorPluginOptions,
|
|
11
|
+
} from './yjs-cursor-plugin'
|
|
12
|
+
export { defineYjsKeymap } from './yjs-keymap'
|
|
13
|
+
export {
|
|
14
|
+
defineYjsSyncPlugin,
|
|
15
|
+
type YjsSyncOptions,
|
|
16
|
+
type YjsSyncPluginOptions,
|
|
17
|
+
} from './yjs-sync-plugin'
|
|
18
|
+
export {
|
|
19
|
+
defineYjsUndoPlugin,
|
|
20
|
+
type YjsUndoOptions,
|
|
21
|
+
type YjsUndoPluginOptions,
|
|
22
|
+
} from './yjs-undo-plugin'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
.ProseMirror .ProseMirror-yjs-cursor {
|
|
2
|
+
position: absolute;
|
|
3
|
+
height: 1em;
|
|
4
|
+
border-left: black;
|
|
5
|
+
border-left-width: 2px;
|
|
6
|
+
border-left-style: solid;
|
|
7
|
+
border-color: orange;
|
|
8
|
+
word-break: normal;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ProseMirror .ProseMirror-yjs-cursor > div {
|
|
13
|
+
position: relative;
|
|
14
|
+
top: -1.05em;
|
|
15
|
+
padding-right: 2px;
|
|
16
|
+
padding-left: 2px;
|
|
17
|
+
background-color: rgb(250, 129, 0);
|
|
18
|
+
color: white;
|
|
19
|
+
font-style: normal;
|
|
20
|
+
font-weight: normal;
|
|
21
|
+
font-size: 13px;
|
|
22
|
+
line-height: normal;
|
|
23
|
+
font-family: serif;
|
|
24
|
+
-webkit-user-select: none;
|
|
25
|
+
-moz-user-select: none;
|
|
26
|
+
-ms-user-select: none;
|
|
27
|
+
user-select: none;
|
|
28
|
+
}
|
|
29
|
+
.ProseMirror > .ProseMirror-yjs-cursor:first-child {
|
|
30
|
+
margin-top: 16px;
|
|
31
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineCommands,
|
|
3
|
+
type Extension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
import {
|
|
6
|
+
redoCommand,
|
|
7
|
+
undoCommand,
|
|
8
|
+
} from 'y-prosemirror'
|
|
9
|
+
|
|
10
|
+
const commands = {
|
|
11
|
+
undo: () => undoCommand,
|
|
12
|
+
redo: () => redoCommand,
|
|
13
|
+
} as const
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export type YjsCommandsExtension = Extension<{
|
|
19
|
+
Commands: {
|
|
20
|
+
undo: []
|
|
21
|
+
redo: []
|
|
22
|
+
}
|
|
23
|
+
}>
|
|
24
|
+
|
|
25
|
+
export function defineYjsCommands(): YjsCommandsExtension {
|
|
26
|
+
return defineCommands(commands)
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
definePlugin,
|
|
3
|
+
type PlainExtension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
import type { Plugin } from '@prosekit/pm/state'
|
|
6
|
+
import { yCursorPlugin } from 'y-prosemirror'
|
|
7
|
+
import type { Awareness } from 'y-protocols/awareness'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Options for `y-prosemirror`'s `yCursorPlugin`.
|
|
11
|
+
*/
|
|
12
|
+
export type YjsCursorPluginOptions = NonNullable<
|
|
13
|
+
Parameters<typeof yCursorPlugin>[1]
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export interface YjsCursorOptions extends YjsCursorPluginOptions {
|
|
17
|
+
awareness: Awareness
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function defineYjsCursorPlugin(
|
|
21
|
+
options: YjsCursorOptions,
|
|
22
|
+
): PlainExtension {
|
|
23
|
+
const { awareness, ...rest } = options
|
|
24
|
+
return definePlugin(yCursorPlugin(awareness, rest) as Plugin)
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineKeymap,
|
|
3
|
+
isApple,
|
|
4
|
+
type Keymap,
|
|
5
|
+
type PlainExtension,
|
|
6
|
+
} from '@prosekit/core'
|
|
7
|
+
import {
|
|
8
|
+
redoCommand,
|
|
9
|
+
undoCommand,
|
|
10
|
+
} from 'y-prosemirror'
|
|
11
|
+
|
|
12
|
+
const keymap: Keymap = {
|
|
13
|
+
'Mod-z': undoCommand,
|
|
14
|
+
'Shift-Mod-z': redoCommand,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!isApple) {
|
|
18
|
+
keymap['Mod-y'] = redoCommand
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function defineYjsKeymap(): PlainExtension {
|
|
22
|
+
return defineKeymap(keymap)
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
definePlugin,
|
|
3
|
+
type PlainExtension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
import type { Plugin } from '@prosekit/pm/state'
|
|
6
|
+
import { ySyncPlugin } from 'y-prosemirror'
|
|
7
|
+
import type * as Y from 'yjs'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Options for `y-prosemirror`'s `ySyncPlugin`.
|
|
11
|
+
*/
|
|
12
|
+
export type YjsSyncPluginOptions = NonNullable<
|
|
13
|
+
Parameters<typeof ySyncPlugin>[1]
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export interface YjsSyncOptions extends YjsSyncPluginOptions {
|
|
17
|
+
fragment: Y.XmlFragment
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function defineYjsSyncPlugin(options: YjsSyncOptions): PlainExtension {
|
|
21
|
+
const { fragment, ...rest } = options
|
|
22
|
+
return definePlugin(ySyncPlugin(fragment, rest) as Plugin)
|
|
23
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
definePlugin,
|
|
3
|
+
type PlainExtension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
import type { ProseMirrorPlugin } from '@prosekit/pm/state'
|
|
6
|
+
import type { EditorView } from '@prosekit/pm/view'
|
|
7
|
+
import {
|
|
8
|
+
yUndoPlugin as originalYUndoPlugin,
|
|
9
|
+
yUndoPluginKey,
|
|
10
|
+
} from 'y-prosemirror'
|
|
11
|
+
import type { UndoManager as YjsUndoManager } from 'yjs'
|
|
12
|
+
|
|
13
|
+
type UndoManager = YjsUndoManager & { restore: () => void }
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @see https://github.com/yjs/y-prosemirror/issues/114 and https://github.com/yjs/y-prosemirror/issues/102
|
|
17
|
+
*/
|
|
18
|
+
function fixYUndoPlugin(yUndoPluginInstance: ProseMirrorPlugin) {
|
|
19
|
+
const originalUndoPluginView = yUndoPluginInstance.spec.view
|
|
20
|
+
yUndoPluginInstance.spec.view = (view: EditorView) => {
|
|
21
|
+
const pluginState = yUndoPluginKey.getState(view.state)
|
|
22
|
+
if (!pluginState) {
|
|
23
|
+
return {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const undoManager = pluginState.undoManager as UndoManager
|
|
27
|
+
|
|
28
|
+
if (undoManager.restore) {
|
|
29
|
+
undoManager.restore()
|
|
30
|
+
undoManager.restore = () => {}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const viewRet = originalUndoPluginView
|
|
34
|
+
? originalUndoPluginView(view)
|
|
35
|
+
: undefined
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
destroy: () => {
|
|
39
|
+
const hasUndoManSelf = undoManager.trackedOrigins.has(undoManager)
|
|
40
|
+
|
|
41
|
+
const observers = undoManager._observers
|
|
42
|
+
|
|
43
|
+
undoManager.restore = () => {
|
|
44
|
+
if (hasUndoManSelf) {
|
|
45
|
+
undoManager.trackedOrigins.add(undoManager)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
undoManager.doc.on(
|
|
49
|
+
'afterTransaction',
|
|
50
|
+
undoManager.afterTransactionHandler,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
undoManager._observers = observers
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (viewRet?.destroy) {
|
|
57
|
+
viewRet.destroy()
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Options for the `y-prosemirror`'s `yUndoPlugin`.
|
|
66
|
+
*/
|
|
67
|
+
export type YjsUndoPluginOptions = NonNullable<
|
|
68
|
+
Parameters<typeof originalYUndoPlugin>[0]
|
|
69
|
+
>
|
|
70
|
+
|
|
71
|
+
export interface YjsUndoOptions extends YjsUndoPluginOptions {}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
function yUndoPlugin(options?: YjsUndoOptions) {
|
|
77
|
+
const yUndoPluginInstance = originalYUndoPlugin(options)
|
|
78
|
+
fixYUndoPlugin(yUndoPluginInstance)
|
|
79
|
+
return yUndoPluginInstance
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
export function defineYjsUndoPlugin(options: YjsUndoOptions): PlainExtension {
|
|
86
|
+
return definePlugin(yUndoPlugin(options))
|
|
87
|
+
}
|