@prosekit/extensions 0.7.2 → 0.7.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 +4 -4
- package/dist/chunk-GPSAJOJA.js +188 -0
- package/dist/{chunk-PYT3MOTF.js → chunk-LVMTQOWG.js} +31 -14
- package/dist/{chunk-2JYT2MT7.js → chunk-OJCMRVEY.js} +36 -21
- package/dist/list/style.css +8 -4
- package/dist/placeholder/style.css +1 -1
- package/dist/prosekit-extensions-autocomplete.js +62 -33
- package/dist/prosekit-extensions-blockquote.js +2 -2
- package/dist/prosekit-extensions-bold.js +7 -3
- package/dist/prosekit-extensions-code-block.js +77 -41
- package/dist/prosekit-extensions-code.js +1 -1
- package/dist/prosekit-extensions-commit.js +70 -30
- package/dist/prosekit-extensions-enter-rule.js +1 -1
- package/dist/prosekit-extensions-heading.js +18 -8
- package/dist/prosekit-extensions-image.js +14 -5
- package/dist/prosekit-extensions-input-rule.js +1 -1
- package/dist/prosekit-extensions-italic.js +1 -1
- package/dist/prosekit-extensions-link.js +27 -14
- package/dist/prosekit-extensions-list.js +3 -2
- package/dist/prosekit-extensions-mark-rule.js +1 -1
- package/dist/prosekit-extensions-mention.js +6 -4
- package/dist/prosekit-extensions-placeholder.js +16 -7
- package/dist/prosekit-extensions-readonly.js +1 -1
- package/dist/prosekit-extensions-search.js +8 -5
- package/dist/prosekit-extensions-strike.js +1 -1
- package/dist/prosekit-extensions-table.js +68 -30
- package/dist/prosekit-extensions-text-align.js +4 -2
- package/dist/prosekit-extensions-virtual-selection.js +11 -6
- package/package.json +4 -4
- package/dist/chunk-ZPEMHYTU.js +0 -140
@@ -835,8 +835,8 @@ export declare function defineTestExtension(): Extension<{
|
|
835
835
|
removeMark: [options: RemoveMarkOptions];
|
836
836
|
unsetBlockType: [options?: UnsetBlockTypeOptions | undefined];
|
837
837
|
unsetMark: [options?: UnsetMarkOptions | undefined];
|
838
|
-
undo: [];
|
839
|
-
redo: [];
|
838
|
+
readonly undo: [];
|
839
|
+
readonly redo: [];
|
840
840
|
toggleBold: [];
|
841
841
|
toggleCode: [];
|
842
842
|
setHeading: [attrs?: HeadingAttrs | undefined];
|
@@ -1330,8 +1330,8 @@ export declare function setupTest(): {
|
|
1330
1330
|
removeMark: [options: RemoveMarkOptions];
|
1331
1331
|
unsetBlockType: [options?: UnsetBlockTypeOptions | undefined];
|
1332
1332
|
unsetMark: [options?: UnsetMarkOptions | undefined];
|
1333
|
-
undo: [];
|
1334
|
-
redo: [];
|
1333
|
+
readonly undo: [];
|
1334
|
+
readonly redo: [];
|
1335
1335
|
toggleBold: [];
|
1336
1336
|
toggleCode: [];
|
1337
1337
|
setHeading: [attrs?: HeadingAttrs | undefined];
|
@@ -0,0 +1,188 @@
|
|
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
|
+
const nodeRange = $from.blockRange($to);
|
25
|
+
if (!nodeRange) {
|
26
|
+
return [];
|
27
|
+
}
|
28
|
+
const stack = [];
|
29
|
+
let start = nodeRange.start;
|
30
|
+
for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) {
|
31
|
+
const child = nodeRange.parent.child(i);
|
32
|
+
stack.push([start, child]);
|
33
|
+
start += child.nodeSize;
|
34
|
+
}
|
35
|
+
const ranges = [];
|
36
|
+
while (stack.length > 0) {
|
37
|
+
const [start2, node] = stack.pop();
|
38
|
+
if (node.type.spec.code) {
|
39
|
+
continue;
|
40
|
+
}
|
41
|
+
if (node.type.isTextblock) {
|
42
|
+
ranges.push([start2 + 1, start2 + 1 + node.content.size]);
|
43
|
+
continue;
|
44
|
+
}
|
45
|
+
node.forEach((child, offset) => {
|
46
|
+
stack.push([start2 + offset + 1, child]);
|
47
|
+
});
|
48
|
+
}
|
49
|
+
return ranges;
|
50
|
+
}
|
51
|
+
function getInlineTextRange($from, $to) {
|
52
|
+
return [$from.start(), $to.end()];
|
53
|
+
}
|
54
|
+
function getTextRanges(doc, from, to) {
|
55
|
+
const $from = doc.resolve(from);
|
56
|
+
const $to = doc.resolve(to);
|
57
|
+
if ($from.sameParent($to) && $from.parent.isTextblock) {
|
58
|
+
return [getInlineTextRange($from, $to)];
|
59
|
+
} else {
|
60
|
+
const nodeRange = $from.blockRange($to);
|
61
|
+
if (!nodeRange) {
|
62
|
+
return [];
|
63
|
+
}
|
64
|
+
return getSpanTextRanges($from, $to);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
function getMapRange(transactions, oldState, newState) {
|
68
|
+
let lo = oldState.selection.from;
|
69
|
+
let hi = oldState.selection.to;
|
70
|
+
for (const tr of transactions) {
|
71
|
+
for (const map of tr.mapping.maps) {
|
72
|
+
lo = map.map(lo);
|
73
|
+
hi = map.map(hi);
|
74
|
+
map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
|
75
|
+
lo = Math.min(lo, hi, newStart);
|
76
|
+
hi = Math.max(lo, hi, newEnd);
|
77
|
+
});
|
78
|
+
}
|
79
|
+
}
|
80
|
+
lo = Math.min(lo, hi, newState.selection.from);
|
81
|
+
hi = Math.min(lo, hi, newState.selection.to);
|
82
|
+
return [lo, hi];
|
83
|
+
}
|
84
|
+
function getCheckRanges(transactions, oldState, newState) {
|
85
|
+
const [from, to] = getMapRange(transactions, oldState, newState);
|
86
|
+
return getTextRanges(newState.doc, from, to);
|
87
|
+
}
|
88
|
+
|
89
|
+
// src/mark-rule/apply.ts
|
90
|
+
function getExpectedMarkings(rules, doc, from, to) {
|
91
|
+
const text = doc.textBetween(from, to, null, OBJECT_REPLACEMENT_CHARACTER);
|
92
|
+
const ranges = [];
|
93
|
+
for (const rule of rules) {
|
94
|
+
rule.regex.lastIndex = 0;
|
95
|
+
const matches = text.matchAll(rule.regex);
|
96
|
+
const markType = getMarkType(doc.type.schema, rule.type);
|
97
|
+
for (const match of matches) {
|
98
|
+
const index = match.index;
|
99
|
+
if (index == null) continue;
|
100
|
+
const attrs = maybeRun(rule.attrs, match);
|
101
|
+
const mark = markType.create(attrs);
|
102
|
+
ranges.push([from + index, from + index + match[0].length, mark]);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
ranges.sort((a, b) => a[0] - b[0] || b[1] - a[1]);
|
106
|
+
const result = [];
|
107
|
+
let freeIndex = 0;
|
108
|
+
for (const range of ranges) {
|
109
|
+
if (range[0] >= freeIndex) {
|
110
|
+
result.push(range);
|
111
|
+
freeIndex = range[1];
|
112
|
+
}
|
113
|
+
}
|
114
|
+
return result;
|
115
|
+
}
|
116
|
+
function getReceivedMarkings(rules, doc, from, to) {
|
117
|
+
const result = [];
|
118
|
+
const schema = doc.type.schema;
|
119
|
+
const markTypes = rules.map((rule) => getMarkType(schema, rule.type));
|
120
|
+
doc.nodesBetween(from, to, (node, pos) => {
|
121
|
+
if (!node.isInline) {
|
122
|
+
return;
|
123
|
+
}
|
124
|
+
for (const markType of markTypes) {
|
125
|
+
const mark = node.marks.find((mark2) => mark2.type === markType);
|
126
|
+
if (mark) {
|
127
|
+
result.push([pos, pos + node.nodeSize, mark]);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
});
|
131
|
+
return result;
|
132
|
+
}
|
133
|
+
function markRangeEquals(a, b) {
|
134
|
+
return a[0] === b[0] && a[1] === b[1] && a[2].eq(b[2]);
|
135
|
+
}
|
136
|
+
function markRangeDiffs(a, b) {
|
137
|
+
return a.filter((x) => !b.some((y) => markRangeEquals(x, y)));
|
138
|
+
}
|
139
|
+
function applyMarkRules(rules, transactions, oldState, newState) {
|
140
|
+
if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) {
|
141
|
+
return null;
|
142
|
+
}
|
143
|
+
const ranges = getCheckRanges(transactions, oldState, newState);
|
144
|
+
const toRemove = [];
|
145
|
+
const toCreate = [];
|
146
|
+
for (const [from, to] of ranges) {
|
147
|
+
const expected = getExpectedMarkings(rules, newState.doc, from, to);
|
148
|
+
const received = getReceivedMarkings(rules, newState.doc, from, to);
|
149
|
+
toRemove.push(...markRangeDiffs(received, expected));
|
150
|
+
toCreate.push(...markRangeDiffs(expected, received));
|
151
|
+
}
|
152
|
+
if (toCreate.length === 0 && toRemove.length === 0) {
|
153
|
+
return null;
|
154
|
+
}
|
155
|
+
const tr = newState.tr;
|
156
|
+
for (const [from, to, mark] of toRemove) {
|
157
|
+
tr.removeMark(from, to, mark);
|
158
|
+
}
|
159
|
+
for (const [from, to, mark] of toCreate) {
|
160
|
+
tr.addMark(from, to, mark);
|
161
|
+
}
|
162
|
+
return tr;
|
163
|
+
}
|
164
|
+
|
165
|
+
// src/mark-rule/extension.ts
|
166
|
+
function defineMarkRule(options) {
|
167
|
+
return defineFacetPayload(markRuleFacet, [options]);
|
168
|
+
}
|
169
|
+
var markRuleFacet = defineFacet({
|
170
|
+
reduce: () => {
|
171
|
+
let rules = [];
|
172
|
+
const plugin = new ProseMirrorPlugin({
|
173
|
+
key: new PluginKey("prosekit-mark-rule"),
|
174
|
+
appendTransaction: (transactions, oldState, newState) => {
|
175
|
+
return applyMarkRules(rules, transactions, oldState, newState);
|
176
|
+
}
|
177
|
+
});
|
178
|
+
return function reducer(input) {
|
179
|
+
rules = input;
|
180
|
+
return plugin;
|
181
|
+
};
|
182
|
+
},
|
183
|
+
parent: pluginFacet
|
184
|
+
});
|
185
|
+
|
186
|
+
export {
|
187
|
+
defineMarkRule
|
188
|
+
};
|
@@ -24,20 +24,35 @@ function createMarkInputRule({
|
|
24
24
|
type,
|
25
25
|
attrs = null
|
26
26
|
}) {
|
27
|
-
|
27
|
+
const rule = new InputRule(regex, (state, match, start, end) => {
|
28
28
|
var _a;
|
29
|
-
|
30
|
-
|
29
|
+
const { tr, schema } = state;
|
30
|
+
const [fullText, markText] = match;
|
31
|
+
if (!markText) {
|
31
32
|
return null;
|
32
|
-
|
33
|
-
|
33
|
+
}
|
34
|
+
const markStart = start + fullText.indexOf(markText);
|
35
|
+
const markEnd = markStart + markText.length;
|
36
|
+
if (!(start <= markStart && markStart < markEnd && markEnd <= end)) {
|
34
37
|
return null;
|
35
|
-
|
36
|
-
|
38
|
+
}
|
39
|
+
const markType = getMarkType(schema, type);
|
40
|
+
const mark = markType.create(maybeRun(attrs, match));
|
41
|
+
if (!isMarkAbsent(tr.doc, markStart, markEnd, markType, attrs)) {
|
37
42
|
return null;
|
38
|
-
|
39
|
-
|
43
|
+
}
|
44
|
+
const initialStoredMarks = (_a = tr.storedMarks) != null ? _a : [];
|
45
|
+
tr.addMark(markStart, markEnd, mark);
|
46
|
+
if (markEnd < end) {
|
47
|
+
tr.delete(markEnd, end);
|
48
|
+
}
|
49
|
+
if (start < markStart) {
|
50
|
+
tr.delete(start, markStart);
|
51
|
+
}
|
52
|
+
tr.setStoredMarks(initialStoredMarks);
|
53
|
+
return tr;
|
40
54
|
});
|
55
|
+
return rule;
|
41
56
|
}
|
42
57
|
function defineMarkInputRule(options) {
|
43
58
|
return defineInputRule(createMarkInputRule(options));
|
@@ -49,7 +64,7 @@ function defineTextBlockInputRule({
|
|
49
64
|
}) {
|
50
65
|
return defineFacetPayload(inputRuleFacet, [
|
51
66
|
({ schema }) => {
|
52
|
-
|
67
|
+
const nodeType = getNodeType(schema, type);
|
53
68
|
return textblockTypeInputRule(regex, nodeType, attrs);
|
54
69
|
}
|
55
70
|
]);
|
@@ -62,15 +77,17 @@ function defineWrappingInputRule({
|
|
62
77
|
}) {
|
63
78
|
return defineFacetPayload(inputRuleFacet, [
|
64
79
|
({ schema }) => {
|
65
|
-
|
80
|
+
const nodeType = getNodeType(schema, type);
|
66
81
|
return wrappingInputRule(regex, nodeType, attrs, join);
|
67
82
|
}
|
68
83
|
]);
|
69
84
|
}
|
70
85
|
var inputRuleFacet = defineFacet({
|
71
|
-
reducer: (inputs) =>
|
72
|
-
|
73
|
-
|
86
|
+
reducer: (inputs) => {
|
87
|
+
return (context) => {
|
88
|
+
const rules = inputs.flatMap((callback) => callback(context));
|
89
|
+
return [inputRules({ rules })];
|
90
|
+
};
|
74
91
|
},
|
75
92
|
parent: pluginFacet
|
76
93
|
});
|
@@ -16,24 +16,26 @@ import {
|
|
16
16
|
function defineEnterRule({
|
17
17
|
regex,
|
18
18
|
handler,
|
19
|
-
stop =
|
19
|
+
stop = false
|
20
20
|
}) {
|
21
|
-
|
21
|
+
const rule = new EnterRule(regex, handler, stop);
|
22
22
|
return defineFacetPayload(enterRule, [rule]);
|
23
23
|
}
|
24
24
|
function defineTextBlockEnterRule({
|
25
25
|
regex,
|
26
26
|
type,
|
27
27
|
attrs,
|
28
|
-
stop =
|
28
|
+
stop = true
|
29
29
|
}) {
|
30
30
|
return defineEnterRule({
|
31
31
|
regex,
|
32
32
|
handler: ({ state, from, to, match }) => {
|
33
|
-
|
34
|
-
|
33
|
+
const nodeType = getNodeType(state.schema, type);
|
34
|
+
const $start = state.doc.resolve(from);
|
35
|
+
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) {
|
35
36
|
return null;
|
36
|
-
|
37
|
+
}
|
38
|
+
const nodeAttrs = maybeRun(attrs, match);
|
37
39
|
return state.tr.delete(from, to).setBlockType(from, from, nodeType, nodeAttrs);
|
38
40
|
},
|
39
41
|
stop
|
@@ -45,42 +47,55 @@ var EnterRule = class {
|
|
45
47
|
this.handler = handler;
|
46
48
|
this.stop = stop;
|
47
49
|
}
|
48
|
-
}
|
50
|
+
};
|
51
|
+
var enterRule = defineFacet({
|
49
52
|
reduce: () => {
|
50
|
-
let rules = []
|
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({
|
51
60
|
key: new PluginKey("prosekit-enter-rule"),
|
52
61
|
props: { handleKeyDown: handler }
|
53
62
|
});
|
54
|
-
return function(inputs) {
|
55
|
-
|
63
|
+
return function reducer(inputs) {
|
64
|
+
rules = inputs;
|
65
|
+
return plugin;
|
56
66
|
};
|
57
67
|
},
|
58
68
|
parent: pluginFacet
|
59
69
|
});
|
60
70
|
function execRules(view, rules, dispatch) {
|
61
|
-
if (view.composing) return
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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(
|
67
78
|
Math.max(0, $cursor.parentOffset - MAX_MATCH),
|
68
79
|
$cursor.parentOffset,
|
69
80
|
null,
|
70
81
|
OBJECT_REPLACEMENT_CHARACTER
|
71
82
|
);
|
72
|
-
for (
|
83
|
+
for (const rule of rules) {
|
73
84
|
rule.regex.lastIndex = 0;
|
74
|
-
|
85
|
+
const match = rule.regex.exec(textBefore);
|
86
|
+
const tr = match && rule.handler({
|
75
87
|
state,
|
76
88
|
from: $cursor.pos - match[0].length,
|
77
89
|
to: $cursor.pos,
|
78
90
|
match
|
79
91
|
});
|
80
|
-
if (tr
|
81
|
-
|
92
|
+
if (!tr) continue;
|
93
|
+
dispatch == null ? void 0 : dispatch(tr);
|
94
|
+
if (rule.stop) {
|
95
|
+
return true;
|
96
|
+
}
|
82
97
|
}
|
83
|
-
return
|
98
|
+
return false;
|
84
99
|
}
|
85
100
|
var MAX_MATCH = 200;
|
86
101
|
|
package/dist/list/style.css
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
.prosemirror-flat-list {
|
3
3
|
padding: 0;
|
4
4
|
margin-top: 0;
|
5
|
+
margin-bottom: 0;
|
5
6
|
margin-left: 32px;
|
6
7
|
margin-bottom: 0;
|
7
8
|
position: relative;
|
@@ -14,7 +15,10 @@
|
|
14
15
|
.prosemirror-flat-list.ProseMirror-selectednode:after {
|
15
16
|
content: "";
|
16
17
|
position: absolute;
|
17
|
-
|
18
|
+
left: -32px;
|
19
|
+
right: -2px;
|
20
|
+
top: -2px;
|
21
|
+
bottom: -2px;
|
18
22
|
border: 2px solid #8cf;
|
19
23
|
pointer-events: none;
|
20
24
|
}
|
@@ -27,7 +31,7 @@
|
|
27
31
|
.prosemirror-flat-list[data-list-kind=ordered] > * {
|
28
32
|
contain: style;
|
29
33
|
}
|
30
|
-
.prosemirror-flat-list[data-list-kind=ordered]
|
34
|
+
.prosemirror-flat-list[data-list-kind=ordered]::before {
|
31
35
|
position: absolute;
|
32
36
|
right: 100%;
|
33
37
|
font-variant-numeric: tabular-nums;
|
@@ -65,10 +69,10 @@
|
|
65
69
|
width: 1.5em;
|
66
70
|
width: 1lh;
|
67
71
|
}
|
68
|
-
.prosemirror-flat-list[data-list-kind=toggle] > .list-marker
|
72
|
+
.prosemirror-flat-list[data-list-kind=toggle] > .list-marker::before {
|
69
73
|
content: "\23f7";
|
70
74
|
}
|
71
|
-
.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-marker
|
75
|
+
.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-marker::before {
|
72
76
|
content: "\23f5";
|
73
77
|
}
|
74
78
|
.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable] > .list-marker {
|
@@ -17,9 +17,11 @@ function defaultCanMatch({ state }) {
|
|
17
17
|
return state.selection.empty && !isInsideCode(state.selection.$from);
|
18
18
|
}
|
19
19
|
function isInsideCode($pos) {
|
20
|
-
for (let d = $pos.depth; d > 0; d--)
|
21
|
-
if ($pos.node(d).type.spec.code)
|
22
|
-
return
|
20
|
+
for (let d = $pos.depth; d > 0; d--) {
|
21
|
+
if ($pos.node(d).type.spec.code) {
|
22
|
+
return true;
|
23
|
+
}
|
24
|
+
}
|
23
25
|
return $pos.marks().some((mark) => mark.type.name === "code");
|
24
26
|
}
|
25
27
|
function getPluginState(state) {
|
@@ -42,39 +44,55 @@ function createAutocompletePlugin({
|
|
42
44
|
return new Plugin({
|
43
45
|
key: pluginKey,
|
44
46
|
state: {
|
45
|
-
init: () =>
|
47
|
+
init: () => {
|
48
|
+
return { active: false, ignore: null, matching: null };
|
49
|
+
},
|
46
50
|
apply: (tr, prevValue, oldState, newState) => {
|
47
51
|
var _a;
|
48
|
-
|
49
|
-
if (!tr.docChanged && oldState.selection.eq(newState.selection) && !meta)
|
52
|
+
const meta = getTrMeta(tr);
|
53
|
+
if (!tr.docChanged && oldState.selection.eq(newState.selection) && !meta) {
|
50
54
|
return prevValue;
|
51
|
-
|
55
|
+
}
|
56
|
+
if (meta) {
|
52
57
|
return meta;
|
53
|
-
|
54
|
-
|
58
|
+
}
|
59
|
+
const nextValue = calcPluginState(newState, getRules());
|
60
|
+
if (nextValue.active && prevValue.ignore != null && ((_a = nextValue.matching) == null ? void 0 : _a.from) === prevValue.ignore) {
|
61
|
+
return prevValue;
|
62
|
+
}
|
63
|
+
return nextValue;
|
55
64
|
}
|
56
65
|
},
|
57
66
|
view: () => ({
|
58
67
|
update: (view, prevState) => {
|
59
68
|
var _a, _b, _c;
|
60
|
-
|
61
|
-
|
62
|
-
|
69
|
+
const prevValue = getPluginState(prevState);
|
70
|
+
const currValue = getPluginState(view.state);
|
71
|
+
if ((prevValue == null ? void 0 : prevValue.active) && prevValue.matching && prevValue.matching.rule !== ((_a = currValue == null ? void 0 : currValue.matching) == null ? void 0 : _a.rule)) {
|
72
|
+
(_c = (_b = prevValue.matching.rule).onLeave) == null ? void 0 : _c.call(_b);
|
73
|
+
}
|
74
|
+
if ((currValue == null ? void 0 : currValue.active) && currValue.matching && currValue.matching.from !== currValue.ignore) {
|
75
|
+
const { from, to, match, rule } = currValue.matching;
|
76
|
+
const textContent = view.state.doc.textBetween(
|
63
77
|
from,
|
64
78
|
to,
|
65
79
|
null,
|
66
80
|
OBJECT_REPLACEMENT_CHARACTER
|
67
|
-
)
|
68
|
-
|
81
|
+
);
|
82
|
+
const deleteMatch = () => {
|
83
|
+
if (view.state.doc.textBetween(
|
69
84
|
from,
|
70
85
|
to,
|
71
86
|
null,
|
72
87
|
OBJECT_REPLACEMENT_CHARACTER
|
73
|
-
) === textContent
|
74
|
-
|
88
|
+
) === textContent) {
|
89
|
+
view.dispatch(view.state.tr.delete(from, to));
|
90
|
+
}
|
91
|
+
};
|
92
|
+
const ignoreMatch = () => {
|
75
93
|
view.dispatch(
|
76
94
|
setTrMeta(view.state.tr, {
|
77
|
-
active:
|
95
|
+
active: false,
|
78
96
|
ignore: from,
|
79
97
|
matching: null
|
80
98
|
})
|
@@ -93,9 +111,10 @@ function createAutocompletePlugin({
|
|
93
111
|
}),
|
94
112
|
props: {
|
95
113
|
decorations: (state) => {
|
96
|
-
|
97
|
-
if (pluginState
|
98
|
-
|
114
|
+
const pluginState = getPluginState(state);
|
115
|
+
if ((pluginState == null ? void 0 : pluginState.active) && pluginState.matching) {
|
116
|
+
const { from, to } = pluginState.matching;
|
117
|
+
const deco = Decoration.inline(from, to, {
|
99
118
|
class: "prosemirror-prediction-match"
|
100
119
|
});
|
101
120
|
return DecorationSet.create(state.doc, [deco]);
|
@@ -107,22 +126,26 @@ function createAutocompletePlugin({
|
|
107
126
|
}
|
108
127
|
var MAX_MATCH = 200;
|
109
128
|
function calcPluginState(state, rules) {
|
110
|
-
|
129
|
+
const $pos = state.selection.$from;
|
130
|
+
const parentOffset = $pos.parentOffset;
|
131
|
+
const textBefore = $pos.parent.textBetween(
|
111
132
|
Math.max(0, parentOffset - MAX_MATCH),
|
112
133
|
parentOffset,
|
113
134
|
null,
|
114
135
|
OBJECT_REPLACEMENT_CHARACTER
|
115
136
|
);
|
116
|
-
for (
|
117
|
-
if (!rule.canMatch({ state }))
|
137
|
+
for (const rule of rules) {
|
138
|
+
if (!rule.canMatch({ state })) {
|
118
139
|
continue;
|
140
|
+
}
|
119
141
|
rule.regex.lastIndex = 0;
|
120
|
-
|
121
|
-
if (!match)
|
142
|
+
const match = rule.regex.exec(textBefore);
|
143
|
+
if (!match) {
|
122
144
|
continue;
|
123
|
-
|
145
|
+
}
|
146
|
+
const from = $pos.pos - textBefore.length + match.index;
|
124
147
|
return {
|
125
|
-
active:
|
148
|
+
active: true,
|
126
149
|
ignore: null,
|
127
150
|
matching: {
|
128
151
|
rule,
|
@@ -132,14 +155,17 @@ function calcPluginState(state, rules) {
|
|
132
155
|
}
|
133
156
|
};
|
134
157
|
}
|
135
|
-
return { active:
|
158
|
+
return { active: false, ignore: null, matching: null };
|
136
159
|
}
|
137
160
|
|
138
161
|
// src/autocomplete/rule.ts
|
139
162
|
var AutocompleteRule = class {
|
140
163
|
constructor(options) {
|
141
164
|
var _a;
|
142
|
-
this.regex = options.regex
|
165
|
+
this.regex = options.regex;
|
166
|
+
this.onMatch = options.onEnter;
|
167
|
+
this.onLeave = options.onLeave;
|
168
|
+
this.canMatch = (_a = options.canMatch) != null ? _a : defaultCanMatch;
|
143
169
|
}
|
144
170
|
};
|
145
171
|
|
@@ -149,13 +175,16 @@ function defineAutocomplete(rule) {
|
|
149
175
|
}
|
150
176
|
var autocompleteFacet = defineFacet({
|
151
177
|
reduce: () => {
|
152
|
-
let rules = []
|
153
|
-
|
154
|
-
|
178
|
+
let rules = [];
|
179
|
+
const getRules = () => rules;
|
180
|
+
const plugin = createAutocompletePlugin({ getRules });
|
181
|
+
return function reducer(inputs) {
|
182
|
+
rules = inputs;
|
183
|
+
return plugin;
|
155
184
|
};
|
156
185
|
},
|
157
186
|
parent: pluginFacet,
|
158
|
-
singleton:
|
187
|
+
singleton: true
|
159
188
|
});
|
160
189
|
export {
|
161
190
|
AutocompleteRule,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import {
|
2
2
|
defineWrappingInputRule
|
3
|
-
} from "./chunk-
|
3
|
+
} from "./chunk-LVMTQOWG.js";
|
4
4
|
|
5
5
|
// src/blockquote/index.ts
|
6
6
|
import { defineNodeSpec, union } from "@prosekit/core";
|
@@ -9,7 +9,7 @@ function defineBlockquoteSpec() {
|
|
9
9
|
name: "blockquote",
|
10
10
|
content: "block+",
|
11
11
|
group: "block",
|
12
|
-
defining:
|
12
|
+
defining: true,
|
13
13
|
parseDOM: [{ tag: "blockquote" }],
|
14
14
|
toDOM() {
|
15
15
|
return ["blockquote", 0];
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import {
|
2
2
|
defineMarkInputRule
|
3
|
-
} from "./chunk-
|
3
|
+
} from "./chunk-LVMTQOWG.js";
|
4
4
|
|
5
5
|
// src/bold/index.ts
|
6
6
|
import {
|
@@ -21,12 +21,16 @@ function defineBoldSpec() {
|
|
21
21
|
// tags with a font-weight normal.
|
22
22
|
{
|
23
23
|
tag: "b",
|
24
|
-
getAttrs: (node) =>
|
24
|
+
getAttrs: (node) => {
|
25
|
+
return typeof node !== "string" && node.style.fontWeight !== "normal" && null;
|
26
|
+
}
|
25
27
|
},
|
26
28
|
{ style: "font-weight=400", clearMark: (m) => m.type.name == "strong" },
|
27
29
|
{
|
28
30
|
style: "font-weight",
|
29
|
-
getAttrs: (value) =>
|
31
|
+
getAttrs: (value) => {
|
32
|
+
return typeof value === "string" && /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null;
|
33
|
+
}
|
30
34
|
}
|
31
35
|
],
|
32
36
|
toDOM() {
|