@prosekit/extensions 0.4.2 → 0.4.3
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/_tsup-dts-rollup.d.ts +62 -2
- package/dist/chunk-TXF4SPMB.js +185 -0
- package/dist/list/style.css +1 -1
- package/dist/prosekit-extensions-code-block.js +3 -3
- package/dist/prosekit-extensions-link.d.ts +1 -0
- package/dist/prosekit-extensions-link.js +25 -10
- package/dist/prosekit-extensions-mark-rule.d.ts +2 -0
- package/dist/prosekit-extensions-mark-rule.js +6 -0
- package/package.json +13 -5
@@ -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,12 @@ 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
|
+
export declare function defineMarkRule(options: MarkRuleOptions): Extension<ExtensionTyping<string, string, CommandArgs>>;
|
489
|
+
|
470
490
|
/**
|
471
491
|
* @public
|
472
492
|
*/
|
@@ -758,6 +778,8 @@ export declare type EnterRuleOptions = {
|
|
758
778
|
*/
|
759
779
|
export declare const exitTable: Command;
|
760
780
|
|
781
|
+
export declare function getCheckRanges(transactions: readonly Transaction[], oldState: EditorState, newState: EditorState): Array<[number, number]>;
|
782
|
+
|
761
783
|
export { getHighlighter }
|
762
784
|
|
763
785
|
export declare function getPluginState(state: EditorState): PredictionPluginState | undefined;
|
@@ -799,9 +821,11 @@ export declare function insertTable({ row, col, header, }: {
|
|
799
821
|
header: boolean;
|
800
822
|
}): Command;
|
801
823
|
|
802
|
-
export declare const
|
824
|
+
export declare const LINK_ENTER_RE: RegExp;
|
803
825
|
|
804
|
-
export declare const
|
826
|
+
export declare const LINK_INPUT_RE: RegExp;
|
827
|
+
|
828
|
+
export declare const LINK_MARK_RE: RegExp;
|
805
829
|
|
806
830
|
/**
|
807
831
|
* @public
|
@@ -812,6 +836,42 @@ export declare interface LinkAttrs {
|
|
812
836
|
|
813
837
|
export { ListDOMSerializer }
|
814
838
|
|
839
|
+
/**
|
840
|
+
* @internal
|
841
|
+
*/
|
842
|
+
export declare class MarkRule {
|
843
|
+
readonly regex: RegExp;
|
844
|
+
readonly type: string | MarkType;
|
845
|
+
readonly getAttrs: (match: RegExpMatchArray) => Attrs | null;
|
846
|
+
constructor({ regex, type, attrs }: MarkRuleOptions);
|
847
|
+
}
|
848
|
+
|
849
|
+
/**
|
850
|
+
* The options for {@link defineMarkRule}.
|
851
|
+
*
|
852
|
+
* @public
|
853
|
+
*/
|
854
|
+
declare interface MarkRuleOptions {
|
855
|
+
/**
|
856
|
+
* The regular expression to match against. It must has a `g` flag to match
|
857
|
+
* all instances of the mark.
|
858
|
+
*/
|
859
|
+
regex: RegExp;
|
860
|
+
/**
|
861
|
+
* The mark type to apply to the matched text.
|
862
|
+
*/
|
863
|
+
type: string | MarkType;
|
864
|
+
/**
|
865
|
+
* Attributes to set on the mark. If a function is provided, it will be called
|
866
|
+
* with the matched result from the regular expression.
|
867
|
+
*
|
868
|
+
* @default null
|
869
|
+
*/
|
870
|
+
attrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null);
|
871
|
+
}
|
872
|
+
export { MarkRuleOptions }
|
873
|
+
export { MarkRuleOptions as MarkRuleOptions_alias_1 }
|
874
|
+
|
815
875
|
declare type MatchHandler = (options: {
|
816
876
|
state: EditorState;
|
817
877
|
match: RegExpExecArray;
|
@@ -0,0 +1,185 @@
|
|
1
|
+
// src/mark-rule/index.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(hi, 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
|
+
const text = doc.textBetween(from, to, OBJECT_REPLACEMENT_CHARACTER);
|
81
|
+
const result = [];
|
82
|
+
for (const rule of rules) {
|
83
|
+
rule.regex.lastIndex = 0;
|
84
|
+
const matches = text.matchAll(rule.regex);
|
85
|
+
const markType = getMarkType(doc.type.schema, rule.type);
|
86
|
+
for (const match of matches) {
|
87
|
+
const index = match.index;
|
88
|
+
if (index == null)
|
89
|
+
continue;
|
90
|
+
const attrs = rule.getAttrs(match);
|
91
|
+
const mark = markType.create(attrs);
|
92
|
+
result.push([mark, from + index, from + index + match[0].length]);
|
93
|
+
}
|
94
|
+
}
|
95
|
+
return result;
|
96
|
+
}
|
97
|
+
function getReceivedMarkings(rules, doc, from, to) {
|
98
|
+
const result = [];
|
99
|
+
const schema = doc.type.schema;
|
100
|
+
const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
|
101
|
+
doc.nodesBetween(from, to, (node, pos) => {
|
102
|
+
if (!node.isInline) {
|
103
|
+
return;
|
104
|
+
}
|
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]);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
});
|
112
|
+
return result;
|
113
|
+
}
|
114
|
+
function markingEquals(a, b) {
|
115
|
+
return a[1] === b[1] && a[2] === b[2] && a[0].eq(b[0]);
|
116
|
+
}
|
117
|
+
function markingDiffs(a, b) {
|
118
|
+
return a.filter((x) => !b.some((y) => markingEquals(x, y)));
|
119
|
+
}
|
120
|
+
function applyMarkRules(rules, transactions, oldState, newState) {
|
121
|
+
if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) {
|
122
|
+
return null;
|
123
|
+
}
|
124
|
+
const ranges = getCheckRanges(transactions, oldState, newState);
|
125
|
+
const toRemove = [];
|
126
|
+
const toCreate = [];
|
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);
|
130
|
+
toRemove.push(...markingDiffs(received, expected));
|
131
|
+
toCreate.push(...markingDiffs(expected, received));
|
132
|
+
}
|
133
|
+
if (toCreate.length === 0 && toRemove.length === 0) {
|
134
|
+
return null;
|
135
|
+
}
|
136
|
+
const tr = newState.tr;
|
137
|
+
for (const [mark, from, to] of toRemove) {
|
138
|
+
tr.removeMark(from, to, mark);
|
139
|
+
}
|
140
|
+
for (const [mark, from, to] of toCreate) {
|
141
|
+
tr.addMark(from, to, mark);
|
142
|
+
}
|
143
|
+
return tr;
|
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
|
+
}
|
160
|
+
var markRuleFacet = Facet.define({
|
161
|
+
converter: () => {
|
162
|
+
let rules = [];
|
163
|
+
const plugin = new ProseMirrorPlugin({
|
164
|
+
appendTransaction: (transactions, oldState, newState) => {
|
165
|
+
return applyMarkRules(rules, transactions, oldState, newState);
|
166
|
+
}
|
167
|
+
});
|
168
|
+
const pluginFunc = () => [plugin];
|
169
|
+
return {
|
170
|
+
create: (inputs) => {
|
171
|
+
rules = inputs;
|
172
|
+
return pluginFunc;
|
173
|
+
},
|
174
|
+
update: (inputs) => {
|
175
|
+
rules = inputs;
|
176
|
+
return null;
|
177
|
+
}
|
178
|
+
};
|
179
|
+
},
|
180
|
+
next: pluginFacet
|
181
|
+
});
|
182
|
+
|
183
|
+
export {
|
184
|
+
defineMarkRule
|
185
|
+
};
|
package/dist/list/style.css
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* ../../node_modules/.pnpm/prosemirror-flat-list@0.
|
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
|
-
|
3
|
-
} from "./chunk-
|
2
|
+
defineMarkRule
|
3
|
+
} from "./chunk-TXF4SPMB.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})?(
|
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
|
27
|
-
var
|
28
|
-
var
|
29
|
-
var
|
30
|
-
var
|
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(
|
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:
|
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
|
};
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@prosekit/extensions",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.4.
|
4
|
+
"version": "0.4.3",
|
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",
|
@@ -150,16 +155,16 @@
|
|
150
155
|
"@prosekit/core": "^0.4.0",
|
151
156
|
"@prosekit/pm": "^0.1.2",
|
152
157
|
"prosemirror-dropcursor": "^1.8.1",
|
153
|
-
"prosemirror-flat-list": "^0.
|
158
|
+
"prosemirror-flat-list": "^0.5.0",
|
154
159
|
"prosemirror-highlight": "^0.5.0",
|
155
160
|
"prosemirror-tables": "^1.3.7",
|
156
|
-
"shiki": "^1.
|
161
|
+
"shiki": "^1.3.0"
|
157
162
|
},
|
158
163
|
"devDependencies": {
|
159
164
|
"@prosekit/dev": "*",
|
160
165
|
"tsup": "^8.0.2",
|
161
|
-
"typescript": "^5.
|
162
|
-
"vitest": "^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
|
],
|