@prosekit/extensions 0.8.0 → 0.9.1

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 (100) hide show
  1. package/dist/commit/style.css +1 -1
  2. package/dist/commit/style.js +0 -0
  3. package/dist/enter-rule-RdhEA900.js +96 -0
  4. package/dist/gap-cursor/style.css +6 -3
  5. package/dist/gap-cursor/style.js +0 -0
  6. package/dist/input-rule-Gji4N7Oe.js +93 -0
  7. package/dist/list/style.css +7 -7
  8. package/dist/list/style.js +0 -0
  9. package/dist/loro/style.css +13 -9
  10. package/dist/loro/style.js +0 -0
  11. package/dist/mark-rule-wEOcDt6i.js +160 -0
  12. package/dist/placeholder/style.css +3 -3
  13. package/dist/placeholder/style.js +0 -0
  14. package/dist/prosekit-extensions-autocomplete.d.ts +33 -3
  15. package/dist/prosekit-extensions-autocomplete.js +126 -174
  16. package/dist/prosekit-extensions-blockquote.d.ts +48 -8
  17. package/dist/prosekit-extensions-blockquote.js +64 -78
  18. package/dist/prosekit-extensions-bold.d.ts +54 -8
  19. package/dist/prosekit-extensions-bold.js +61 -73
  20. package/dist/prosekit-extensions-code-block.d.ts +159 -20
  21. package/dist/prosekit-extensions-code-block.js +201 -184
  22. package/dist/prosekit-extensions-code.d.ts +54 -8
  23. package/dist/prosekit-extensions-code.js +44 -56
  24. package/dist/prosekit-extensions-commit.d.ts +52 -4
  25. package/dist/prosekit-extensions-commit.js +140 -183
  26. package/dist/prosekit-extensions-doc.d.ts +19 -2
  27. package/dist/prosekit-extensions-doc.js +14 -12
  28. package/dist/prosekit-extensions-drop-cursor.d.ts +35 -3
  29. package/dist/prosekit-extensions-drop-cursor.js +14 -8
  30. package/dist/prosekit-extensions-enter-rule.d.ts +105 -5
  31. package/dist/prosekit-extensions-enter-rule.js +3 -8
  32. package/dist/prosekit-extensions-file.d.ts +129 -8
  33. package/dist/prosekit-extensions-file.js +124 -132
  34. package/dist/prosekit-extensions-gap-cursor.d.ts +26 -2
  35. package/dist/prosekit-extensions-gap-cursor.js +21 -9
  36. package/dist/prosekit-extensions-hard-break.d.ts +53 -0
  37. package/dist/prosekit-extensions-hard-break.js +58 -0
  38. package/dist/prosekit-extensions-heading.d.ts +63 -9
  39. package/dist/prosekit-extensions-heading.js +121 -95
  40. package/dist/prosekit-extensions-horizontal-rule.d.ts +38 -8
  41. package/dist/prosekit-extensions-horizontal-rule.js +53 -71
  42. package/dist/prosekit-extensions-image.d.ts +50 -7
  43. package/dist/prosekit-extensions-image.js +71 -62
  44. package/dist/prosekit-extensions-input-rule.d.ts +129 -6
  45. package/dist/prosekit-extensions-input-rule.js +3 -14
  46. package/dist/prosekit-extensions-italic.d.ts +54 -8
  47. package/dist/prosekit-extensions-italic.js +51 -63
  48. package/dist/prosekit-extensions-link.d.ts +62 -10
  49. package/dist/prosekit-extensions-link.js +95 -100
  50. package/dist/prosekit-extensions-list.d.ts +104 -17
  51. package/dist/prosekit-extensions-list.js +115 -158
  52. package/dist/prosekit-extensions-loro.d.ts +69 -11
  53. package/dist/prosekit-extensions-loro.js +49 -77
  54. package/dist/prosekit-extensions-mark-rule.d.ts +37 -2
  55. package/dist/prosekit-extensions-mark-rule.js +3 -6
  56. package/dist/prosekit-extensions-mention.d.ts +39 -4
  57. package/dist/prosekit-extensions-mention.js +52 -50
  58. package/dist/prosekit-extensions-mod-click-prevention.d.ts +17 -2
  59. package/dist/prosekit-extensions-mod-click-prevention.js +20 -16
  60. package/dist/prosekit-extensions-paragraph.d.ts +60 -7
  61. package/dist/prosekit-extensions-paragraph.js +46 -45
  62. package/dist/prosekit-extensions-placeholder.d.ts +33 -2
  63. package/dist/prosekit-extensions-placeholder.js +39 -56
  64. package/dist/prosekit-extensions-readonly.d.ts +10 -1
  65. package/dist/prosekit-extensions-readonly.js +13 -14
  66. package/dist/prosekit-extensions-search.d.ts +74 -3
  67. package/dist/prosekit-extensions-search.js +48 -47
  68. package/dist/prosekit-extensions-strike.d.ts +47 -8
  69. package/dist/prosekit-extensions-strike.js +44 -49
  70. package/dist/prosekit-extensions-table.d.ts +231 -26
  71. package/dist/prosekit-extensions-table.js +3 -34
  72. package/dist/prosekit-extensions-text-align.d.ts +71 -8
  73. package/dist/prosekit-extensions-text-align.js +63 -44
  74. package/dist/prosekit-extensions-text.d.ts +19 -2
  75. package/dist/prosekit-extensions-text.js +13 -11
  76. package/dist/prosekit-extensions-underline.d.ts +43 -7
  77. package/dist/prosekit-extensions-underline.js +33 -37
  78. package/dist/prosekit-extensions-virtual-selection.d.ts +21 -2
  79. package/dist/prosekit-extensions-virtual-selection.js +49 -52
  80. package/dist/prosekit-extensions-yjs.d.ts +90 -14
  81. package/dist/prosekit-extensions-yjs.js +88 -131
  82. package/dist/prosekit-extensions.d.ts +1 -1
  83. package/dist/search/style.css +4 -3
  84. package/dist/search/style.js +0 -0
  85. package/dist/shiki-highlighter-chunk-CZGvZlhf.d.ts +18 -0
  86. package/dist/shiki-highlighter-chunk.d.ts +2 -0
  87. package/dist/shiki-highlighter-chunk.js +32 -39
  88. package/dist/table/style.css +10 -13
  89. package/dist/table/style.js +0 -0
  90. package/dist/table-DnVliJ6E.js +287 -0
  91. package/dist/virtual-selection/style.css +2 -2
  92. package/dist/virtual-selection/style.js +0 -0
  93. package/dist/yjs/style.css +9 -8
  94. package/dist/yjs/style.js +0 -0
  95. package/package.json +81 -54
  96. package/dist/_tsup-dts-rollup.d.ts +0 -2459
  97. package/dist/chunk-6UYLCVBX.js +0 -185
  98. package/dist/chunk-D54VSLLS.js +0 -105
  99. package/dist/chunk-I2UMHK3L.js +0 -99
  100. package/dist/chunk-QVFEYPQ6.js +0 -306
@@ -1,4 +1,3 @@
1
- /* src/commit/style.css */
2
1
  .prosekit-commit-deletion {
3
2
  background-color: #e5534b80;
4
3
  text-decoration: line-through;
@@ -6,3 +5,4 @@
6
5
  .prosekit-commit-addition {
7
6
  background-color: #53e54b80;
8
7
  }
8
+
File without changes
@@ -0,0 +1,96 @@
1
+ import { OBJECT_REPLACEMENT_CHARACTER, defineFacet, defineFacetPayload, getNodeType, isTextSelection, maybeRun, pluginFacet } from "@prosekit/core";
2
+ import { PluginKey, ProseMirrorPlugin } from "@prosekit/pm/state";
3
+ import { keydownHandler } from "@prosekit/pm/keymap";
4
+
5
+ //#region src/enter-rule/index.ts
6
+ /**
7
+ * Defines an enter rule. An enter rule applies when the text directly in front of
8
+ * the cursor matches `regex` and user presses Enter. The `regex` should end
9
+ * with `$`.
10
+ *
11
+ * @param options
12
+ *
13
+ * @public
14
+ */
15
+ function defineEnterRule({ regex, handler, stop = false }) {
16
+ const rule = new EnterRule(regex, handler, stop);
17
+ return defineFacetPayload(enterRule, [rule]);
18
+ }
19
+ /**
20
+ * Defines an enter rule that replaces the matched text with a block node.
21
+ *
22
+ * See also {@link defineEnterRule}.
23
+ *
24
+ * @param options
25
+ *
26
+ * @public
27
+ */
28
+ function defineTextBlockEnterRule({ regex, type, attrs, stop = true }) {
29
+ return defineEnterRule({
30
+ regex,
31
+ handler: ({ state, from, to, match }) => {
32
+ const nodeType = getNodeType(state.schema, type);
33
+ const $start = state.doc.resolve(from);
34
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) return null;
35
+ const nodeAttrs = maybeRun(attrs, match);
36
+ return state.tr.delete(from, to).setBlockType(from, from, nodeType, nodeAttrs);
37
+ },
38
+ stop
39
+ });
40
+ }
41
+ /**
42
+ * @internal
43
+ */
44
+ var EnterRule = class {
45
+ constructor(regex, handler, stop) {
46
+ this.regex = regex;
47
+ this.handler = handler;
48
+ this.stop = stop;
49
+ }
50
+ };
51
+ const enterRule = defineFacet({
52
+ reduce: () => {
53
+ let rules = [];
54
+ const command = (state, dispatch, view) => {
55
+ if (!view) return false;
56
+ return execRules(view, rules, dispatch);
57
+ };
58
+ const handler = keydownHandler({ Enter: command });
59
+ const plugin = new ProseMirrorPlugin({
60
+ key: new PluginKey("prosekit-enter-rule"),
61
+ props: { handleKeyDown: handler }
62
+ });
63
+ return function reducer(inputs) {
64
+ rules = inputs;
65
+ return plugin;
66
+ };
67
+ },
68
+ parent: pluginFacet
69
+ });
70
+ function execRules(view, rules, dispatch) {
71
+ if (view.composing) return false;
72
+ const state = view.state;
73
+ const selection = state.selection;
74
+ if (!isTextSelection(selection)) return false;
75
+ const $cursor = selection.$cursor;
76
+ if (!$cursor || $cursor.parent.type.spec.code) return false;
77
+ const textBefore = $cursor.parent.textBetween(Math.max(0, $cursor.parentOffset - MAX_MATCH), $cursor.parentOffset, null, OBJECT_REPLACEMENT_CHARACTER);
78
+ for (const rule of rules) {
79
+ rule.regex.lastIndex = 0;
80
+ const match = rule.regex.exec(textBefore);
81
+ const tr = match && rule.handler({
82
+ state,
83
+ from: $cursor.pos - match[0].length,
84
+ to: $cursor.pos,
85
+ match
86
+ });
87
+ if (!tr) continue;
88
+ dispatch?.(tr);
89
+ if (rule.stop) return true;
90
+ }
91
+ return false;
92
+ }
93
+ const MAX_MATCH = 200;
94
+
95
+ //#endregion
96
+ export { defineEnterRule, defineTextBlockEnterRule };
@@ -1,23 +1,26 @@
1
- /* src/gap-cursor/style.css */
2
1
  .ProseMirror-gapcursor {
3
2
  display: none;
4
- pointer-events: none;
5
3
  position: relative;
4
+ pointer-events: none;
6
5
  }
6
+
7
7
  .ProseMirror-gapcursor:after {
8
- content: "";
9
8
  display: block;
10
9
  position: absolute;
11
10
  top: -2px;
12
11
  width: 20px;
13
12
  border-top: 1px solid currentColor;
13
+ content: "";
14
14
  animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
15
15
  }
16
+
16
17
  @keyframes ProseMirror-cursor-blink {
17
18
  to {
18
19
  visibility: hidden;
19
20
  }
20
21
  }
22
+
21
23
  .ProseMirror-focused .ProseMirror-gapcursor {
22
24
  display: block;
23
25
  }
26
+
File without changes
@@ -0,0 +1,93 @@
1
+ import { defineFacet, defineFacetPayload, getMarkType, getNodeType, isMarkAbsent, maybeRun, pluginFacet } from "@prosekit/core";
2
+ import { InputRule, inputRules, textblockTypeInputRule, wrappingInputRule } from "@prosekit/pm/inputrules";
3
+
4
+ //#region src/input-rule/index.ts
5
+ /**
6
+ * Defines an input rule extension.
7
+ *
8
+ * @param rule - The ProseMirror input rule to add.
9
+ *
10
+ * @public
11
+ */
12
+ function defineInputRule(rule) {
13
+ return defineInputRuleFacetPayload(() => rule);
14
+ }
15
+ /**
16
+ * @internal
17
+ */
18
+ function createMarkInputRule({ regex, type, attrs = null, inCodeMark = false }) {
19
+ const rule = new InputRule(regex, (state, match, start, end) => {
20
+ const { tr, schema } = state;
21
+ const [fullText, markText] = match;
22
+ if (!markText) return null;
23
+ const markStart = start + fullText.indexOf(markText);
24
+ const markEnd = markStart + markText.length;
25
+ if (!(start <= markStart && markStart < markEnd && markEnd <= end)) return null;
26
+ const markType = getMarkType(schema, type);
27
+ const mark = markType.create(maybeRun(attrs, match));
28
+ if (!isMarkAbsent(tr.doc, markStart, markEnd, markType, attrs)) return null;
29
+ const initialStoredMarks = tr.storedMarks ?? [];
30
+ tr.addMark(markStart, markEnd, mark);
31
+ if (markEnd < end) tr.delete(markEnd, end);
32
+ if (start < markStart) tr.delete(start, markStart);
33
+ tr.setStoredMarks(initialStoredMarks);
34
+ return tr;
35
+ }, { inCodeMark });
36
+ return rule;
37
+ }
38
+ /**
39
+ * Defines an input rule for automatically adding inline marks when a given
40
+ * pattern is typed.
41
+ *
42
+ * @public
43
+ */
44
+ function defineMarkInputRule(options) {
45
+ return defineInputRule(createMarkInputRule(options));
46
+ }
47
+ /**
48
+ * Defines an input rule that changes the type of a textblock when the matched
49
+ * text is typed into it.
50
+ *
51
+ * See also [textblockTypeInputRule](https://prosemirror.net/docs/ref/#inputrules.textblockTypeInputRule)
52
+ *
53
+ * @param options
54
+ *
55
+ * @public
56
+ */
57
+ function defineTextBlockInputRule({ regex, type, attrs }) {
58
+ return defineInputRuleFacetPayload(({ schema }) => {
59
+ const nodeType = getNodeType(schema, type);
60
+ return textblockTypeInputRule(regex, nodeType, attrs);
61
+ });
62
+ }
63
+ /**
64
+ * Defines an input rule for automatically wrapping a textblock when a given
65
+ * string is typed.
66
+ *
67
+ * See also [wrappingInputRule](https://prosemirror.net/docs/ref/#inputrules.wrappingInputRule)
68
+ *
69
+ * @param options
70
+ *
71
+ * @public
72
+ */
73
+ function defineWrappingInputRule({ regex, type, attrs, join }) {
74
+ return defineInputRuleFacetPayload(({ schema }) => {
75
+ const nodeType = getNodeType(schema, type);
76
+ return wrappingInputRule(regex, nodeType, attrs, join);
77
+ });
78
+ }
79
+ function defineInputRuleFacetPayload(input) {
80
+ return defineFacetPayload(inputRuleFacet, [input]);
81
+ }
82
+ const inputRuleFacet = defineFacet({
83
+ reducer: (inputs) => {
84
+ return (context) => {
85
+ const rules = inputs.flatMap((callback) => callback(context));
86
+ return [inputRules({ rules })];
87
+ };
88
+ },
89
+ parent: pluginFacet
90
+ });
91
+
92
+ //#endregion
93
+ export { createMarkInputRule, defineInputRule, defineMarkInputRule, defineTextBlockInputRule, defineWrappingInputRule };
@@ -1,4 +1,4 @@
1
- /* ../../node_modules/.pnpm/prosemirror-flat-list@0.5.4/node_modules/prosemirror-flat-list/dist/style.css */
1
+ /* src/style.css */
2
2
  .prosemirror-flat-list {
3
3
  padding: 0;
4
4
  margin-top: 0;
@@ -25,9 +25,6 @@
25
25
  .prosemirror-flat-list[data-list-kind=bullet] {
26
26
  list-style: disc;
27
27
  }
28
- .prosemirror-flat-list[data-list-kind=ordered] {
29
- counter-increment: prosemirror-flat-list-counter;
30
- }
31
28
  .prosemirror-flat-list[data-list-kind=ordered] > * {
32
29
  contain: style;
33
30
  }
@@ -37,6 +34,9 @@
37
34
  font-variant-numeric: tabular-nums;
38
35
  content: counter(prosemirror-flat-list-counter, decimal) ". ";
39
36
  }
37
+ .prosemirror-flat-list[data-list-kind=ordered] {
38
+ counter-increment: prosemirror-flat-list-counter;
39
+ }
40
40
  .prosemirror-flat-list[data-list-kind=ordered]:first-child,
41
41
  :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered] {
42
42
  counter-reset: prosemirror-flat-list-counter;
@@ -58,8 +58,8 @@
58
58
  width: 1.5em;
59
59
  width: 1lh;
60
60
  }
61
- .prosemirror-flat-list[data-list-kind=task] > .list-marker,
62
- .prosemirror-flat-list[data-list-kind=task] > .list-marker * {
61
+ :is(.prosemirror-flat-list[data-list-kind=task] > .list-marker),
62
+ :is(.prosemirror-flat-list[data-list-kind=task] > .list-marker) * {
63
63
  cursor: pointer;
64
64
  }
65
65
  .prosemirror-flat-list[data-list-kind=toggle] > .list-marker {
@@ -86,4 +86,4 @@
86
86
  display: none;
87
87
  }
88
88
 
89
- /* src/list/style.css */
89
+
File without changes
@@ -1,30 +1,34 @@
1
- /* src/loro/style.css */
2
1
  .ProseMirror-loro-cursor:first-child {
3
2
  margin-top: 16px;
4
3
  }
4
+
5
+ /* This gives the remote user caret. The colors are automatically overwritten */
5
6
  .ProseMirror-loro-cursor {
6
7
  position: relative;
7
- margin-left: -1px;
8
8
  margin-right: -1px;
9
- border-left: 1px solid black;
9
+ margin-left: -1px;
10
10
  border-right: 1px solid black;
11
+ border-left: 1px solid black;
11
12
  border-color: orange;
12
13
  word-break: normal;
13
14
  pointer-events: none;
14
15
  }
16
+
17
+ /* This renders the username above the caret */
15
18
  .ProseMirror-loro-cursor > div {
16
19
  position: absolute;
17
20
  top: -1.05em;
18
21
  left: -1px;
19
- font-size: 13px;
22
+ padding-right: 2px;
23
+ padding-left: 2px;
20
24
  background-color: rgb(250, 129, 0);
21
- font-family: serif;
25
+ color: white;
22
26
  font-style: normal;
23
27
  font-weight: normal;
28
+ font-size: 13px;
24
29
  line-height: normal;
25
- user-select: none;
26
- color: white;
27
- padding-left: 2px;
28
- padding-right: 2px;
30
+ font-family: serif;
29
31
  white-space: nowrap;
32
+ user-select: none;
30
33
  }
34
+
File without changes
@@ -0,0 +1,160 @@
1
+ import { OBJECT_REPLACEMENT_CHARACTER, defineFacet, defineFacetPayload, getMarkType, maybeRun, pluginFacet } from "@prosekit/core";
2
+ import { PluginKey, ProseMirrorPlugin } from "@prosekit/pm/state";
3
+
4
+ //#region src/mark-rule/range.ts
5
+ function getSpanTextRanges($from, $to) {
6
+ const nodeRange = $from.blockRange($to);
7
+ if (!nodeRange) return [];
8
+ const stack = [];
9
+ let start = nodeRange.start;
10
+ for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) {
11
+ const child = nodeRange.parent.child(i);
12
+ stack.push([start, child]);
13
+ start += child.nodeSize;
14
+ }
15
+ const ranges = [];
16
+ while (stack.length > 0) {
17
+ const [start$1, node] = stack.pop();
18
+ if (node.type.spec.code) continue;
19
+ if (node.type.isTextblock) {
20
+ ranges.push([start$1 + 1, start$1 + 1 + node.content.size]);
21
+ continue;
22
+ }
23
+ node.forEach((child, offset) => {
24
+ stack.push([start$1 + offset + 1, child]);
25
+ });
26
+ }
27
+ return ranges;
28
+ }
29
+ function getInlineTextRange($from, $to) {
30
+ return [$from.start(), $to.end()];
31
+ }
32
+ function getTextRanges(doc, from, to) {
33
+ const $from = doc.resolve(from);
34
+ const $to = doc.resolve(to);
35
+ if ($from.sameParent($to) && $from.parent.isTextblock) return [getInlineTextRange($from, $to)];
36
+ else {
37
+ const nodeRange = $from.blockRange($to);
38
+ if (!nodeRange) return [];
39
+ return getSpanTextRanges($from, $to);
40
+ }
41
+ }
42
+ function getMapRange(transactions, oldState, newState) {
43
+ let lo = oldState.selection.from;
44
+ let hi = oldState.selection.to;
45
+ for (const tr of transactions) for (const map of tr.mapping.maps) {
46
+ lo = map.map(lo);
47
+ hi = map.map(hi);
48
+ map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
49
+ lo = Math.min(lo, hi, newStart);
50
+ hi = Math.max(lo, hi, newEnd);
51
+ });
52
+ }
53
+ lo = Math.min(lo, hi, newState.selection.from);
54
+ hi = Math.min(lo, hi, newState.selection.to);
55
+ return [lo, hi];
56
+ }
57
+ function getCheckRanges(transactions, oldState, newState) {
58
+ const [from, to] = getMapRange(transactions, oldState, newState);
59
+ return getTextRanges(newState.doc, from, to);
60
+ }
61
+
62
+ //#endregion
63
+ //#region src/mark-rule/apply.ts
64
+ function getExpectedMarkings(rules, doc, from, to) {
65
+ const text = doc.textBetween(from, to, null, OBJECT_REPLACEMENT_CHARACTER);
66
+ const ranges = [];
67
+ for (const rule of rules) {
68
+ rule.regex.lastIndex = 0;
69
+ const matches = text.matchAll(rule.regex);
70
+ const markType = getMarkType(doc.type.schema, rule.type);
71
+ for (const match of matches) {
72
+ const index = match.index;
73
+ if (index == null) continue;
74
+ const attrs = maybeRun(rule.attrs, match);
75
+ const mark = markType.create(attrs);
76
+ ranges.push([
77
+ from + index,
78
+ from + index + match[0].length,
79
+ mark
80
+ ]);
81
+ }
82
+ }
83
+ ranges.sort((a, b) => a[0] - b[0] || b[1] - a[1]);
84
+ const result = [];
85
+ let freeIndex = 0;
86
+ for (const range of ranges) if (range[0] >= freeIndex) {
87
+ result.push(range);
88
+ freeIndex = range[1];
89
+ }
90
+ return result;
91
+ }
92
+ function getReceivedMarkings(rules, doc, from, to) {
93
+ const result = [];
94
+ const schema = doc.type.schema;
95
+ const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
96
+ doc.nodesBetween(from, to, (node, pos) => {
97
+ if (!node.isInline) return;
98
+ for (const markType of markTypes) {
99
+ const mark = node.marks.find((mark$1) => mark$1.type === markType);
100
+ if (mark) result.push([
101
+ pos,
102
+ pos + node.nodeSize,
103
+ mark
104
+ ]);
105
+ }
106
+ });
107
+ return result;
108
+ }
109
+ function markRangeEquals(a, b) {
110
+ return a[0] === b[0] && a[1] === b[1] && a[2].eq(b[2]);
111
+ }
112
+ function markRangeDiffs(a, b) {
113
+ return a.filter((x) => !b.some((y) => markRangeEquals(x, y)));
114
+ }
115
+ function applyMarkRules(rules, transactions, oldState, newState) {
116
+ if (transactions.length === 0 || transactions.every((tr$1) => !tr$1.docChanged)) return null;
117
+ const ranges = getCheckRanges(transactions, oldState, newState);
118
+ const toRemove = [];
119
+ const toCreate = [];
120
+ for (const [from, to] of ranges) {
121
+ const expected = getExpectedMarkings(rules, newState.doc, from, to);
122
+ const received = getReceivedMarkings(rules, newState.doc, from, to);
123
+ toRemove.push(...markRangeDiffs(received, expected));
124
+ toCreate.push(...markRangeDiffs(expected, received));
125
+ }
126
+ if (toCreate.length === 0 && toRemove.length === 0) return null;
127
+ const tr = newState.tr;
128
+ for (const [from, to, mark] of toRemove) tr.removeMark(from, to, mark);
129
+ for (const [from, to, mark] of toCreate) tr.addMark(from, to, mark);
130
+ return tr;
131
+ }
132
+
133
+ //#endregion
134
+ //#region src/mark-rule/mark-rule.ts
135
+ /**
136
+ * A mark rule is something that can automatically apply marks to text if it
137
+ * matches a certain pattern, and remove them if it doesn't match anymore.
138
+ */
139
+ function defineMarkRule(options) {
140
+ return defineFacetPayload(markRuleFacet, [options]);
141
+ }
142
+ const markRuleFacet = defineFacet({
143
+ reduce: () => {
144
+ let rules = [];
145
+ const plugin = new ProseMirrorPlugin({
146
+ key: new PluginKey("prosekit-mark-rule"),
147
+ appendTransaction: (transactions, oldState, newState) => {
148
+ return applyMarkRules(rules, transactions, oldState, newState);
149
+ }
150
+ });
151
+ return function reducer(input) {
152
+ rules = input;
153
+ return plugin;
154
+ };
155
+ },
156
+ parent: pluginFacet
157
+ });
158
+
159
+ //#endregion
160
+ export { defineMarkRule };
@@ -1,8 +1,8 @@
1
- /* src/placeholder/style.css */
2
1
  .prosekit-placeholder::before {
3
2
  position: absolute;
4
- opacity: 30%;
5
- pointer-events: none;
6
3
  height: 0;
7
4
  content: attr(data-placeholder);
5
+ opacity: 30%;
6
+ pointer-events: none;
8
7
  }
8
+
File without changes
@@ -1,3 +1,33 @@
1
- export { defineAutocomplete_alias_1 as defineAutocomplete } from './_tsup-dts-rollup.js';
2
- export { AutocompleteRule_alias_1 as AutocompleteRule } from './_tsup-dts-rollup.js';
3
- export { MatchHandler_alias_1 as MatchHandler } from './_tsup-dts-rollup.js';
1
+ import { Extension } from "@prosekit/core";
2
+ import { EditorState } from "@prosekit/pm/state";
3
+
4
+ //#region src/autocomplete/autocomplete-rule.d.ts
5
+ type MatchHandler = (options: {
6
+ state: EditorState;
7
+ match: RegExpExecArray;
8
+ from: number;
9
+ to: number;
10
+ ignoreMatch: () => void;
11
+ deleteMatch: () => void;
12
+ }) => void;
13
+ declare class AutocompleteRule {
14
+ readonly regex: RegExp;
15
+ readonly onMatch: MatchHandler;
16
+ readonly onLeave?: VoidFunction;
17
+ readonly canMatch: (options: {
18
+ state: EditorState;
19
+ }) => boolean;
20
+ constructor(options: {
21
+ regex: RegExp;
22
+ onEnter: MatchHandler;
23
+ onLeave?: VoidFunction;
24
+ canMatch?: (options: {
25
+ state: EditorState;
26
+ }) => boolean;
27
+ });
28
+ }
29
+ //#endregion
30
+ //#region src/autocomplete/autocomplete.d.ts
31
+ declare function defineAutocomplete(rule: AutocompleteRule): Extension;
32
+ //#endregion
33
+ export { AutocompleteRule, MatchHandler, defineAutocomplete };