@prosekit/extensions 0.4.2 → 0.4.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.
@@ -16,6 +16,7 @@ import { IndentListOptions } from 'prosemirror-flat-list';
16
16
  import { InputRule } from '@prosekit/pm/inputrules';
17
17
  import { ListAttributes } from 'prosemirror-flat-list';
18
18
  import { ListDOMSerializer } from 'prosemirror-flat-list';
19
+ import { MarkType } from '@prosekit/pm/model';
19
20
  import { NodeRange } from 'prosemirror-model';
20
21
  import { NodeType } from '@prosekit/pm/model';
21
22
  import { Options } from 'tsup';
@@ -28,6 +29,8 @@ import { ToggleCollapsedOptions } from 'prosemirror-flat-list';
28
29
  import { Transaction } from '@prosekit/pm/state';
29
30
  import { UnwrapListOptions } from 'prosemirror-flat-list';
30
31
 
32
+ export declare function applyMarkRules(rules: MarkRule[], transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): Transaction | null;
33
+
31
34
  declare class AutocompleteRule {
32
35
  readonly regex: RegExp;
33
36
  readonly onMatch: MatchHandler;
@@ -412,10 +415,21 @@ expandLink: [];
412
415
  };
413
416
  }>;
414
417
 
418
+ /**
419
+ * Apply link marks after typing Enter.
420
+ */
415
421
  export declare function defineLinkEnterRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
416
422
 
423
+ /**
424
+ * Apply link marks after pressing Space.
425
+ */
417
426
  export declare function defineLinkInputRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
418
427
 
428
+ /**
429
+ * Apply and remove link marks to the text during typing.
430
+ */
431
+ export declare function defineLinkMarkRule(): Extension<ExtensionTyping<string, string, CommandArgs>>;
432
+
419
433
  export declare function defineLinkSpec(): Extension< {
420
434
  MARKS: "link";
421
435
  }>;
@@ -467,6 +481,14 @@ export declare function defineListSpec(): Extension<{
467
481
  NODES: "list";
468
482
  }>;
469
483
 
484
+ /**
485
+ * A mark rule is something that can automatically apply marks to text if it
486
+ * matches a certain pattern, and remove them if it doesn't match anymore.
487
+ */
488
+ declare function defineMarkRule(options: MarkRuleOptions): Extension<ExtensionTyping<string, string, CommandArgs>>;
489
+ export { defineMarkRule }
490
+ export { defineMarkRule as defineMarkRule_alias_1 }
491
+
470
492
  /**
471
493
  * @public
472
494
  */
@@ -758,6 +780,8 @@ export declare type EnterRuleOptions = {
758
780
  */
759
781
  export declare const exitTable: Command;
760
782
 
783
+ export declare function getCheckRanges(transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): Array<[number, number]>;
784
+
761
785
  export { getHighlighter }
762
786
 
763
787
  export declare function getPluginState(state: EditorState): PredictionPluginState | undefined;
@@ -799,9 +823,11 @@ export declare function insertTable({ row, col, header, }: {
799
823
  header: boolean;
800
824
  }): Command;
801
825
 
802
- export declare const LINK_RE: RegExp;
826
+ export declare const LINK_ENTER_RE: RegExp;
803
827
 
804
- export declare const LINK_SPACE_RE: RegExp;
828
+ export declare const LINK_INPUT_RE: RegExp;
829
+
830
+ export declare const LINK_MARK_RE: RegExp;
805
831
 
806
832
  /**
807
833
  * @public
@@ -812,6 +838,41 @@ export declare interface LinkAttrs {
812
838
 
813
839
  export { ListDOMSerializer }
814
840
 
841
+ /**
842
+ * @internal
843
+ */
844
+ export declare interface MarkRule {
845
+ regex: RegExp;
846
+ type: string | MarkType;
847
+ getAttrs?: ((match: RegExpMatchArray) => Attrs | null) | null;
848
+ }
849
+
850
+ /**
851
+ * The options for {@link defineMarkRule}.
852
+ *
853
+ * @public
854
+ */
855
+ declare interface MarkRuleOptions {
856
+ /**
857
+ * The regular expression to match against. It must has a `g` flag to match
858
+ * all instances of the mark.
859
+ */
860
+ regex: RegExp;
861
+ /**
862
+ * The mark type to apply to the matched text.
863
+ */
864
+ type: string | MarkType;
865
+ /**
866
+ * Attributes to set on the mark. If a function is provided, it will be called
867
+ * with the matched result from the regular expression.
868
+ *
869
+ * @default null
870
+ */
871
+ attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null);
872
+ }
873
+ export { MarkRuleOptions }
874
+ export { MarkRuleOptions as MarkRuleOptions_alias_1 }
875
+
815
876
  declare type MatchHandler = (options: {
816
877
  state: EditorState;
817
878
  match: RegExpExecArray;
@@ -0,0 +1,187 @@
1
+ // src/mark-rule/extension.ts
2
+ import { Facet, pluginFacet } from "@prosekit/core";
3
+ import { ProseMirrorPlugin } from "@prosekit/pm/state";
4
+
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";
12
+ function getSpanTextRanges($from, $to) {
13
+ const nodeRange = $from.blockRange($to);
14
+ if (!nodeRange) {
15
+ return [];
16
+ }
17
+ const stack = [];
18
+ let start = nodeRange.start;
19
+ for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) {
20
+ const child = nodeRange.parent.child(i);
21
+ stack.push([start, child]);
22
+ start += child.nodeSize;
23
+ }
24
+ const ranges = [];
25
+ while (stack.length > 0) {
26
+ const [start2, node] = stack.pop();
27
+ if (node.type.spec.code) {
28
+ continue;
29
+ }
30
+ if (node.type.isTextblock) {
31
+ ranges.push([start2 + 1, start2 + 1 + node.content.size]);
32
+ continue;
33
+ }
34
+ node.forEach((child, offset) => {
35
+ stack.push([start2 + offset + 1, child]);
36
+ });
37
+ }
38
+ return ranges;
39
+ }
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
+ }
55
+ }
56
+ function getMapRange(transactions, oldState, newState) {
57
+ let lo = oldState.selection.from;
58
+ let hi = oldState.selection.to;
59
+ for (const tr of transactions) {
60
+ for (const map of tr.mapping.maps) {
61
+ lo = map.map(lo);
62
+ hi = map.map(hi);
63
+ map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
64
+ lo = Math.min(lo, hi, newStart);
65
+ hi = Math.max(lo, hi, newEnd);
66
+ });
67
+ }
68
+ }
69
+ lo = Math.min(lo, hi, newState.selection.from);
70
+ hi = Math.min(lo, hi, newState.selection.to);
71
+ return [lo, hi];
72
+ }
73
+ function getCheckRanges(transactions, oldState, newState) {
74
+ const [from, to] = getMapRange(transactions, oldState, newState);
75
+ return getTextRanges(newState.doc, from, to);
76
+ }
77
+
78
+ // src/mark-rule/apply.ts
79
+ function getExpectedMarkings(rules, doc, from, to) {
80
+ var _a;
81
+ const text = doc.textBetween(from, to, OBJECT_REPLACEMENT_CHARACTER);
82
+ const ranges = [];
83
+ for (const rule of rules) {
84
+ rule.regex.lastIndex = 0;
85
+ const matches = text.matchAll(rule.regex);
86
+ const markType = getMarkType(doc.type.schema, rule.type);
87
+ for (const match of matches) {
88
+ const index = match.index;
89
+ if (index == null)
90
+ continue;
91
+ const attrs = (_a = rule.getAttrs) == null ? void 0 : _a.call(rule, match);
92
+ const mark = markType.create(attrs);
93
+ ranges.push([from + index, from + index + match[0].length, mark]);
94
+ }
95
+ }
96
+ ranges.sort((a, b) => a[0] - b[0] || b[1] - a[1]);
97
+ const result = [];
98
+ let freeIndex = 0;
99
+ for (const range of ranges) {
100
+ if (range[0] >= freeIndex) {
101
+ result.push(range);
102
+ freeIndex = range[1];
103
+ }
104
+ }
105
+ return result;
106
+ }
107
+ function getReceivedMarkings(rules, doc, from, to) {
108
+ const result = [];
109
+ const schema = doc.type.schema;
110
+ const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
111
+ doc.nodesBetween(from, to, (node, pos) => {
112
+ if (!node.isInline) {
113
+ return;
114
+ }
115
+ for (const markType of markTypes) {
116
+ const mark = node.marks.find((mark2) => mark2.type === markType);
117
+ if (mark) {
118
+ result.push([pos, pos + node.nodeSize, mark]);
119
+ }
120
+ }
121
+ });
122
+ return result;
123
+ }
124
+ function markRangeEquals(a, b) {
125
+ return a[0] === b[0] && a[1] === b[1] && a[2].eq(b[2]);
126
+ }
127
+ function markRangeDiffs(a, b) {
128
+ return a.filter((x) => !b.some((y) => markRangeEquals(x, y)));
129
+ }
130
+ function applyMarkRules(rules, transactions, oldState, newState) {
131
+ if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) {
132
+ return null;
133
+ }
134
+ const ranges = getCheckRanges(transactions, oldState, newState);
135
+ const toRemove = [];
136
+ const toCreate = [];
137
+ for (const [from, to] of ranges) {
138
+ const expected = getExpectedMarkings(rules, newState.doc, from, to);
139
+ const received = getReceivedMarkings(rules, newState.doc, from, to);
140
+ toRemove.push(...markRangeDiffs(received, expected));
141
+ toCreate.push(...markRangeDiffs(expected, received));
142
+ }
143
+ if (toCreate.length === 0 && toRemove.length === 0) {
144
+ return null;
145
+ }
146
+ const tr = newState.tr;
147
+ for (const [from, to, mark] of toRemove) {
148
+ tr.removeMark(from, to, mark);
149
+ }
150
+ for (const [from, to, mark] of toCreate) {
151
+ tr.addMark(from, to, mark);
152
+ }
153
+ return tr;
154
+ }
155
+
156
+ // src/mark-rule/extension.ts
157
+ function defineMarkRule(options) {
158
+ const { regex, type, attrs } = options;
159
+ const getAttrs = attrs && typeof attrs === "object" ? () => attrs : attrs;
160
+ return markRuleFacet.extension([{ regex, type, getAttrs }]);
161
+ }
162
+ var markRuleFacet = Facet.define({
163
+ converter: () => {
164
+ let rules = [];
165
+ const plugin = new ProseMirrorPlugin({
166
+ appendTransaction: (transactions, oldState, newState) => {
167
+ return applyMarkRules(rules, transactions, oldState, newState);
168
+ }
169
+ });
170
+ const pluginFunc = () => [plugin];
171
+ return {
172
+ create: (inputs) => {
173
+ rules = inputs;
174
+ return pluginFunc;
175
+ },
176
+ update: (inputs) => {
177
+ rules = inputs;
178
+ return null;
179
+ }
180
+ };
181
+ },
182
+ next: pluginFacet
183
+ });
184
+
185
+ export {
186
+ defineMarkRule
187
+ };
@@ -1,4 +1,4 @@
1
- /* ../../node_modules/.pnpm/prosemirror-flat-list@0.4.6/node_modules/prosemirror-flat-list/dist/style.css */
1
+ /* ../../node_modules/.pnpm/prosemirror-flat-list@0.5.0/node_modules/prosemirror-flat-list/dist/style.css */
2
2
  .prosemirror-flat-list {
3
3
  padding: 0;
4
4
  margin-top: 0;
@@ -1,9 +1,9 @@
1
- import {
2
- defineTextBlockInputRule
3
- } from "./chunk-DYFRBXUX.js";
4
1
  import {
5
2
  defineTextBlockEnterRule
6
3
  } from "./chunk-ASTUC4KT.js";
4
+ import {
5
+ defineTextBlockInputRule
6
+ } from "./chunk-DYFRBXUX.js";
7
7
 
8
8
  // src/code-block/code-block.ts
9
9
  import { union } from "@prosekit/core";
@@ -2,5 +2,6 @@ export { defineLinkSpec } from './_tsup-dts-rollup';
2
2
  export { defineLinkCommands } from './_tsup-dts-rollup';
3
3
  export { defineLinkInputRule } from './_tsup-dts-rollup';
4
4
  export { defineLinkEnterRule } from './_tsup-dts-rollup';
5
+ export { defineLinkMarkRule } from './_tsup-dts-rollup';
5
6
  export { defineLink } from './_tsup-dts-rollup';
6
7
  export { LinkAttrs } from './_tsup-dts-rollup';
@@ -1,9 +1,12 @@
1
1
  import {
2
- defineInputRule
3
- } from "./chunk-DYFRBXUX.js";
2
+ defineMarkRule
3
+ } from "./chunk-MX6UNVWH.js";
4
4
  import {
5
5
  defineEnterRule
6
6
  } from "./chunk-ASTUC4KT.js";
7
+ import {
8
+ defineInputRule
9
+ } from "./chunk-DYFRBXUX.js";
7
10
 
8
11
  // src/link/index.ts
9
12
  import {
@@ -19,15 +22,19 @@ import { InputRule } from "@prosekit/pm/inputrules";
19
22
 
20
23
  // src/link/link-regex.ts
21
24
  var TLD_RE_PATTERN = "a(?:a(?:a|rp)|b(?:arth|b(?:ott|vie)?|c|le|ogado|udhabi)|c(?:ademy|c(?:enture|ountants?)|o|tor)?|d(?:s|ult)?|e(?:g|ro|tna)?|f(?:l|rica)?|g(?:akhan|ency)?|i(?:g|r(?:bus|force|tel))?|kdn|l(?:faromeo|i(?:baba|pay)|l(?:finanz|state|y)|s(?:ace|tom))?|m(?:azon|e(?:rican(?:express|family)|x)|fam|ica|sterdam)?|n(?:alytics|droid|quan|z)|ol?|p(?:artments|p(?:le)?)|q(?:uarelle)?|r(?:a(?:b|mco)|chi|my|pa|te?)?|s(?:da|ia|sociates)?|t(?:hleta|torney)?|u(?:ction|di(?:ble|o)?|spost|t(?:hor|os?))?|vianca|ws?|xa?|z(?:ure)?)|b(?:a(?:by|idu|n(?:a(?:mex|narepublic)|d|k)|r(?:c(?:elona|lay(?:card|s))|efoot|gains)?|s(?:eball|ketball)|uhaus|yern)?|b(?:c|t|va)?|c[gn]|d|e(?:a(?:ts|uty)|er|ntley|rlin|st(?:buy)?|t)?|f|g|h(?:arti)?|i(?:ble|d|ke|ngo?|o|z)?|j|l(?:ack(?:friday)?|o(?:ckbuster|g|omberg)|ue)|m[sw]?|n(?:pparibas)?|o(?:ats|ehringer|fa|m|nd|o(?:k(?:ing)?)?|s(?:ch|t(?:ik|on))|t|utique|x)?|r(?:adesco|idgestone|o(?:adway|ker|ther)|ussels)?|s|t|u(?:ild(?:ers)?|siness|y|zz)|v|w|y|zh?)|c(?:a(?:b|fe|l(?:l|vinklein)?|m(?:era|p)?|non|p(?:etown|ital(?:one)?)|r(?:avan|ds|e(?:ers?)?|s)?|s(?:a|e|h|ino)|t(?:ering|holic)?)?|b(?:a|n|re|s)|c|d|e(?:nter|o|rn)|f[ad]?|g|h(?:a(?:n(?:el|nel)|rity|se|t)|eap|intai|r(?:istmas|ome)|urch)?|i(?:priani|rcle|sco|t(?:adel|ic?|y(?:eats)?))?|k|l(?:aims|eaning|i(?:ck|ni(?:c|que))|o(?:thing|ud)|ub(?:med)?)?|m|n|o(?:ach|des|ffee|l(?:lege|ogne)|m(?:cast|m(?:bank|unity)|p(?:a(?:ny|re)|uter)|sec)?|n(?:dos|s(?:truction|ulting)|t(?:act|ractors))|o(?:king(?:channel)?|l|p)|rsica|u(?:ntry|pons?|rses))?|pa|r(?:edit(?:card|union)?|icket|own|s|uises?)?|u(?:isinella)?|v|w|x|y(?:mru|ou)?|z)|d(?:a(?:bur|d|nce|t(?:a|e|ing|sun)|y)|clk|ds|e(?:al(?:er|s)?|gree|l(?:ivery|l|oitte|ta)|mocrat|nt(?:al|ist)|si(?:gn)?|v)?|hl|i(?:amonds|et|gital|rect(?:ory)?|s(?:co(?:unt|ver)|h)|y)|j|k|m|np|o(?:c(?:s|tor)|g|mains|t|wnload)?|rive|tv|u(?:bai|nlop|pont|rban)|v(?:ag|r)|z)|e(?:a(?:rth|t)|co?|d(?:eka|u(?:cation)?)|e|g|m(?:ail|erck)|n(?:ergy|gineer(?:ing)?|terprises)|pson|quipment|r(?:icsson|ni)?|s(?:q|tate)?|t(?:isalat)?|u(?:rovision|s)?|vents|x(?:change|p(?:ert|osed|ress)|traspace))|f(?:a(?:ge|i(?:l|rwinds|th)|mily|ns?|rm(?:ers)?|s(?:hion|t))|e(?:dex|edback|rr(?:ari|ero))|i(?:at|d(?:elity|o)|lm|na(?:l|nc(?:e|ial))|r(?:e(?:stone)?|mdale)|sh(?:ing)?|t(?:ness)?)?|j|k|l(?:i(?:ckr|ghts|r)|o(?:rist|wers)|y)|m|o(?:o(?:d(?:network)?|tball)?|r(?:d|ex|sale|um)|undation|x)?|r(?:e(?:e|senius)|l|o(?:gans|nt(?:door|ier)))?|tr|u(?:jitsu|nd?|rniture|tbol)|yi)|g(?:a(?:l(?:l(?:ery|o|up))?|mes?|p|rden|y)?|b(?:iz)?|dn?|e(?:a|nt(?:ing)?|orge)?|f|g(?:ee)?|h|i(?:fts?|v(?:es|ing))?|l(?:ass|e|ob(?:al|o))?|m(?:ail|bh|o|x)?|n|o(?:daddy|l(?:d(?:point)?|f)|o(?:dyear|g(?:le)?)?|p|t|v)|p|q|r(?:a(?:inger|phics|tis)|een|ipe|o(?:cery|up))?|s|t|u(?:ardian|cci|ge|i(?:de|tars)|ru)?|w|y)|h(?:a(?:ir|mburg|ngout|us)|bo|dfc(?:bank)?|e(?:alth(?:care)?|l(?:p|sinki)|r(?:e|mes))|gtv|i(?:phop|samitsu|tachi|v)|kt?|m|n|o(?:ckey|l(?:dings|iday)|me(?:depot|goods|s(?:ense)?)|nda|rse|s(?:pital|t(?:ing)?)|t(?:el(?:es|s)|mail)?|use|w)|r|sbc|t|u(?:ghes)?|y(?:att|undai))|i(?:bm|c(?:bc|e|u)|d|e(?:ee)?|fm|kano|l|m(?:amat|db|mo(?:bilien)?)?|n(?:c|dustries|f(?:initi|o)|g|k|s(?:titute|ur(?:ance|e))|t(?:ernational|uit)?|vestments)?|o|piranga|q|r(?:ish)?|s(?:maili|t(?:anbul)?)?|t(?:au|v)?)|j(?:a(?:guar|va)|cb|e(?:ep|tzt|welry)?|io|ll|mp?|nj|o(?:b(?:s|urg)|t|y)?|p(?:morgan|rs)?|u(?:egos|niper))|k(?:aufen|ddi|e(?:rry(?:hotels|logistics|properties))?|fh|g|h|i(?:a|ds|m|nd(?:er|le)|tchen|wi)?|m|n|o(?:eln|matsu|sher)|p(?:mg|n)?|r(?:d|ed)?|uokgroup|w|y(?:oto)?|z)|l(?:a(?:caixa|m(?:borghini|er)|n(?:c(?:aster|ia)|d(?:rover)?|xess)|salle|t(?:ino|robe)?|w(?:yer)?)?|b|c|ds|e(?:ase|clerc|frak|g(?:al|o)|xus)|gbt|i(?:dl|fe(?:insurance|style)?|ghting|ke|lly|m(?:ited|o)|n(?:coln|de|k)|psy|v(?:e|ing))?|k|l[cp]|o(?:ans?|c(?:ker|us)|l|ndon|tt[eo]|ve)|pl(?:financial)?|r|s|t(?:da?)?|u(?:ndbeck|x(?:e|ury))?|v|y)|m(?:a(?:cys|drid|i(?:f|son)|keup|n(?:agement|go)?|p|r(?:ket(?:ing|s)?|riott|shalls)|serati|ttel)?|ba|c(?:kinsey)?|d|e(?:d(?:ia)?|et|lbourne|m(?:e|orial)|nu?|rckmsd)?|g|h|i(?:ami|crosoft|l|n[it]|t(?:subishi)?)|k|l[bs]?|ma?|n|o(?:bi(?:le)?|da|e|i|m|n(?:ash|ey|ster)|r(?:mon|tgage)|scow|to(?:rcycles)?|v(?:ie)?)?|p|q|r|sd?|t[nr]?|u(?:s(?:eum|ic)|tual)?|v|w|x|y|z)|n(?:a(?:b|goya|me|tura|vy)?|ba|c|e(?:c|t(?:bank|flix|work)?|ustar|ws?|x(?:t(?:direct)?|us))?|fl?|go?|hk|i(?:co|k(?:e|on)|nja|ssa[ny])?|l|o(?:kia|rt(?:hwesternmutual|on)|w(?:ruz|tv)?)?|p|r[aw]?|tt|u|yc|z)|o(?:b(?:i|server)|ffice|kinawa|l(?:ayan(?:group)?|dnavy|lo)|m(?:ega)?|n(?:e|g|l(?:ine)?)|oo|pen|r(?:a(?:cle|nge)|g(?:anic)?|igins)|saka|t(?:suka|t)|vh)|p(?:a(?:ge|nasonic|r(?:is|s|t(?:ners|s|y))|ssagens|y)?|ccw|et?|f(?:izer)?|g|h(?:armacy|d|ilips|o(?:ne|to(?:graphy|s)?)|ysio)?|i(?:c(?:s|t(?:et|ures))|d|n[gk]?|oneer|zza)|k|l(?:a(?:ce|y(?:station)?)|u(?:mbing|s))?|m|nc?|o(?:hl|ker|litie|rn|st)|r(?:a(?:merica|xi)|ess|ime|o(?:d(?:uctions)?|f|gressive|mo|pert(?:ies|y)|tection)?|u(?:dential)?)?|s|t|ub|wc?|y)|q(?:a|pon|ue(?:bec|st))|r(?:a(?:cing|dio)|e(?:a(?:d|l(?:estate|t(?:or|y)))|cipes|d(?:stone|umbrella)?|hab|i(?:sen?|t)|liance|n(?:t(?:als)?)?|p(?:air|ort|ublican)|st(?:aurant)?|views?|xroth)?|i(?:c(?:h(?:ardli)?|oh)|l|o|p)|o(?:c(?:her|ks)|deo|gers|om)?|s(?:vp)?|u(?:gby|hr|n)?|we?|yukyu)|s(?:a(?:arland|fe(?:ty)?|kura|l(?:e|on)|ms(?:club|ung)|n(?:dvik(?:coromant)?|ofi)|p|rl|s|ve|xo)?|b[is]?|c(?:a|b|h(?:aeffler|midt|o(?:larships|ol)|ule|warz)|ience|ot)?|d|e(?:a(?:rch|t)|cur(?:e|ity)|ek|lect|ner|rvices|ven|w|xy?)?|fr|g|h(?:a(?:ngrila|rp|w)|ell|i(?:a|ksha)|o(?:es|p(?:ping)?|uji|w(?:time)?))?|i(?:lk|n(?:a|gles)|te)?|j|k(?:in?|y(?:pe)?)?|l(?:ing)?|m(?:art|ile)?|n(?:cf)?|o(?:c(?:cer|ial)|ft(?:bank|ware)|hu|l(?:ar|utions)|n[gy]|y)?|p(?:a(?:ce)?|o(?:rt|t))|rl?|s|t(?:a(?:da|ples|r|te(?:bank|farm))|c(?:group)?|o(?:ckholm|r(?:age|e))|ream|ud(?:io|y)|yle)?|u(?:cks|pp(?:l(?:ies|y)|ort)|r(?:f|gery)|zuki)?|v|w(?:atch|iss)|x|y(?:dney|stems)?|z)|t(?:a(?:b|ipei|lk|obao|rget|t(?:a(?:motors|r)|too)|xi?)|ci?|dk?|e(?:am|ch(?:nology)?|l|masek|nnis|va)|f|g|h(?:d|eat(?:er|re))?|i(?:aa|ckets|enda|ffany|ps|r(?:es|ol))|j(?:maxx|x)?|k(?:maxx)?|l|m(?:all)?|n|o(?:day|kyo|ols|p|ray|shiba|tal|urs|wn|y(?:ota|s))?|r(?:a(?:d(?:e|ing)|ining|vel(?:channel|ers(?:insurance)?)?)|ust|v)?|t|u(?:be|i|nes|shu)|vs?|w|z)|u(?:a|b(?:ank|s)|g|k|n(?:i(?:com|versity)|o)|ol|ps|s|y|z)|v(?:a(?:cations|n(?:a|guard))?|c|e(?:gas|ntures|r(?:isign|sicherung)|t)?|g|i(?:ajes|deo|g|king|llas|n|p|rgin|s(?:a|ion)|v[ao])?|laanderen|n|o(?:dka|l(?:kswagen|vo)|t(?:e|ing|o)|yage)|u(?:elos)?)|w(?:a(?:l(?:es|mart|ter)|ng(?:gou)?|tch(?:es)?)|e(?:ather(?:channel)?|b(?:cam|er|site)|d(?:ding)?|i(?:bo|r))|f|hoswho|i(?:en|ki|lliamhill|n(?:dows|e|ners)?)|me|o(?:lterskluwer|odside|r(?:ks?|ld)|w)|s|t[cf])|x(?:box|erox|finity|i(?:huan|n)|xx|yz)|y(?:a(?:chts|hoo|maxun|ndex)|e|o(?:dobashi|ga|kohama|u(?:tube)?)|t|un)|z(?:a(?:ppos|ra)?|ero|ip|m|one|uerich|w)";
25
+ var PUNCTUATION_CHAR_PATTERN = "\\.\\,\\;\\!\\?";
26
+ var STOP_CHAR_PATTERN = "[" + PUNCTUATION_CHAR_PATTERN + "]";
27
+ var END_CHAR_PATTERN = "[^\\s" + PUNCTUATION_CHAR_PATTERN + "]";
22
28
  var LINK_RE_BASE_PATTERN = (
23
29
  // start of the link group
24
- "((?:(?:(?:https?:)?\\/\\/)?(?:(?:[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62})?[a-z0-9\\u00a1-\\uffff]\\.)+(?:" + TLD_RE_PATTERN + "))(?::\\d{2,5})?(?:[/?#]\\S*)?)"
30
+ "((?:(?:(?:https?:)?\\/\\/)?(?:(?:[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62})?[a-z0-9\\u00a1-\\uffff]\\.)+(?:" + TLD_RE_PATTERN + "))(?::\\d{2,5})?(?:/(?:\\S*" + END_CHAR_PATTERN + ")?)?(?:\\?(?:\\S*" + END_CHAR_PATTERN + "))?(?:\\#(?:\\S*" + END_CHAR_PATTERN + ")?)?)"
25
31
  );
26
- var LINK_STOP_PATTERN = "(?:\\.|\\,|\\;\\!)?";
27
- var LINK_RE_PATTERN = LINK_RE_BASE_PATTERN + LINK_STOP_PATTERN + "$";
28
- var LINK_SPACE_RE_PATTERN = LINK_RE_BASE_PATTERN + LINK_STOP_PATTERN + "\\s$";
29
- var LINK_RE = new RegExp(LINK_RE_PATTERN, "gi");
30
- var LINK_SPACE_RE = new RegExp(LINK_SPACE_RE_PATTERN, "gi");
32
+ var LINK_ENTER_PATTERN = LINK_RE_BASE_PATTERN + STOP_CHAR_PATTERN + "?$";
33
+ var LINK_INPUT_PATTERN = LINK_RE_BASE_PATTERN + STOP_CHAR_PATTERN + "?\\s$";
34
+ var LINK_MARK_PATTERN = LINK_RE_BASE_PATTERN + "(?=" + STOP_CHAR_PATTERN + "|\\s|$)";
35
+ var LINK_ENTER_RE = new RegExp(LINK_ENTER_PATTERN, "gi");
36
+ var LINK_INPUT_RE = new RegExp(LINK_INPUT_PATTERN, "gi");
37
+ var LINK_MARK_RE = new RegExp(LINK_MARK_PATTERN, "gi");
31
38
 
32
39
  // src/link/index.ts
33
40
  function defineLinkSpec() {
@@ -63,7 +70,7 @@ function defineLinkCommands() {
63
70
  }
64
71
  function defineLinkInputRule() {
65
72
  return defineInputRule(
66
- new InputRule(LINK_SPACE_RE, (state, match, from) => {
73
+ new InputRule(LINK_INPUT_RE, (state, match, from) => {
67
74
  const href = match[1];
68
75
  if (!href)
69
76
  return null;
@@ -74,7 +81,7 @@ function defineLinkInputRule() {
74
81
  }
75
82
  function defineLinkEnterRule() {
76
83
  return defineEnterRule({
77
- regex: LINK_RE,
84
+ regex: LINK_ENTER_RE,
78
85
  handler: ({ state, from, match }) => {
79
86
  const href = match[1];
80
87
  if (!href)
@@ -85,6 +92,13 @@ function defineLinkEnterRule() {
85
92
  }
86
93
  });
87
94
  }
95
+ function defineLinkMarkRule() {
96
+ return defineMarkRule({
97
+ regex: LINK_MARK_RE,
98
+ type: "link",
99
+ attrs: (match) => ({ href: match[1] })
100
+ });
101
+ }
88
102
  function defineLink() {
89
103
  return union([
90
104
  defineLinkSpec(),
@@ -98,5 +112,6 @@ export {
98
112
  defineLinkCommands,
99
113
  defineLinkEnterRule,
100
114
  defineLinkInputRule,
115
+ defineLinkMarkRule,
101
116
  defineLinkSpec
102
117
  };
@@ -0,0 +1,2 @@
1
+ export { MarkRuleOptions } from './_tsup-dts-rollup';
2
+ export { defineMarkRule_alias_1 as defineMarkRule } from './_tsup-dts-rollup';
@@ -0,0 +1,6 @@
1
+ import {
2
+ defineMarkRule
3
+ } from "./chunk-MX6UNVWH.js";
4
+ export {
5
+ defineMarkRule
6
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/extensions",
3
3
  "type": "module",
4
- "version": "0.4.2",
4
+ "version": "0.4.4",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -30,6 +30,11 @@
30
30
  "import": "./dist/prosekit-extensions.js",
31
31
  "default": "./dist/prosekit-extensions.js"
32
32
  },
33
+ "./mark-rule": {
34
+ "types": "./dist/prosekit-extensions-mark-rule.d.ts",
35
+ "import": "./dist/prosekit-extensions-mark-rule.js",
36
+ "default": "./dist/prosekit-extensions-mark-rule.js"
37
+ },
33
38
  "./autocomplete": {
34
39
  "types": "./dist/prosekit-extensions-autocomplete.d.ts",
35
40
  "import": "./dist/prosekit-extensions-autocomplete.js",
@@ -147,19 +152,19 @@
147
152
  "dist"
148
153
  ],
149
154
  "dependencies": {
150
- "@prosekit/core": "^0.4.0",
155
+ "@prosekit/core": "^0.4.1",
151
156
  "@prosekit/pm": "^0.1.2",
152
157
  "prosemirror-dropcursor": "^1.8.1",
153
- "prosemirror-flat-list": "^0.4.6",
158
+ "prosemirror-flat-list": "^0.5.0",
154
159
  "prosemirror-highlight": "^0.5.0",
155
160
  "prosemirror-tables": "^1.3.7",
156
- "shiki": "^1.1.7"
161
+ "shiki": "^1.3.0"
157
162
  },
158
163
  "devDependencies": {
159
164
  "@prosekit/dev": "*",
160
165
  "tsup": "^8.0.2",
161
- "typescript": "^5.3.3",
162
- "vitest": "^1.3.1"
166
+ "typescript": "^5.4.5",
167
+ "vitest": "^1.5.2"
163
168
  },
164
169
  "scripts": {
165
170
  "build:tsup": "tsup",
@@ -171,6 +176,9 @@
171
176
  ".": [
172
177
  "./dist/prosekit-extensions.d.ts"
173
178
  ],
179
+ "mark-rule": [
180
+ "./dist/prosekit-extensions-mark-rule.d.ts"
181
+ ],
174
182
  "autocomplete": [
175
183
  "./dist/prosekit-extensions-autocomplete.d.ts"
176
184
  ],