@prosekit/extensions 0.11.4 → 0.11.6
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-E7nCfdnR.js +58 -0
- package/dist/drop-indicator-E7nCfdnR.js.map +1 -0
- package/dist/enter-rule-RdhEA900.js +2 -1
- package/dist/enter-rule-RdhEA900.js.map +1 -0
- package/dist/file-DVUhe5KJ.js +134 -0
- package/dist/file-DVUhe5KJ.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/index-DY6lIIYV.d.ts +134 -0
- package/dist/index-DY6lIIYV.d.ts.map +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-CGmswjQ_.js} +3 -3
- package/dist/mark-rule-CGmswjQ_.js.map +1 -0
- package/dist/{paste-rule-Cca3n5TA.js → paste-rule-BIztzELg.js} +5 -15
- package/dist/paste-rule-BIztzELg.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 +3 -2
- 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 +5 -107
- 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 -125
- package/dist/prosekit-extensions-file.js +1 -139
- 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 -5
- 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 +80 -3
- package/dist/prosekit-extensions-image.d.ts.map +1 -0
- package/dist/prosekit-extensions-image.js +90 -10
- 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 +7 -8
- 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 -5
- 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 -5
- 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 +47 -114
- package/dist/prosekit-extensions-table.d.ts.map +1 -0
- package/dist/prosekit-extensions-table.js +2 -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.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 → shiki-highlighter-chunk-Cwu1Jr9o.d.ts} +2 -1
- package/dist/shiki-highlighter-chunk-Cwu1Jr9o.d.ts.map +1 -0
- package/dist/shiki-highlighter-chunk.d.ts +1 -1
- 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-BNwuK7xg.js +297 -0
- package/dist/table-BNwuK7xg.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 +12 -10
- 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 +62 -0
- package/src/drop-indicator/drop-indicator.ts +35 -0
- package/src/drop-indicator/index.ts +14 -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 +140 -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 +36 -0
- package/src/image/image-spec.ts +72 -0
- package/src/image/image-upload-handler.ts +156 -0
- package/src/image/image.ts +25 -0
- package/src/image/index.ts +22 -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/drop-indicator-dB9rZn8e.js +0 -267
- package/dist/table-CPI9ZxbK.js +0 -760
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export {
|
|
2
|
+
defineHorizontalRule,
|
|
3
|
+
type HorizontalRuleExtension,
|
|
4
|
+
} from './horizontal-rule'
|
|
5
|
+
export {
|
|
6
|
+
defineHorizontalRuleCommands,
|
|
7
|
+
insertHorizontalRule,
|
|
8
|
+
type HorizontalRuleCommandsExtension,
|
|
9
|
+
} from './horizontal-rule-commands'
|
|
10
|
+
export { defineHorizontalRuleInputRule } from './horizontal-rule-input-rule'
|
|
11
|
+
export {
|
|
12
|
+
defineHorizontalRuleSpec,
|
|
13
|
+
type HorizontalRuleSpecExtension,
|
|
14
|
+
} from './horizontal-rule-spec'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineCommands,
|
|
3
|
+
insertNode,
|
|
4
|
+
type Extension,
|
|
5
|
+
} from '@prosekit/core'
|
|
6
|
+
import type { Command } from '@prosekit/pm/state'
|
|
7
|
+
|
|
8
|
+
import type { ImageAttrs } from './image-spec'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export type ImageCommandsExtension = Extension<{
|
|
14
|
+
Commands: {
|
|
15
|
+
insertImage: [attrs?: ImageAttrs]
|
|
16
|
+
}
|
|
17
|
+
}>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns a command that inserts an image node with the given attributes at the
|
|
21
|
+
* current selection position.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export function insertImage(attrs?: ImageAttrs): Command {
|
|
26
|
+
return insertNode({ type: 'image', attrs })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export function defineImageCommands(): ImageCommandsExtension {
|
|
33
|
+
return defineCommands({
|
|
34
|
+
insertImage,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineNodeSpec,
|
|
3
|
+
type Extension,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export interface ImageAttrs {
|
|
10
|
+
src?: string | null
|
|
11
|
+
width?: number | null
|
|
12
|
+
height?: number | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export type ImageSpecExtension = Extension<{
|
|
19
|
+
Nodes: {
|
|
20
|
+
image: ImageAttrs
|
|
21
|
+
}
|
|
22
|
+
}>
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export function defineImageSpec(): ImageSpecExtension {
|
|
28
|
+
return defineNodeSpec({
|
|
29
|
+
name: 'image',
|
|
30
|
+
attrs: {
|
|
31
|
+
src: { default: null, validate: 'string|null' },
|
|
32
|
+
width: { default: null, validate: 'number|null' },
|
|
33
|
+
height: { default: null, validate: 'number|null' },
|
|
34
|
+
},
|
|
35
|
+
group: 'block',
|
|
36
|
+
defining: true,
|
|
37
|
+
draggable: true,
|
|
38
|
+
parseDOM: [
|
|
39
|
+
{
|
|
40
|
+
tag: 'img[src]',
|
|
41
|
+
getAttrs: (element): ImageAttrs => {
|
|
42
|
+
if (typeof element === 'string') {
|
|
43
|
+
return { src: null }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const src = element.getAttribute('src') || null
|
|
47
|
+
|
|
48
|
+
let width: number | null = null
|
|
49
|
+
let height: number | null = null
|
|
50
|
+
|
|
51
|
+
const rect = element.getBoundingClientRect()
|
|
52
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
53
|
+
width = rect.width
|
|
54
|
+
height = rect.height
|
|
55
|
+
} else if (
|
|
56
|
+
element instanceof HTMLImageElement
|
|
57
|
+
&& element.naturalWidth > 0
|
|
58
|
+
&& element.naturalHeight > 0
|
|
59
|
+
) {
|
|
60
|
+
width = element.naturalWidth
|
|
61
|
+
height = element.naturalHeight
|
|
62
|
+
}
|
|
63
|
+
return { src, width, height }
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
toDOM(node) {
|
|
68
|
+
const attrs = node.attrs as ImageAttrs
|
|
69
|
+
return ['img', attrs]
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
insertNode,
|
|
3
|
+
ProseKitError,
|
|
4
|
+
union,
|
|
5
|
+
type PlainExtension,
|
|
6
|
+
} from '@prosekit/core'
|
|
7
|
+
import type { EditorView } from '@prosekit/pm/view'
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
defineFileDropHandler,
|
|
11
|
+
defineFilePasteHandler,
|
|
12
|
+
UploadTask,
|
|
13
|
+
type FileDropHandler,
|
|
14
|
+
type FileDropHandlerOptions,
|
|
15
|
+
type FilePasteHandler,
|
|
16
|
+
type FilePasteHandlerOptions,
|
|
17
|
+
type Uploader,
|
|
18
|
+
} from '../file'
|
|
19
|
+
|
|
20
|
+
import type { ImageAttrs } from './image-spec'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A predicate to determine if the pasted file should be uploaded and inserted as an image.
|
|
24
|
+
*/
|
|
25
|
+
export type ImageCanPastePredicate = (options: FilePasteHandlerOptions) => boolean
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A predicate to determine if the dropped file should be uploaded and inserted as an image.
|
|
29
|
+
*/
|
|
30
|
+
export type ImageCanDropPredicate = (options: FileDropHandlerOptions) => boolean
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A handler to be called when an error occurs during the upload.
|
|
34
|
+
*/
|
|
35
|
+
export type ImageUploadErrorHandler = (options: ImageUploadErrorHandlerOptions) => void
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Options for the {@link ImageUploadErrorHandler} callback.
|
|
39
|
+
*/
|
|
40
|
+
export interface ImageUploadErrorHandlerOptions {
|
|
41
|
+
/**
|
|
42
|
+
* The file that was uploaded.
|
|
43
|
+
*/
|
|
44
|
+
file: File
|
|
45
|
+
/**
|
|
46
|
+
* The error that occurred during the upload.
|
|
47
|
+
*/
|
|
48
|
+
error: unknown
|
|
49
|
+
/**
|
|
50
|
+
* The upload task that was used to upload the file.
|
|
51
|
+
*/
|
|
52
|
+
uploadTask: UploadTask<string>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Options for {@link defineImageUploadHandler}.
|
|
57
|
+
*/
|
|
58
|
+
export interface ImageUploadHandlerOptions {
|
|
59
|
+
/**
|
|
60
|
+
* The uploader used to upload the file. It should return a promise that
|
|
61
|
+
* resolves to the URL of the uploaded image.
|
|
62
|
+
*/
|
|
63
|
+
uploader: Uploader<string>
|
|
64
|
+
/**
|
|
65
|
+
* A predicate to determine if the pasted file should be uploaded and inserted as an image.
|
|
66
|
+
* If not provided, it defaults to only allowing paste of files with a content type starting with `image/`.
|
|
67
|
+
*/
|
|
68
|
+
canPaste?: ImageCanPastePredicate
|
|
69
|
+
/**
|
|
70
|
+
* A predicate to determine if the dropped file should be uploaded and inserted as an image.
|
|
71
|
+
* If not provided, it defaults to only allowing drop of files with a content type starting with `image/`.
|
|
72
|
+
*/
|
|
73
|
+
canDrop?: ImageCanDropPredicate
|
|
74
|
+
/**
|
|
75
|
+
* A handler to be called when an error occurs during the upload.
|
|
76
|
+
* If not provided, it defaults to logging the error to the console.
|
|
77
|
+
*/
|
|
78
|
+
onError?: ImageUploadErrorHandler
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function defaultCanUpload({ file }: { file: File }): boolean {
|
|
82
|
+
// Only handle image files by default
|
|
83
|
+
return file.type.startsWith('image/')
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const defaultOnError: ImageUploadErrorHandler = ({ error }) => {
|
|
87
|
+
console.error('[prosekit] Failed to upload image:', error)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Returns an extension that handles image file uploads when pasting or dropping
|
|
92
|
+
* images into the editor.
|
|
93
|
+
*
|
|
94
|
+
* @param options
|
|
95
|
+
*/
|
|
96
|
+
export function defineImageUploadHandler({
|
|
97
|
+
uploader,
|
|
98
|
+
canPaste = defaultCanUpload,
|
|
99
|
+
canDrop = defaultCanUpload,
|
|
100
|
+
onError = defaultOnError,
|
|
101
|
+
}: ImageUploadHandlerOptions): PlainExtension {
|
|
102
|
+
const handleInsert = (view: EditorView, file: File, pos?: number): boolean => {
|
|
103
|
+
const uploadTask = new UploadTask({ file, uploader })
|
|
104
|
+
const objectURL = uploadTask.objectURL
|
|
105
|
+
const attrs: ImageAttrs = { src: objectURL }
|
|
106
|
+
uploadTask.finished.then((resultURL) => {
|
|
107
|
+
if (view.isDestroyed) {
|
|
108
|
+
return
|
|
109
|
+
} else if (typeof resultURL !== 'string') {
|
|
110
|
+
const error = new ProseKitError(`Unexpected upload result. Expected a string but got ${typeof resultURL}`)
|
|
111
|
+
onError({ file, error, uploadTask })
|
|
112
|
+
} else {
|
|
113
|
+
replaceImageURL(view, objectURL, resultURL)
|
|
114
|
+
UploadTask.delete(objectURL)
|
|
115
|
+
}
|
|
116
|
+
}).catch((error) => {
|
|
117
|
+
onError({ file, error, uploadTask })
|
|
118
|
+
})
|
|
119
|
+
const command = insertNode({ type: 'image', attrs, pos })
|
|
120
|
+
return command(view.state, view.dispatch, view)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const handlePaste: FilePasteHandler = (options) => {
|
|
124
|
+
if (!canPaste(options)) return false
|
|
125
|
+
return handleInsert(options.view, options.file)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const handleDrop: FileDropHandler = (options) => {
|
|
129
|
+
if (!canDrop(options)) return false
|
|
130
|
+
return handleInsert(options.view, options.file, options.pos)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return union(
|
|
134
|
+
defineFilePasteHandler(handlePaste),
|
|
135
|
+
defineFileDropHandler(handleDrop),
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function replaceImageURL(view: EditorView, oldURL: string, newURL: string) {
|
|
140
|
+
const positions: number[] = []
|
|
141
|
+
view.state.doc.descendants((node, pos) => {
|
|
142
|
+
if (node.type.name === 'image') {
|
|
143
|
+
const attrs = node.attrs as ImageAttrs
|
|
144
|
+
if (attrs.src === oldURL) {
|
|
145
|
+
positions.push(pos)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
if (positions.length > 0) {
|
|
150
|
+
const tr = view.state.tr
|
|
151
|
+
for (const pos of positions) {
|
|
152
|
+
tr.setNodeAttribute(pos, 'src', newURL)
|
|
153
|
+
}
|
|
154
|
+
view.dispatch(tr)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
union,
|
|
3
|
+
type Union,
|
|
4
|
+
} from '@prosekit/core'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
defineImageCommands,
|
|
8
|
+
type ImageCommandsExtension,
|
|
9
|
+
} from './image-commands'
|
|
10
|
+
import {
|
|
11
|
+
defineImageSpec,
|
|
12
|
+
type ImageSpecExtension,
|
|
13
|
+
} from './image-spec'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export type ImageExtension = Union<[ImageSpecExtension, ImageCommandsExtension]>
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export function defineImage(): ImageExtension {
|
|
24
|
+
return union(defineImageSpec(), defineImageCommands())
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export {
|
|
2
|
+
defineImage,
|
|
3
|
+
type ImageExtension,
|
|
4
|
+
} from './image'
|
|
5
|
+
export {
|
|
6
|
+
defineImageCommands,
|
|
7
|
+
insertImage,
|
|
8
|
+
type ImageCommandsExtension,
|
|
9
|
+
} from './image-commands'
|
|
10
|
+
export {
|
|
11
|
+
defineImageSpec,
|
|
12
|
+
type ImageAttrs,
|
|
13
|
+
type ImageSpecExtension,
|
|
14
|
+
} from './image-spec'
|
|
15
|
+
export {
|
|
16
|
+
defineImageUploadHandler,
|
|
17
|
+
type ImageCanDropPredicate,
|
|
18
|
+
type ImageCanPastePredicate,
|
|
19
|
+
type ImageUploadErrorHandler,
|
|
20
|
+
type ImageUploadErrorHandlerOptions,
|
|
21
|
+
type ImageUploadHandlerOptions,
|
|
22
|
+
} from './image-upload-handler'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineFacet,
|
|
3
|
+
defineFacetPayload,
|
|
4
|
+
getMarkType,
|
|
5
|
+
getNodeType,
|
|
6
|
+
isMarkAbsent,
|
|
7
|
+
maybeRun,
|
|
8
|
+
pluginFacet,
|
|
9
|
+
type PlainExtension,
|
|
10
|
+
type PluginPayload,
|
|
11
|
+
} from '@prosekit/core'
|
|
12
|
+
import {
|
|
13
|
+
InputRule,
|
|
14
|
+
inputRules,
|
|
15
|
+
textblockTypeInputRule,
|
|
16
|
+
wrappingInputRule,
|
|
17
|
+
} from '@prosekit/pm/inputrules'
|
|
18
|
+
import type {
|
|
19
|
+
Attrs,
|
|
20
|
+
MarkType,
|
|
21
|
+
NodeType,
|
|
22
|
+
ProseMirrorNode,
|
|
23
|
+
Schema,
|
|
24
|
+
} from '@prosekit/pm/model'
|
|
25
|
+
import type { Plugin } from '@prosekit/pm/state'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Defines an input rule extension.
|
|
29
|
+
*
|
|
30
|
+
* @param rule - The ProseMirror input rule to add.
|
|
31
|
+
*
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export function defineInputRule(rule: InputRule): PlainExtension {
|
|
35
|
+
return defineInputRuleFacetPayload(() => rule)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Options for {@link defineMarkInputRule}.
|
|
40
|
+
*
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
export interface MarkInputRuleOptions {
|
|
44
|
+
/**
|
|
45
|
+
* The regular expression to match against, which should end with `$` and has
|
|
46
|
+
* exactly one capture group. All other matched text outside the capture group
|
|
47
|
+
* will be deleted.
|
|
48
|
+
*/
|
|
49
|
+
regex: RegExp
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The type of mark to set.
|
|
53
|
+
*/
|
|
54
|
+
type: string | MarkType
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Attributes to set on the mark.
|
|
58
|
+
*/
|
|
59
|
+
attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null)
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Whether this rule should fire inside marks marked as [code](https://prosemirror.net/docs/ref/#model.MarkSpec.code).
|
|
63
|
+
*
|
|
64
|
+
* @default `false`
|
|
65
|
+
*/
|
|
66
|
+
inCodeMark?: boolean
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
export function createMarkInputRule({
|
|
73
|
+
regex,
|
|
74
|
+
type,
|
|
75
|
+
attrs = null,
|
|
76
|
+
inCodeMark = false,
|
|
77
|
+
}: MarkInputRuleOptions): InputRule {
|
|
78
|
+
const rule = new InputRule(regex, (state, match, start, end) => {
|
|
79
|
+
const { tr, schema } = state
|
|
80
|
+
const [fullText, markText] = match
|
|
81
|
+
|
|
82
|
+
if (!markText) {
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const markStart = start + fullText.indexOf(markText)
|
|
87
|
+
const markEnd = markStart + markText.length
|
|
88
|
+
|
|
89
|
+
if (!(start <= markStart && markStart < markEnd && markEnd <= end)) {
|
|
90
|
+
// Incorrect regex.
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const markType = getMarkType(schema, type)
|
|
95
|
+
const mark = markType.create(maybeRun(attrs, match))
|
|
96
|
+
|
|
97
|
+
if (!isMarkAbsent(tr.doc, markStart, markEnd, markType, attrs)) {
|
|
98
|
+
// The mark is already active.
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const initialStoredMarks = tr.storedMarks ?? []
|
|
103
|
+
|
|
104
|
+
tr.addMark(markStart, markEnd, mark)
|
|
105
|
+
|
|
106
|
+
if (markEnd < end) {
|
|
107
|
+
tr.delete(markEnd, end)
|
|
108
|
+
}
|
|
109
|
+
if (start < markStart) {
|
|
110
|
+
tr.delete(start, markStart)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Make sure not to reactivate any marks which had previously been
|
|
114
|
+
// deactivated. By keeping track of the initial stored marks we are able to
|
|
115
|
+
// discard any unintended consequences of deleting text and adding it again.
|
|
116
|
+
tr.setStoredMarks(initialStoredMarks)
|
|
117
|
+
|
|
118
|
+
return tr
|
|
119
|
+
}, { inCodeMark })
|
|
120
|
+
|
|
121
|
+
return rule
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Defines an input rule for automatically adding inline marks when a given
|
|
126
|
+
* pattern is typed.
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
*/
|
|
130
|
+
export function defineMarkInputRule(
|
|
131
|
+
options: MarkInputRuleOptions,
|
|
132
|
+
): PlainExtension {
|
|
133
|
+
return defineInputRule(createMarkInputRule(options))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Defines an input rule that changes the type of a textblock when the matched
|
|
138
|
+
* text is typed into it.
|
|
139
|
+
*
|
|
140
|
+
* See also [textblockTypeInputRule](https://prosemirror.net/docs/ref/#inputrules.textblockTypeInputRule)
|
|
141
|
+
*
|
|
142
|
+
* @param options
|
|
143
|
+
*
|
|
144
|
+
* @public
|
|
145
|
+
*/
|
|
146
|
+
export function defineTextBlockInputRule({
|
|
147
|
+
regex,
|
|
148
|
+
type,
|
|
149
|
+
attrs,
|
|
150
|
+
}: {
|
|
151
|
+
/**
|
|
152
|
+
* The regular expression to match against, which should end with `$`. It
|
|
153
|
+
* usually also starts with `^` to that it is only matched at the start of a
|
|
154
|
+
* textblock.
|
|
155
|
+
*/
|
|
156
|
+
regex: RegExp
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The node type to replace the matched text with.
|
|
160
|
+
*/
|
|
161
|
+
type: string | NodeType
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Attributes to set on the node.
|
|
165
|
+
*/
|
|
166
|
+
attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null)
|
|
167
|
+
}): PlainExtension {
|
|
168
|
+
return defineInputRuleFacetPayload(({ schema }): InputRule => {
|
|
169
|
+
const nodeType = getNodeType(schema, type)
|
|
170
|
+
return textblockTypeInputRule(regex, nodeType, attrs)
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Defines an input rule for automatically wrapping a textblock when a given
|
|
176
|
+
* string is typed.
|
|
177
|
+
*
|
|
178
|
+
* See also [wrappingInputRule](https://prosemirror.net/docs/ref/#inputrules.wrappingInputRule)
|
|
179
|
+
*
|
|
180
|
+
* @param options
|
|
181
|
+
*
|
|
182
|
+
* @public
|
|
183
|
+
*/
|
|
184
|
+
export function defineWrappingInputRule({
|
|
185
|
+
regex,
|
|
186
|
+
type,
|
|
187
|
+
attrs,
|
|
188
|
+
join,
|
|
189
|
+
}: {
|
|
190
|
+
/**
|
|
191
|
+
* The regular expression to match against, which should end with `$`. It
|
|
192
|
+
* usually also starts with `^` to that it is only matched at the start of a
|
|
193
|
+
* textblock.
|
|
194
|
+
*/
|
|
195
|
+
regex: RegExp
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The type of node to wrap in.
|
|
199
|
+
*/
|
|
200
|
+
type: string | NodeType
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Attributes to set on the node.
|
|
204
|
+
*/
|
|
205
|
+
attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null)
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* By default, if there's a node with the same type above the newly wrapped
|
|
209
|
+
* node, the rule will try to
|
|
210
|
+
* [join](https://prosemirror.net/docs/ref/#transform.Transform.join) those
|
|
211
|
+
* two nodes. You can pass a join predicate, which takes a regular expression
|
|
212
|
+
* match and the node before the wrapped node, and can return a boolean to
|
|
213
|
+
* indicate whether a join should happen.
|
|
214
|
+
*/
|
|
215
|
+
join?: (match: RegExpMatchArray, node: ProseMirrorNode) => boolean
|
|
216
|
+
}): PlainExtension {
|
|
217
|
+
return defineInputRuleFacetPayload(({ schema }): InputRule => {
|
|
218
|
+
const nodeType = getNodeType(schema, type)
|
|
219
|
+
return wrappingInputRule(regex, nodeType, attrs, join)
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function defineInputRuleFacetPayload(input: InputRulePayload): PlainExtension {
|
|
224
|
+
return defineFacetPayload(inputRuleFacet, [input]) as PlainExtension
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
type InputRulePayload = (context: { schema: Schema }) => InputRule
|
|
228
|
+
|
|
229
|
+
const inputRuleFacet = defineFacet<InputRulePayload, PluginPayload>({
|
|
230
|
+
reducer: (inputs: InputRulePayload[]): PluginPayload => {
|
|
231
|
+
return (context): Plugin[] => {
|
|
232
|
+
const rules: InputRule[] = inputs.flatMap((callback) => callback(context))
|
|
233
|
+
return [inputRules({ rules })]
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
parent: pluginFacet,
|
|
237
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export {
|
|
2
|
+
defineItalic,
|
|
3
|
+
type ItalicExtension,
|
|
4
|
+
} from './italic'
|
|
5
|
+
export {
|
|
6
|
+
defineItalicCommands,
|
|
7
|
+
type ItalicCommandsExtension,
|
|
8
|
+
} from './italic-commands'
|
|
9
|
+
export { defineItalicInputRule } from './italic-input-rule'
|
|
10
|
+
export { defineItalicKeymap } from './italic-keymap'
|
|
11
|
+
export {
|
|
12
|
+
defineItalicSpec,
|
|
13
|
+
type ItalicSpecExtension,
|
|
14
|
+
} from './italic-spec'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createEditor,
|
|
3
|
+
defineBaseCommands,
|
|
4
|
+
union,
|
|
5
|
+
} from '@prosekit/core'
|
|
6
|
+
import {
|
|
7
|
+
describe,
|
|
8
|
+
expect,
|
|
9
|
+
it,
|
|
10
|
+
} from 'vitest'
|
|
11
|
+
|
|
12
|
+
import { defineDoc } from '../doc'
|
|
13
|
+
import { defineParagraph } from '../paragraph'
|
|
14
|
+
import { defineText } from '../text'
|
|
15
|
+
|
|
16
|
+
import { defineItalic } from './index'
|
|
17
|
+
|
|
18
|
+
describe('command', () => {
|
|
19
|
+
const extension = union(
|
|
20
|
+
defineDoc(),
|
|
21
|
+
defineParagraph(),
|
|
22
|
+
defineText(),
|
|
23
|
+
defineItalic(),
|
|
24
|
+
defineBaseCommands(),
|
|
25
|
+
)
|
|
26
|
+
const editor = createEditor({ extension })
|
|
27
|
+
const div = document.body.appendChild(document.createElement('div'))
|
|
28
|
+
editor.mount(div)
|
|
29
|
+
|
|
30
|
+
describe('toggleItalic', () => {
|
|
31
|
+
it('can add and remove italic', () => {
|
|
32
|
+
editor.commands.insertText({ text: 'Hello world' })
|
|
33
|
+
editor.commands.selectAll()
|
|
34
|
+
editor.commands.toggleItalic()
|
|
35
|
+
expect(editor.view.state.doc.toJSON()).toMatchInlineSnapshot(`
|
|
36
|
+
{
|
|
37
|
+
"content": [
|
|
38
|
+
{
|
|
39
|
+
"content": [
|
|
40
|
+
{
|
|
41
|
+
"marks": [
|
|
42
|
+
{
|
|
43
|
+
"type": "italic",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
"text": "Hello world",
|
|
47
|
+
"type": "text",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
"type": "paragraph",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
"type": "doc",
|
|
54
|
+
}
|
|
55
|
+
`)
|
|
56
|
+
editor.commands.toggleItalic()
|
|
57
|
+
expect(editor.view.state.doc.toJSON()).toMatchInlineSnapshot(`
|
|
58
|
+
{
|
|
59
|
+
"content": [
|
|
60
|
+
{
|
|
61
|
+
"content": [
|
|
62
|
+
{
|
|
63
|
+
"text": "Hello world",
|
|
64
|
+
"type": "text",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
"type": "paragraph",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
"type": "doc",
|
|
71
|
+
}
|
|
72
|
+
`)
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineCommands,
|
|
3
|
+
toggleMark,
|
|
4
|
+
type Extension,
|
|
5
|
+
} from '@prosekit/core'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export type ItalicCommandsExtension = Extension<{
|
|
11
|
+
Commands: {
|
|
12
|
+
toggleItalic: []
|
|
13
|
+
}
|
|
14
|
+
}>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export function defineItalicCommands(): ItalicCommandsExtension {
|
|
20
|
+
return defineCommands({
|
|
21
|
+
toggleItalic: () => toggleMark({ type: 'italic' }),
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe,
|
|
3
|
+
expect,
|
|
4
|
+
it,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { setupTest } from '../testing'
|
|
8
|
+
import { inputText } from '../testing/keyboard'
|
|
9
|
+
|
|
10
|
+
describe('defineItalicInputRule', () => {
|
|
11
|
+
const { editor, n, m } = setupTest()
|
|
12
|
+
it('should add italic marks when typing "*"', async () => {
|
|
13
|
+
const doc = n.doc(n.p('<a>'))
|
|
14
|
+
editor.set(doc)
|
|
15
|
+
|
|
16
|
+
await inputText('*word')
|
|
17
|
+
expect(editor.view.state.doc.toJSON()).toEqual(
|
|
18
|
+
n.doc(n.p('*word')).toJSON(),
|
|
19
|
+
)
|
|
20
|
+
await inputText('*')
|
|
21
|
+
expect(editor.view.state.doc.toJSON()).toEqual(
|
|
22
|
+
n.doc(n.p(m.italic('word'))).toJSON(),
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
})
|