@prosekit/extensions 0.7.2 → 0.7.4

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.
Files changed (32) hide show
  1. package/dist/_tsup-dts-rollup.d.ts +393 -83
  2. package/dist/chunk-GPSAJOJA.js +188 -0
  3. package/dist/{chunk-PYT3MOTF.js → chunk-LVMTQOWG.js} +31 -14
  4. package/dist/{chunk-2JYT2MT7.js → chunk-OJCMRVEY.js} +36 -21
  5. package/dist/list/style.css +9 -5
  6. package/dist/placeholder/style.css +1 -1
  7. package/dist/prosekit-extensions-autocomplete.js +62 -33
  8. package/dist/prosekit-extensions-blockquote.js +2 -2
  9. package/dist/prosekit-extensions-bold.js +7 -3
  10. package/dist/prosekit-extensions-code-block.js +77 -41
  11. package/dist/prosekit-extensions-code.js +1 -1
  12. package/dist/prosekit-extensions-commit.js +70 -30
  13. package/dist/prosekit-extensions-enter-rule.js +1 -1
  14. package/dist/prosekit-extensions-heading.js +18 -8
  15. package/dist/prosekit-extensions-image.js +14 -5
  16. package/dist/prosekit-extensions-input-rule.js +1 -1
  17. package/dist/prosekit-extensions-italic.js +1 -1
  18. package/dist/prosekit-extensions-link.js +30 -17
  19. package/dist/prosekit-extensions-list.d.ts +4 -4
  20. package/dist/prosekit-extensions-list.js +33 -22
  21. package/dist/prosekit-extensions-mark-rule.js +1 -1
  22. package/dist/prosekit-extensions-mention.js +6 -4
  23. package/dist/prosekit-extensions-placeholder.js +16 -7
  24. package/dist/prosekit-extensions-readonly.js +1 -1
  25. package/dist/prosekit-extensions-search.js +8 -5
  26. package/dist/prosekit-extensions-strike.js +1 -1
  27. package/dist/prosekit-extensions-table.js +68 -31
  28. package/dist/prosekit-extensions-text-align.d.ts +1 -0
  29. package/dist/prosekit-extensions-text-align.js +4 -2
  30. package/dist/prosekit-extensions-virtual-selection.js +11 -6
  31. package/package.json +9 -8
  32. package/dist/chunk-ZPEMHYTU.js +0 -140
@@ -1,18 +1,9 @@
1
1
  import {
2
2
  defineInputRule
3
- } from "./chunk-PYT3MOTF.js";
3
+ } from "./chunk-LVMTQOWG.js";
4
4
 
5
5
  // src/list/index.ts
6
- import {
7
- defineNodeSpec,
8
- definePlugin,
9
- union
10
- } from "@prosekit/core";
11
- import {
12
- createListPlugins,
13
- createListSpec,
14
- listInputRules
15
- } from "prosemirror-flat-list";
6
+ import { union as union2 } from "@prosekit/core";
16
7
 
17
8
  // src/list/commands.ts
18
9
  import { defineCommands, insertNode } from "@prosekit/core";
@@ -43,6 +34,13 @@ function defineListCommands() {
43
34
  });
44
35
  }
45
36
 
37
+ // src/list/input-rules.ts
38
+ import { union } from "@prosekit/core";
39
+ import { listInputRules } from "prosemirror-flat-list";
40
+ function defineListInputRules() {
41
+ return union(listInputRules.map(defineInputRule));
42
+ }
43
+
46
44
  // src/list/keymap.ts
47
45
  import { defineKeymap } from "@prosekit/core";
48
46
  import { chainCommands, deleteSelection } from "@prosekit/pm/commands";
@@ -60,30 +58,43 @@ var backspaceCommand = chainCommands(
60
58
  deleteSelection,
61
59
  joinListUp,
62
60
  joinCollapsedListBackward
63
- ), listKeymap = {
61
+ );
62
+ var dedentListCommand = createDedentListCommand();
63
+ var indentListCommand = createIndentListCommand();
64
+ var listKeymap = {
64
65
  Enter: enterCommand,
65
66
  Backspace: backspaceCommand,
66
67
  Delete: deleteCommand,
67
- "Mod-[": createDedentListCommand(),
68
- "Mod-]": createIndentListCommand()
68
+ "Mod-]": indentListCommand,
69
+ "Mod-[": dedentListCommand,
70
+ Tab: indentListCommand,
71
+ "Shift-Tab": dedentListCommand
69
72
  };
70
73
  function defineListKeymap() {
71
74
  return defineKeymap(listKeymap);
72
75
  }
73
76
 
74
- // src/list/index.ts
75
- import { ListDOMSerializer } from "prosemirror-flat-list";
76
- function defineListSpec() {
77
- return defineNodeSpec({ ...createListSpec(), name: "list" });
78
- }
77
+ // src/list/plugins.ts
78
+ import { definePlugin } from "@prosekit/core";
79
+ import { createListPlugins } from "prosemirror-flat-list";
79
80
  function defineListPlugins() {
80
81
  return definePlugin(({ schema }) => createListPlugins({ schema }));
81
82
  }
82
- function defineListInputRules() {
83
- return union(listInputRules.map(defineInputRule));
83
+
84
+ // src/list/spec.ts
85
+ import { defineNodeSpec } from "@prosekit/core";
86
+ import { createListSpec } from "prosemirror-flat-list";
87
+ function defineListSpec() {
88
+ return defineNodeSpec({
89
+ ...createListSpec(),
90
+ name: "list"
91
+ });
84
92
  }
93
+
94
+ // src/list/index.ts
95
+ import { ListDOMSerializer } from "prosemirror-flat-list";
85
96
  function defineList() {
86
- return union([
97
+ return union2([
87
98
  defineListSpec(),
88
99
  defineListPlugins(),
89
100
  defineListKeymap(),
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineMarkRule
3
- } from "./chunk-ZPEMHYTU.js";
3
+ } from "./chunk-GPSAJOJA.js";
4
4
  export {
5
5
  defineMarkRule
6
6
  };
@@ -8,18 +8,18 @@ import {
8
8
  function defineMentionSpec() {
9
9
  return defineNodeSpec({
10
10
  name: "mention",
11
- atom: !0,
11
+ atom: true,
12
12
  group: "inline",
13
13
  attrs: {
14
14
  id: {},
15
15
  value: {},
16
16
  kind: { default: "" }
17
17
  },
18
- inline: !0,
18
+ inline: true,
19
19
  leafText: (node) => node.attrs.value.toString(),
20
20
  parseDOM: [
21
21
  {
22
- tag: "span[data-mention]",
22
+ tag: `span[data-mention]`,
23
23
  getAttrs: (dom) => ({
24
24
  id: dom.getAttribute("data-id") || "",
25
25
  kind: dom.getAttribute("data-mention") || "",
@@ -41,7 +41,9 @@ function defineMentionSpec() {
41
41
  }
42
42
  function defineMentionCommands() {
43
43
  return defineCommands({
44
- insertMention: (attrs) => insertNode({ type: "mention", attrs })
44
+ insertMention: (attrs) => {
45
+ return insertNode({ type: "mention", attrs });
46
+ }
45
47
  });
46
48
  }
47
49
  function defineMention() {
@@ -11,24 +11,33 @@ function createPlaceholderPlugin(options) {
11
11
  key: new PluginKey("prosekit-placeholder"),
12
12
  props: {
13
13
  decorations: (state) => {
14
- if (options.strategy === "doc" && !isDocEmpty(state.doc) || isInCodeBlock(state.selection))
14
+ if (options.strategy === "doc" && !isDocEmpty(state.doc)) {
15
15
  return null;
16
- let placeholderText = options.placeholder, deco = createPlaceholderDecoration(state, placeholderText);
17
- return deco ? DecorationSet.create(state.doc, [deco]) : null;
16
+ }
17
+ if (isInCodeBlock(state.selection)) {
18
+ return null;
19
+ }
20
+ const placeholderText = options.placeholder;
21
+ const deco = createPlaceholderDecoration(state, placeholderText);
22
+ if (!deco) {
23
+ return null;
24
+ }
25
+ return DecorationSet.create(state.doc, [deco]);
18
26
  }
19
27
  }
20
28
  });
21
29
  }
22
30
  function isDocEmpty(doc) {
23
31
  var _a;
24
- return doc.childCount <= 1 && !((_a = doc.firstChild) != null && _a.content.size);
32
+ return doc.childCount <= 1 && !((_a = doc.firstChild) == null ? void 0 : _a.content.size);
25
33
  }
26
34
  function createPlaceholderDecoration(state, placeholderText) {
27
- let { selection } = state;
35
+ const { selection } = state;
28
36
  if (!selection.empty) return null;
29
- let $pos = selection.$anchor, node = $pos.parent;
37
+ const $pos = selection.$anchor;
38
+ const node = $pos.parent;
30
39
  if (node.content.size > 0) return null;
31
- let before = $pos.before();
40
+ const before = $pos.before();
32
41
  return Decoration.node(before, before + node.nodeSize, {
33
42
  class: "prosekit-placeholder",
34
43
  "data-placeholder": placeholderText
@@ -7,7 +7,7 @@ function defineReadonly() {
7
7
  var plugin = new ProseMirrorPlugin({
8
8
  key: new PluginKey("prosekey-readonly"),
9
9
  props: {
10
- editable: () => !1
10
+ editable: () => false
11
11
  }
12
12
  });
13
13
  export {
@@ -13,13 +13,13 @@ import {
13
13
  search
14
14
  } from "prosemirror-search";
15
15
  function defineSearchQuery(options) {
16
- let query = new SearchQuery(options);
16
+ const query = new SearchQuery(options);
17
17
  return definePlugin(search({ initialQuery: query }));
18
18
  }
19
19
  function scrollActiveIntoView(view) {
20
20
  if (view.isDestroyed) return;
21
- let active = view.dom.querySelector(".ProseMirror-active-search-match");
22
- active == null || active.scrollIntoView({
21
+ const active = view.dom.querySelector(".ProseMirror-active-search-match");
22
+ active == null ? void 0 : active.scrollIntoView({
23
23
  block: "nearest",
24
24
  inline: "nearest",
25
25
  behavior: "smooth"
@@ -27,8 +27,11 @@ function scrollActiveIntoView(view) {
27
27
  }
28
28
  function withScrollActiveIntoView(command) {
29
29
  return (state, dispatch, view) => {
30
- let result = command(state, dispatch, view);
31
- return result && dispatch && view && setTimeout(() => scrollActiveIntoView(view), 50), result;
30
+ const result = command(state, dispatch, view);
31
+ if (result && dispatch && view) {
32
+ setTimeout(() => scrollActiveIntoView(view), 50);
33
+ }
34
+ return result;
32
35
  };
33
36
  }
34
37
  function defineSearchCommands() {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineMarkInputRule
3
- } from "./chunk-PYT3MOTF.js";
3
+ } from "./chunk-LVMTQOWG.js";
4
4
 
5
5
  // src/strike/index.ts
6
6
  import {
@@ -10,13 +10,23 @@ import {
10
10
  } from "@prosekit/core";
11
11
  import { TextSelection } from "@prosekit/pm/state";
12
12
  function createEmptyTable(schema, row, col, header) {
13
- let table = getNodeType(schema, "table"), tableRow = getNodeType(schema, "tableRow"), tableCell = getNodeType(schema, "tableCell"), tableHeaderCell = getNodeType(schema, "tableHeaderCell"), createHeaderRow = () => tableRow.createAndFill(
14
- null,
15
- Array.from({ length: col }, () => tableHeaderCell.createAndFill())
16
- ), createBodyRow = () => tableRow.createAndFill(
17
- null,
18
- Array.from({ length: col }, () => tableCell.createAndFill())
19
- ), rows = [
13
+ const table = getNodeType(schema, "table");
14
+ const tableRow = getNodeType(schema, "tableRow");
15
+ const tableCell = getNodeType(schema, "tableCell");
16
+ const tableHeaderCell = getNodeType(schema, "tableHeaderCell");
17
+ const createHeaderRow = () => {
18
+ return tableRow.createAndFill(
19
+ null,
20
+ Array.from({ length: col }, () => tableHeaderCell.createAndFill())
21
+ );
22
+ };
23
+ const createBodyRow = () => {
24
+ return tableRow.createAndFill(
25
+ null,
26
+ Array.from({ length: col }, () => tableCell.createAndFill())
27
+ );
28
+ };
29
+ const rows = [
20
30
  ...Array.from({ length: header ? 1 : 0 }, createHeaderRow),
21
31
  ...Array.from({ length: header ? row - 1 : row }, createBodyRow)
22
32
  ];
@@ -28,27 +38,41 @@ function insertTable({
28
38
  header
29
39
  }) {
30
40
  return (state, dispatch, view) => {
31
- let table = createEmptyTable(state.schema, row, col, header);
41
+ const table = createEmptyTable(state.schema, row, col, header);
32
42
  return insertNode({ node: table })(state, dispatch, view);
33
43
  };
34
44
  }
35
45
  var exitTable = (state, dispatch) => {
36
- let { $head, $anchor } = state.selection;
37
- if (!$head.sameParent($anchor))
38
- return !1;
39
- let tableStart = -1, tableDepth = -1;
40
- for (let depth = $head.depth; depth >= 0; depth--)
41
- $head.node(depth).type.spec.tableRole === "table" && (tableStart = $head.before(depth), tableDepth = depth);
42
- if (tableStart < 0 || tableDepth <= 0)
43
- return !1;
44
- let above = $head.node(tableDepth - 1), after = $head.indexAfter(tableDepth - 1), type = defaultBlockAt(above.contentMatchAt(after)), node = type == null ? void 0 : type.createAndFill();
45
- if (!type || !node || !above.canReplaceWith(after, after, type))
46
- return !1;
46
+ const { $head, $anchor } = state.selection;
47
+ if (!$head.sameParent($anchor)) {
48
+ return false;
49
+ }
50
+ let tableStart = -1;
51
+ let tableDepth = -1;
52
+ for (let depth = $head.depth; depth >= 0; depth--) {
53
+ const node2 = $head.node(depth);
54
+ if (node2.type.spec.tableRole === "table") {
55
+ tableStart = $head.before(depth);
56
+ tableDepth = depth;
57
+ }
58
+ }
59
+ if (tableStart < 0 || tableDepth <= 0) {
60
+ return false;
61
+ }
62
+ const above = $head.node(tableDepth - 1);
63
+ const after = $head.indexAfter(tableDepth - 1);
64
+ const type = defaultBlockAt(above.contentMatchAt(after));
65
+ const node = type == null ? void 0 : type.createAndFill();
66
+ if (!type || !node || !above.canReplaceWith(after, after, type)) {
67
+ return false;
68
+ }
47
69
  if (dispatch) {
48
- let pos = $head.after(tableDepth), tr = state.tr.replaceWith(pos, pos, node);
49
- tr.setSelection(TextSelection.near(tr.doc.resolve(pos), 1)), dispatch(tr.scrollIntoView());
70
+ const pos = $head.after(tableDepth);
71
+ const tr = state.tr.replaceWith(pos, pos, node);
72
+ tr.setSelection(TextSelection.near(tr.doc.resolve(pos), 1));
73
+ dispatch(tr.scrollIntoView());
50
74
  }
51
- return !0;
75
+ return true;
52
76
  };
53
77
  function defineTableCommands() {
54
78
  return defineCommands({
@@ -66,16 +90,19 @@ function defineTablePlugins() {
66
90
 
67
91
  // src/table/table-spec.ts
68
92
  import { defineNodeSpec } from "@prosekit/core";
69
- import "prosemirror-tables";
70
93
  var cellAttrs = {
71
94
  colspan: { default: 1 },
72
95
  rowspan: { default: 1 },
73
96
  colwidth: { default: null }
74
- }, cellContent = "block+";
97
+ };
98
+ var cellContent = "block+";
75
99
  function getCellAttrs(dom) {
76
- if (typeof dom == "string")
100
+ if (typeof dom === "string") {
77
101
  return {};
78
- let widthAttr = dom.getAttribute("data-colwidth"), widths = widthAttr && /^\d+(,\d+)*$/.test(widthAttr) ? widthAttr.split(",").map((s) => Number(s)) : null, colspan = Number(dom.getAttribute("colspan") || 1);
102
+ }
103
+ const widthAttr = dom.getAttribute("data-colwidth");
104
+ const widths = widthAttr && /^\d+(,\d+)*$/.test(widthAttr) ? widthAttr.split(",").map((s) => Number(s)) : null;
105
+ const colspan = Number(dom.getAttribute("colspan") || 1);
79
106
  return {
80
107
  colspan,
81
108
  rowspan: Number(dom.getAttribute("rowspan") || 1),
@@ -83,15 +110,25 @@ function getCellAttrs(dom) {
83
110
  };
84
111
  }
85
112
  function setCellAttrs(node) {
86
- let pmAttrs = node.attrs, domAttrs = {};
87
- return pmAttrs.colspan !== 1 && (domAttrs.colspan = pmAttrs.colspan), pmAttrs.rowspan !== 1 && (domAttrs.rowspan = pmAttrs.rowspan), pmAttrs.colwidth && (domAttrs["data-colwidth"] = pmAttrs.colwidth.join(",")), domAttrs;
113
+ const pmAttrs = node.attrs;
114
+ const domAttrs = {};
115
+ if (pmAttrs.colspan !== 1) {
116
+ domAttrs.colspan = pmAttrs.colspan;
117
+ }
118
+ if (pmAttrs.rowspan !== 1) {
119
+ domAttrs.rowspan = pmAttrs.rowspan;
120
+ }
121
+ if (pmAttrs.colwidth) {
122
+ domAttrs["data-colwidth"] = pmAttrs.colwidth.join(",");
123
+ }
124
+ return domAttrs;
88
125
  }
89
126
  function defineTableSpec() {
90
127
  return defineNodeSpec({
91
128
  name: "table",
92
129
  tableRole: "table",
93
130
  content: "tableRow+",
94
- isolating: !0,
131
+ isolating: true,
95
132
  group: "block",
96
133
  parseDOM: [{ tag: "table" }],
97
134
  toDOM() {
@@ -116,7 +153,7 @@ function defineTableCellSpec() {
116
153
  tableRole: "cell",
117
154
  content: cellContent,
118
155
  attrs: cellAttrs,
119
- isolating: !0,
156
+ isolating: true,
120
157
  parseDOM: [{ tag: "td", getAttrs: (dom) => getCellAttrs(dom) }],
121
158
  toDOM(node) {
122
159
  return ["td", setCellAttrs(node), 0];
@@ -129,7 +166,7 @@ function defineTableHeaderCellSpec() {
129
166
  tableRole: "header_cell",
130
167
  content: cellContent,
131
168
  attrs: cellAttrs,
132
- isolating: !0,
169
+ isolating: true,
133
170
  parseDOM: [{ tag: "th", getAttrs: (dom) => getCellAttrs(dom) }],
134
171
  toDOM(node) {
135
172
  return ["th", setCellAttrs(node), 0];
@@ -3,3 +3,4 @@ export { defineTextAlignCommands } from './_tsup-dts-rollup';
3
3
  export { defineTextAlignKeymap } from './_tsup-dts-rollup';
4
4
  export { defineTextAlign } from './_tsup-dts-rollup';
5
5
  export { TextAlignOptions } from './_tsup-dts-rollup';
6
+ export { TextAlignCommandTyping } from './_tsup-dts-rollup';
@@ -11,9 +11,11 @@ function defineTextAlignAttr(type, defaultValue) {
11
11
  type,
12
12
  attr: "textAlign",
13
13
  default: defaultValue,
14
- splittable: !0,
14
+ splittable: true,
15
15
  toDOM: (value) => value ? ["style", `text-align:${value};`] : null,
16
- parseDOM: (node) => node.style.getPropertyValue("text-align") || null
16
+ parseDOM: (node) => {
17
+ return node.style.getPropertyValue("text-align") || null;
18
+ }
17
19
  });
18
20
  }
19
21
  function defineTextAlignAttrs(types, defaultValue) {
@@ -21,7 +21,7 @@ function getFocusState(state) {
21
21
  var virtualSelectionPlugin = new ProseMirrorPlugin({
22
22
  key,
23
23
  state: {
24
- init: () => !1,
24
+ init: () => false,
25
25
  apply: (tr, value) => {
26
26
  var _a;
27
27
  return (_a = getFocusMeta(tr)) != null ? _a : value;
@@ -30,16 +30,21 @@ var virtualSelectionPlugin = new ProseMirrorPlugin({
30
30
  props: {
31
31
  handleDOMEvents: {
32
32
  focus: (view) => {
33
- view.dispatch(setFocusMeta(view.state.tr, !1));
33
+ view.dispatch(setFocusMeta(view.state.tr, false));
34
34
  },
35
35
  blur: (view) => {
36
- let { dom, root } = view;
37
- root.activeElement !== dom && view.dispatch(setFocusMeta(view.state.tr, !0));
36
+ const { dom, root } = view;
37
+ const activeElement = root.activeElement;
38
+ if (activeElement === dom) return;
39
+ view.dispatch(setFocusMeta(view.state.tr, true));
38
40
  }
39
41
  },
40
42
  decorations: (state) => {
41
- let { selection, doc } = state;
42
- return selection.empty || !getFocusState(state) ? null : DecorationSet.create(doc, [
43
+ const { selection, doc } = state;
44
+ if (selection.empty || !getFocusState(state)) {
45
+ return null;
46
+ }
47
+ return DecorationSet.create(doc, [
43
48
  Decoration.inline(selection.from, selection.to, {
44
49
  class: "prosekit-virtual-selection"
45
50
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/extensions",
3
3
  "type": "module",
4
- "version": "0.7.2",
4
+ "version": "0.7.4",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -180,19 +180,20 @@
180
180
  "dependencies": {
181
181
  "prosemirror-changeset": "^2.2.1",
182
182
  "prosemirror-dropcursor": "^1.8.1",
183
- "prosemirror-flat-list": "^0.5.2",
183
+ "prosemirror-flat-list": "^0.5.3",
184
184
  "prosemirror-highlight": "^0.8.0",
185
- "prosemirror-search": "^0.1.0",
185
+ "prosemirror-search": "^1.0.0",
186
186
  "prosemirror-tables": "^1.3.7",
187
187
  "shiki": "^1.10.3",
188
- "@prosekit/core": "^0.7.2",
189
- "@prosekit/pm": "^0.1.5"
188
+ "@prosekit/core": "^0.7.4",
189
+ "@prosekit/pm": "^0.1.6"
190
190
  },
191
191
  "devDependencies": {
192
- "@vitest/browser": "^2.0.2",
193
- "tsup": "^8.1.0",
192
+ "@vitest/browser": "^2.0.3",
193
+ "tsup": "^8.1.2",
194
+ "type-fest": "^4.22.1",
194
195
  "typescript": "^5.5.3",
195
- "vitest": "^2.0.2",
196
+ "vitest": "^2.0.3",
196
197
  "@prosekit/dev": "0.0.0"
197
198
  },
198
199
  "scripts": {
@@ -1,140 +0,0 @@
1
- // src/mark-rule/extension.ts
2
- import {
3
- defineFacet,
4
- defineFacetPayload,
5
- pluginFacet
6
- } from "@prosekit/core";
7
- import {
8
- PluginKey,
9
- ProseMirrorPlugin
10
- } from "@prosekit/pm/state";
11
-
12
- // src/mark-rule/apply.ts
13
- import {
14
- OBJECT_REPLACEMENT_CHARACTER,
15
- getMarkType,
16
- maybeRun
17
- } from "@prosekit/core";
18
- import "@prosekit/pm/model";
19
- import "@prosekit/pm/state";
20
-
21
- // src/mark-rule/range.ts
22
- import "@prosekit/pm/state";
23
- function getSpanTextRanges($from, $to) {
24
- let nodeRange = $from.blockRange($to);
25
- if (!nodeRange)
26
- return [];
27
- let stack = [], start = nodeRange.start;
28
- for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) {
29
- let child = nodeRange.parent.child(i);
30
- stack.push([start, child]), start += child.nodeSize;
31
- }
32
- let ranges = [];
33
- for (; stack.length > 0; ) {
34
- let [start2, node] = stack.pop();
35
- if (!node.type.spec.code) {
36
- if (node.type.isTextblock) {
37
- ranges.push([start2 + 1, start2 + 1 + node.content.size]);
38
- continue;
39
- }
40
- node.forEach((child, offset) => {
41
- stack.push([start2 + offset + 1, child]);
42
- });
43
- }
44
- }
45
- return ranges;
46
- }
47
- function getInlineTextRange($from, $to) {
48
- return [$from.start(), $to.end()];
49
- }
50
- function getTextRanges(doc, from, to) {
51
- let $from = doc.resolve(from), $to = doc.resolve(to);
52
- return $from.sameParent($to) && $from.parent.isTextblock ? [getInlineTextRange($from, $to)] : $from.blockRange($to) ? getSpanTextRanges($from, $to) : [];
53
- }
54
- function getMapRange(transactions, oldState, newState) {
55
- let lo = oldState.selection.from, hi = oldState.selection.to;
56
- for (let tr of transactions)
57
- for (let map of tr.mapping.maps)
58
- lo = map.map(lo), hi = map.map(hi), map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
59
- lo = Math.min(lo, hi, newStart), hi = Math.max(lo, hi, newEnd);
60
- });
61
- return lo = Math.min(lo, hi, newState.selection.from), hi = Math.min(lo, hi, newState.selection.to), [lo, hi];
62
- }
63
- function getCheckRanges(transactions, oldState, newState) {
64
- let [from, to] = getMapRange(transactions, oldState, newState);
65
- return getTextRanges(newState.doc, from, to);
66
- }
67
-
68
- // src/mark-rule/apply.ts
69
- function getExpectedMarkings(rules, doc, from, to) {
70
- let text = doc.textBetween(from, to, null, OBJECT_REPLACEMENT_CHARACTER), ranges = [];
71
- for (let rule of rules) {
72
- rule.regex.lastIndex = 0;
73
- let matches = text.matchAll(rule.regex), markType = getMarkType(doc.type.schema, rule.type);
74
- for (let match of matches) {
75
- let index = match.index;
76
- if (index == null) continue;
77
- let attrs = maybeRun(rule.attrs, match), mark = markType.create(attrs);
78
- ranges.push([from + index, from + index + match[0].length, mark]);
79
- }
80
- }
81
- ranges.sort((a, b) => a[0] - b[0] || b[1] - a[1]);
82
- let result = [], freeIndex = 0;
83
- for (let range of ranges)
84
- range[0] >= freeIndex && (result.push(range), freeIndex = range[1]);
85
- return result;
86
- }
87
- function getReceivedMarkings(rules, doc, from, to) {
88
- let result = [], schema = doc.type.schema, markTypes = rules.map((rule) => getMarkType(schema, rule.type));
89
- return doc.nodesBetween(from, to, (node, pos) => {
90
- if (node.isInline)
91
- for (let markType of markTypes) {
92
- let mark = node.marks.find((mark2) => mark2.type === markType);
93
- mark && result.push([pos, pos + node.nodeSize, mark]);
94
- }
95
- }), result;
96
- }
97
- function markRangeEquals(a, b) {
98
- return a[0] === b[0] && a[1] === b[1] && a[2].eq(b[2]);
99
- }
100
- function markRangeDiffs(a, b) {
101
- return a.filter((x) => !b.some((y) => markRangeEquals(x, y)));
102
- }
103
- function applyMarkRules(rules, transactions, oldState, newState) {
104
- if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged))
105
- return null;
106
- let ranges = getCheckRanges(transactions, oldState, newState), toRemove = [], toCreate = [];
107
- for (let [from, to] of ranges) {
108
- let expected = getExpectedMarkings(rules, newState.doc, from, to), received = getReceivedMarkings(rules, newState.doc, from, to);
109
- toRemove.push(...markRangeDiffs(received, expected)), toCreate.push(...markRangeDiffs(expected, received));
110
- }
111
- if (toCreate.length === 0 && toRemove.length === 0)
112
- return null;
113
- let tr = newState.tr;
114
- for (let [from, to, mark] of toRemove)
115
- tr.removeMark(from, to, mark);
116
- for (let [from, to, mark] of toCreate)
117
- tr.addMark(from, to, mark);
118
- return tr;
119
- }
120
-
121
- // src/mark-rule/extension.ts
122
- function defineMarkRule(options) {
123
- return defineFacetPayload(markRuleFacet, [options]);
124
- }
125
- var markRuleFacet = defineFacet({
126
- reduce: () => {
127
- let rules = [], plugin = new ProseMirrorPlugin({
128
- key: new PluginKey("prosekit-mark-rule"),
129
- appendTransaction: (transactions, oldState, newState) => applyMarkRules(rules, transactions, oldState, newState)
130
- });
131
- return function(input) {
132
- return rules = input, plugin;
133
- };
134
- },
135
- parent: pluginFacet
136
- });
137
-
138
- export {
139
- defineMarkRule
140
- };