@prosekit/extensions 0.0.0-next-20240427133255 → 0.0.0-next-20240427200701

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.
@@ -24,13 +24,13 @@ import { Parser } from 'prosemirror-highlight';
24
24
  import { Plugin as Plugin_2 } from '@prosekit/pm/state';
25
25
  import { PluginKey } from '@prosekit/pm/state';
26
26
  import { ProseMirrorNode } from '@prosekit/pm/model';
27
- import type { ResolvedPos } from '@prosekit/pm/model';
28
- import type { Selection as Selection_2 } from '@prosekit/pm/state';
29
27
  import type { SpecialLanguage } from 'shiki';
30
28
  import { ToggleCollapsedOptions } from 'prosemirror-flat-list';
31
29
  import { Transaction } from '@prosekit/pm/state';
32
30
  import { UnwrapListOptions } from 'prosemirror-flat-list';
33
31
 
32
+ export declare function applyMarkRules(rules: MarkRule[], transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): Transaction | null;
33
+
34
34
  declare class AutocompleteRule {
35
35
  readonly regex: RegExp;
36
36
  readonly onMatch: MatchHandler;
@@ -471,11 +471,8 @@ export declare function defineListSpec(): Extension<{
471
471
  }>;
472
472
 
473
473
  /**
474
- * A mark rule is something that can automatically apply marks to text if it matches a certain pattern, and remove them if it doesn't match anymore.
475
- *
476
- * For every transaction that changes the document, the mark rule will be applied to the changed text.
477
- *
478
- *
474
+ * A mark rule is something that can automatically apply marks to text if it
475
+ * matches a certain pattern, and remove them if it doesn't match anymore.
479
476
  */
480
477
  export declare function defineMarkRule(options: MarkRuleOptions): Extension<ExtensionTyping<string, string, CommandArgs>>;
481
478
 
@@ -770,20 +767,12 @@ export declare type EnterRuleOptions = {
770
767
  */
771
768
  export declare const exitTable: Command;
772
769
 
773
- /**
774
- * @internal
775
- */
776
- export declare function findChangedTextRanges(selection: Selection_2): Array<[from: number, to: number]>;
777
-
778
- /** @internal */
779
- export declare function getAffectedRange(transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): readonly [number, number];
770
+ export declare function getCheckRanges(transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): Array<[number, number]>;
780
771
 
781
772
  export { getHighlighter }
782
773
 
783
774
  export declare function getPluginState(state: EditorState): PredictionPluginState | undefined;
784
775
 
785
- export declare function getSpanTextRanges($from: ResolvedPos, $to: ResolvedPos): [number, number][];
786
-
787
776
  export declare function getTrMeta(tr: Transaction): PredictionPluginState;
788
777
 
789
778
  export declare interface HeadingAttrs {
@@ -834,9 +823,24 @@ export declare interface LinkAttrs {
834
823
 
835
824
  export { ListDOMSerializer }
836
825
 
837
- export declare interface MarkRuleOptions {
826
+ /**
827
+ * @internal
828
+ */
829
+ export declare class MarkRule {
830
+ readonly regex: RegExp;
831
+ readonly type: string | MarkType;
832
+ readonly getAttrs: (match: RegExpMatchArray) => Attrs | null;
833
+ constructor({ regex, type, attrs }: MarkRuleOptions);
834
+ }
835
+
836
+ /**
837
+ * The options for {@link defineMarkRule}.
838
+ *
839
+ * @public
840
+ */
841
+ declare interface MarkRuleOptions {
838
842
  /**
839
- * The regular expression to match against. It should have a `g` flag to match
843
+ * The regular expression to match against. It must has a `g` flag to match
840
844
  * all instances of the mark.
841
845
  */
842
846
  regex: RegExp;
@@ -847,9 +851,13 @@ export declare interface MarkRuleOptions {
847
851
  /**
848
852
  * Attributes to set on the mark. If a function is provided, it will be called
849
853
  * with the matched result from the regular expression.
854
+ *
855
+ * @default null
850
856
  */
851
857
  attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null);
852
858
  }
859
+ export { MarkRuleOptions }
860
+ export { MarkRuleOptions as MarkRuleOptions_alias_1 }
853
861
 
854
862
  declare type MatchHandler = (options: {
855
863
  state: EditorState;
@@ -1,3 +1,2 @@
1
1
  export { defineMarkRule } from './_tsup-dts-rollup';
2
- export { getAffectedRange } from './_tsup-dts-rollup';
3
2
  export { MarkRuleOptions } from './_tsup-dts-rollup';
@@ -1,15 +1,14 @@
1
1
  // src/mark-rule/index.ts
2
- import {
3
- Facet,
4
- OBJECT_REPLACEMENT_CHARACTER,
5
- getMarkType,
6
- pluginFacet
7
- } from "@prosekit/core";
8
- import "@prosekit/pm/model";
2
+ import { Facet, pluginFacet } from "@prosekit/core";
9
3
  import { ProseMirrorPlugin } from "@prosekit/pm/state";
10
4
 
11
- // src/mark-rule/changed-range.ts
12
- import { isTextSelection } from "@prosekit/core";
5
+ // src/mark-rule/apply.ts
6
+ import { OBJECT_REPLACEMENT_CHARACTER, getMarkType } from "@prosekit/core";
7
+ import "@prosekit/pm/model";
8
+ import "@prosekit/pm/state";
9
+
10
+ // src/mark-rule/range.ts
11
+ import "@prosekit/pm/state";
13
12
  function getSpanTextRanges($from, $to) {
14
13
  const nodeRange = $from.blockRange($to);
15
14
  if (!nodeRange) {
@@ -38,12 +37,23 @@ function getSpanTextRanges($from, $to) {
38
37
  }
39
38
  return ranges;
40
39
  }
41
-
42
- // src/mark-rule/index.ts
43
- function defineMarkRule(options) {
44
- return markRuleFacet.extension([options]);
40
+ function getInlineTextRange($from, $to) {
41
+ return [$from.start(), $to.end()];
42
+ }
43
+ function getTextRanges(doc, from, to) {
44
+ const $from = doc.resolve(from);
45
+ const $to = doc.resolve(to);
46
+ if ($from.sameParent($to) && $from.parent.isTextblock) {
47
+ return [getInlineTextRange($from, $to)];
48
+ } else {
49
+ const nodeRange = $from.blockRange($to);
50
+ if (!nodeRange) {
51
+ return [];
52
+ }
53
+ return getSpanTextRanges($from, $to);
54
+ }
45
55
  }
46
- function getAffectedRange(transactions, oldState, newState) {
56
+ function getMapRange(transactions, oldState, newState) {
47
57
  let lo = oldState.selection.from;
48
58
  let hi = oldState.selection.to;
49
59
  for (const tr of transactions) {
@@ -60,19 +70,12 @@ function getAffectedRange(transactions, oldState, newState) {
60
70
  hi = Math.min(lo, hi, newState.selection.to);
61
71
  return [lo, hi];
62
72
  }
63
- function getCheckRanges(doc, from, to) {
64
- const $from = doc.resolve(from);
65
- const $to = doc.resolve(to);
66
- if ($from.sameParent($to)) {
67
- return [[$from.start(), $to.end()]];
68
- } else {
69
- const nodeRange = $from.blockRange($to);
70
- if (!nodeRange) {
71
- return [];
72
- }
73
- return getSpanTextRanges($from, $to);
74
- }
73
+ function getCheckRanges(transactions, oldState, newState) {
74
+ const [from, to] = getMapRange(transactions, oldState, newState);
75
+ return getTextRanges(newState.doc, from, to);
75
76
  }
77
+
78
+ // src/mark-rule/apply.ts
76
79
  function getExpectedMarkings(rules, doc, from, to) {
77
80
  const text = doc.textBetween(from, to, OBJECT_REPLACEMENT_CHARACTER);
78
81
  const result = [];
@@ -80,14 +83,13 @@ function getExpectedMarkings(rules, doc, from, to) {
80
83
  rule.regex.lastIndex = 0;
81
84
  const matches = text.matchAll(rule.regex);
82
85
  const markType = getMarkType(doc.type.schema, rule.type);
83
- const getAttrs = rule.attrs;
84
86
  for (const match of matches) {
85
87
  const index = match.index;
86
88
  if (index == null)
87
89
  continue;
88
- const attrs = getAttrs ? typeof getAttrs === "function" ? getAttrs(match) : getAttrs : null;
90
+ const attrs = rule.getAttrs(match);
89
91
  const mark = markType.create(attrs);
90
- result.push([from + index, from + index + match[0].length, mark]);
92
+ result.push([mark, from + index, from + index + match[0].length]);
91
93
  }
92
94
  }
93
95
  return result;
@@ -96,25 +98,21 @@ function getReceivedMarkings(rules, doc, from, to) {
96
98
  const result = [];
97
99
  const schema = doc.type.schema;
98
100
  const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
99
- let seen = false;
100
- doc.nodesBetween(from, to, (node) => {
101
- if (!node.isTextblock || seen) {
101
+ doc.nodesBetween(from, to, (node, pos) => {
102
+ if (!node.isInline) {
102
103
  return;
103
104
  }
104
- seen = true;
105
- node.content.forEach((child, offset) => {
106
- for (const markType of markTypes) {
107
- const mark = child.marks.find((mark2) => mark2.type === markType);
108
- if (mark) {
109
- result.push([from + offset, from + offset + child.nodeSize, mark]);
110
- }
105
+ for (const markType of markTypes) {
106
+ const mark = node.marks.find((mark2) => mark2.type === markType);
107
+ if (mark) {
108
+ result.push([mark, pos, pos + node.nodeSize]);
111
109
  }
112
- });
110
+ }
113
111
  });
114
112
  return result;
115
113
  }
116
114
  function markingEquals(a, b) {
117
- return a[0] === b[0] && a[1] === b[1] && a[2].eq(b[2]);
115
+ return a[1] === b[1] && a[2] === b[2] && a[0].eq(b[0]);
118
116
  }
119
117
  function markingDiffs(a, b) {
120
118
  return a.filter((x) => !b.some((y) => markingEquals(x, y)));
@@ -123,13 +121,12 @@ function applyMarkRules(rules, transactions, oldState, newState) {
123
121
  if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) {
124
122
  return null;
125
123
  }
126
- const [from, to] = getAffectedRange(transactions, oldState, newState);
127
- const ranges = getCheckRanges(newState.doc, from, to);
124
+ const ranges = getCheckRanges(transactions, oldState, newState);
128
125
  const toRemove = [];
129
126
  const toCreate = [];
130
- for (const [from2, to2] of ranges) {
131
- const expected = getExpectedMarkings(rules, newState.doc, from2, to2);
132
- const received = getReceivedMarkings(rules, newState.doc, from2, to2);
127
+ for (const [from, to] of ranges) {
128
+ const expected = getExpectedMarkings(rules, newState.doc, from, to);
129
+ const received = getReceivedMarkings(rules, newState.doc, from, to);
133
130
  toRemove.push(...markingDiffs(received, expected));
134
131
  toCreate.push(...markingDiffs(expected, received));
135
132
  }
@@ -137,14 +134,29 @@ function applyMarkRules(rules, transactions, oldState, newState) {
137
134
  return null;
138
135
  }
139
136
  const tr = newState.tr;
140
- for (const [from2, to2, mark] of toRemove) {
141
- tr.removeMark(from2, to2, mark);
137
+ for (const [mark, from, to] of toRemove) {
138
+ tr.removeMark(from, to, mark);
142
139
  }
143
- for (const [from2, to2, mark] of toCreate) {
144
- tr.addMark(from2, to2, mark);
140
+ for (const [mark, from, to] of toCreate) {
141
+ tr.addMark(from, to, mark);
145
142
  }
146
143
  return tr;
147
144
  }
145
+
146
+ // src/mark-rule/rule.ts
147
+ import "@prosekit/pm/model";
148
+ var MarkRule = class {
149
+ constructor({ regex, type, attrs = null }) {
150
+ this.regex = regex;
151
+ this.type = type;
152
+ this.getAttrs = typeof attrs === "function" ? attrs : () => attrs;
153
+ }
154
+ };
155
+
156
+ // src/mark-rule/index.ts
157
+ function defineMarkRule(options) {
158
+ return markRuleFacet.extension([new MarkRule(options)]);
159
+ }
148
160
  var markRuleFacet = Facet.define({
149
161
  converter: () => {
150
162
  let rules = [];
@@ -168,6 +180,5 @@ var markRuleFacet = Facet.define({
168
180
  next: pluginFacet
169
181
  });
170
182
  export {
171
- defineMarkRule,
172
- getAffectedRange
183
+ defineMarkRule
173
184
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/extensions",
3
3
  "type": "module",
4
- "version": "0.0.0-next-20240427133255",
4
+ "version": "0.0.0-next-20240427200701",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -152,8 +152,8 @@
152
152
  "dist"
153
153
  ],
154
154
  "dependencies": {
155
- "@prosekit/core": "0.0.0-next-20240427133255",
156
- "@prosekit/pm": "0.0.0-next-20240427133255",
155
+ "@prosekit/core": "0.0.0-next-20240427200701",
156
+ "@prosekit/pm": "0.0.0-next-20240427200701",
157
157
  "prosemirror-dropcursor": "^1.8.1",
158
158
  "prosemirror-flat-list": "^0.5.0",
159
159
  "prosemirror-highlight": "^0.5.0",