@codemirror/view 6.0.1 → 6.1.0
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/CHANGELOG.md +24 -0
- package/dist/index.cjs +53 -17
- package/dist/index.d.ts +13 -2
- package/dist/index.js +53 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 6.1.0 (2022-07-19)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
`MatchDecorator` now supports a `decorate` option that can be used to customize the way decorations are added for each match.
|
|
6
|
+
|
|
7
|
+
## 6.0.3 (2022-07-08)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix a problem where `posAtCoords` could incorrectly return the start of the next line when querying positions between lines.
|
|
12
|
+
|
|
13
|
+
Fix an issue where registering a high-precedence keymap made keymap handling take precedence over other keydown event handlers.
|
|
14
|
+
|
|
15
|
+
Ctrl/Cmd-clicking can now remove ranges from a multi-range selection.
|
|
16
|
+
|
|
17
|
+
## 6.0.2 (2022-06-23)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
Fix a CSS issue that broke horizontal scroll width stabilization.
|
|
22
|
+
|
|
23
|
+
Fix a bug where `defaultLineHeight` could get an incorrect value in very narrow editors.
|
|
24
|
+
|
|
1
25
|
## 6.0.1 (2022-06-17)
|
|
2
26
|
|
|
3
27
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -2726,6 +2726,7 @@ class DocView extends ContentView {
|
|
|
2726
2726
|
// If no workable line exists, force a layout of a measurable element
|
|
2727
2727
|
let dummy = document.createElement("div"), lineHeight, charWidth;
|
|
2728
2728
|
dummy.className = "cm-line";
|
|
2729
|
+
dummy.style.width = "99999px";
|
|
2729
2730
|
dummy.textContent = "abc def ghi jkl mno pqr stu";
|
|
2730
2731
|
this.view.observer.ignore(() => {
|
|
2731
2732
|
this.dom.appendChild(dummy);
|
|
@@ -3136,7 +3137,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3136
3137
|
let range = doc.caretRangeFromPoint(x, y);
|
|
3137
3138
|
if (range) {
|
|
3138
3139
|
({ startContainer: node, startOffset: offset } = range);
|
|
3139
|
-
if (browser.safari &&
|
|
3140
|
+
if (browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3141
|
+
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
|
|
3140
3142
|
node = undefined;
|
|
3141
3143
|
}
|
|
3142
3144
|
}
|
|
@@ -3163,7 +3165,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
|
3163
3165
|
// the space between lines as belonging to the last character of the
|
|
3164
3166
|
// line before. This is used to detect such a result so that it can be
|
|
3165
3167
|
// ignored (issue #401).
|
|
3166
|
-
function
|
|
3168
|
+
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3167
3169
|
let len;
|
|
3168
3170
|
if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
|
|
3169
3171
|
return false;
|
|
@@ -3172,6 +3174,22 @@ function isSuspiciousCaretResult(node, offset, x) {
|
|
|
3172
3174
|
return false;
|
|
3173
3175
|
return textRange(node, len - 1, len).getBoundingClientRect().left > x;
|
|
3174
3176
|
}
|
|
3177
|
+
// Chrome will move positions between lines to the start of the next line
|
|
3178
|
+
function isSuspiciousChromeCaretResult(node, offset, x) {
|
|
3179
|
+
if (offset != 0)
|
|
3180
|
+
return false;
|
|
3181
|
+
for (let cur = node;;) {
|
|
3182
|
+
let parent = cur.parentNode;
|
|
3183
|
+
if (!parent || parent.nodeType != 1 || parent.firstChild != cur)
|
|
3184
|
+
return false;
|
|
3185
|
+
if (parent.classList.contains("cm-line"))
|
|
3186
|
+
break;
|
|
3187
|
+
cur = parent;
|
|
3188
|
+
}
|
|
3189
|
+
let rect = node.nodeType == 1 ? node.getBoundingClientRect()
|
|
3190
|
+
: textRange(node, 0, Math.max(node.nodeValue.length, 1)).getBoundingClientRect();
|
|
3191
|
+
return x - rect.left > 5;
|
|
3192
|
+
}
|
|
3175
3193
|
function moveToLineBoundary(view, start, forward, includeWrap) {
|
|
3176
3194
|
let line = view.state.doc.lineAt(start.head);
|
|
3177
3195
|
let coords = !includeWrap || !view.lineWrapping ? null
|
|
@@ -3730,6 +3748,8 @@ function basicMouseSelection(view, event) {
|
|
|
3730
3748
|
}
|
|
3731
3749
|
if (extend)
|
|
3732
3750
|
return startSel.replaceRange(startSel.main.extend(range.from, range.to));
|
|
3751
|
+
else if (multiple && startSel.ranges.length > 1 && startSel.ranges.some(r => r.eq(range)))
|
|
3752
|
+
return removeRange(startSel, range);
|
|
3733
3753
|
else if (multiple)
|
|
3734
3754
|
return startSel.addRange(range);
|
|
3735
3755
|
else
|
|
@@ -3737,6 +3757,12 @@ function basicMouseSelection(view, event) {
|
|
|
3737
3757
|
}
|
|
3738
3758
|
};
|
|
3739
3759
|
}
|
|
3760
|
+
function removeRange(sel, range) {
|
|
3761
|
+
for (let i = 0;; i++) {
|
|
3762
|
+
if (sel.ranges[i].eq(range))
|
|
3763
|
+
return state.EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3740
3766
|
handlers.dragstart = (view, event) => {
|
|
3741
3767
|
let { selection: { main } } = view.state;
|
|
3742
3768
|
let { mouseSelection } = view.inputState;
|
|
@@ -5166,6 +5192,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5166
5192
|
".cm-content": {
|
|
5167
5193
|
margin: 0,
|
|
5168
5194
|
flexGrow: 2,
|
|
5195
|
+
flexShrink: 0,
|
|
5169
5196
|
minHeight: "100%",
|
|
5170
5197
|
display: "block",
|
|
5171
5198
|
whiteSpace: "pre",
|
|
@@ -5181,7 +5208,8 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5181
5208
|
whiteSpace_fallback: "pre-wrap",
|
|
5182
5209
|
whiteSpace: "break-spaces",
|
|
5183
5210
|
wordBreak: "break-word",
|
|
5184
|
-
overflowWrap: "anywhere"
|
|
5211
|
+
overflowWrap: "anywhere",
|
|
5212
|
+
flexShrink: 1
|
|
5185
5213
|
},
|
|
5186
5214
|
"&light .cm-content": { caretColor: "black" },
|
|
5187
5215
|
"&dark .cm-content": { caretColor: "white" },
|
|
@@ -5219,8 +5247,8 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5219
5247
|
// Two animations defined so that we can switch between them to
|
|
5220
5248
|
// restart the animation without forcing another style
|
|
5221
5249
|
// recomputation.
|
|
5222
|
-
"@keyframes cm-blink": { "0%": {}, "50%": {
|
|
5223
|
-
"@keyframes cm-blink2": { "0%": {}, "50%": {
|
|
5250
|
+
"@keyframes cm-blink": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5251
|
+
"@keyframes cm-blink2": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5224
5252
|
".cm-cursor, .cm-dropCursor": {
|
|
5225
5253
|
position: "absolute",
|
|
5226
5254
|
borderLeft: "1.2px solid black",
|
|
@@ -6887,11 +6915,11 @@ function modifiers(name, event, shift) {
|
|
|
6887
6915
|
name = "Shift-" + name;
|
|
6888
6916
|
return name;
|
|
6889
6917
|
}
|
|
6890
|
-
const handleKeyEvents = EditorView.domEventHandlers({
|
|
6918
|
+
const handleKeyEvents = state.Prec.default(EditorView.domEventHandlers({
|
|
6891
6919
|
keydown(event, view) {
|
|
6892
6920
|
return runHandlers(getKeymap(view.state), event, view, "editor");
|
|
6893
6921
|
}
|
|
6894
|
-
});
|
|
6922
|
+
}));
|
|
6895
6923
|
/**
|
|
6896
6924
|
Facet used for registering keymaps.
|
|
6897
6925
|
|
|
@@ -7353,7 +7381,7 @@ function iterMatches(doc, re, from, to, f) {
|
|
|
7353
7381
|
for (let cursor = doc.iterRange(from, to), pos = from, m; !cursor.next().done; pos += cursor.value.length) {
|
|
7354
7382
|
if (!cursor.lineBreak)
|
|
7355
7383
|
while (m = re.exec(cursor.value))
|
|
7356
|
-
f(pos + m.index,
|
|
7384
|
+
f(pos + m.index, m);
|
|
7357
7385
|
}
|
|
7358
7386
|
}
|
|
7359
7387
|
function matchRanges(view, maxLength) {
|
|
@@ -7383,11 +7411,20 @@ class MatchDecorator {
|
|
|
7383
7411
|
Create a decorator.
|
|
7384
7412
|
*/
|
|
7385
7413
|
constructor(config) {
|
|
7386
|
-
|
|
7414
|
+
const { regexp, decoration, decorate, boundary, maxLength = 1000 } = config;
|
|
7387
7415
|
if (!regexp.global)
|
|
7388
7416
|
throw new RangeError("The regular expression given to MatchDecorator should have its 'g' flag set");
|
|
7389
7417
|
this.regexp = regexp;
|
|
7390
|
-
|
|
7418
|
+
if (decorate) {
|
|
7419
|
+
this.addMatch = (match, view, from, add) => decorate(add, from, from + match[0].length, match, view);
|
|
7420
|
+
}
|
|
7421
|
+
else if (decoration) {
|
|
7422
|
+
let getDeco = typeof decoration == "function" ? decoration : () => decoration;
|
|
7423
|
+
this.addMatch = (match, view, from, add) => add(from, from + match[0].length, getDeco(match, view, from));
|
|
7424
|
+
}
|
|
7425
|
+
else {
|
|
7426
|
+
throw new RangeError("Either 'decorate' or 'decoration' should be provided to MatchDecorator");
|
|
7427
|
+
}
|
|
7391
7428
|
this.boundary = boundary;
|
|
7392
7429
|
this.maxLength = maxLength;
|
|
7393
7430
|
}
|
|
@@ -7397,9 +7434,9 @@ class MatchDecorator {
|
|
|
7397
7434
|
plugin.
|
|
7398
7435
|
*/
|
|
7399
7436
|
createDeco(view) {
|
|
7400
|
-
let build = new state.RangeSetBuilder();
|
|
7437
|
+
let build = new state.RangeSetBuilder(), add = build.add.bind(build);
|
|
7401
7438
|
for (let { from, to } of matchRanges(view, this.maxLength))
|
|
7402
|
-
iterMatches(view.state.doc, this.regexp, from, to, (
|
|
7439
|
+
iterMatches(view.state.doc, this.regexp, from, to, (from, m) => this.addMatch(m, view, from, add));
|
|
7403
7440
|
return build.finish();
|
|
7404
7441
|
}
|
|
7405
7442
|
/**
|
|
@@ -7441,15 +7478,14 @@ class MatchDecorator {
|
|
|
7441
7478
|
}
|
|
7442
7479
|
}
|
|
7443
7480
|
let ranges = [], m;
|
|
7481
|
+
let add = (from, to, deco) => ranges.push(deco.range(from, to));
|
|
7444
7482
|
if (fromLine == toLine) {
|
|
7445
7483
|
this.regexp.lastIndex = start - fromLine.from;
|
|
7446
|
-
while ((m = this.regexp.exec(fromLine.text)) && m.index < end - fromLine.from)
|
|
7447
|
-
|
|
7448
|
-
ranges.push(this.getDeco(m, view, pos).range(pos, pos + m[0].length));
|
|
7449
|
-
}
|
|
7484
|
+
while ((m = this.regexp.exec(fromLine.text)) && m.index < end - fromLine.from)
|
|
7485
|
+
this.addMatch(m, view, m.index + fromLine.from, add);
|
|
7450
7486
|
}
|
|
7451
7487
|
else {
|
|
7452
|
-
iterMatches(view.state.doc, this.regexp, start, end, (from,
|
|
7488
|
+
iterMatches(view.state.doc, this.regexp, start, end, (from, m) => this.addMatch(m, view, from, add));
|
|
7453
7489
|
}
|
|
7454
7490
|
deco = deco.update({ filterFrom: start, filterTo: end, filter: (from, to) => from < start || to > end, add: ranges });
|
|
7455
7491
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1357,7 +1357,7 @@ represent a matching configuration.
|
|
|
1357
1357
|
*/
|
|
1358
1358
|
declare class MatchDecorator {
|
|
1359
1359
|
private regexp;
|
|
1360
|
-
private
|
|
1360
|
+
private addMatch;
|
|
1361
1361
|
private boundary;
|
|
1362
1362
|
private maxLength;
|
|
1363
1363
|
/**
|
|
@@ -1374,7 +1374,18 @@ declare class MatchDecorator {
|
|
|
1374
1374
|
The decoration to apply to matches, either directly or as a
|
|
1375
1375
|
function of the match.
|
|
1376
1376
|
*/
|
|
1377
|
-
decoration
|
|
1377
|
+
decoration?: Decoration | ((match: RegExpExecArray, view: EditorView, pos: number) => Decoration);
|
|
1378
|
+
/**
|
|
1379
|
+
Customize the way decorations are added for matches. This
|
|
1380
|
+
function, when given, will be called for matches and should
|
|
1381
|
+
call `add` to create decorations for them. Note that the
|
|
1382
|
+
decorations should appear *in* the given range, and the
|
|
1383
|
+
function should have no side effects beyond calling `add`.
|
|
1384
|
+
|
|
1385
|
+
The `decoration` option is ignored when `decorate` is
|
|
1386
|
+
provided.
|
|
1387
|
+
*/
|
|
1388
|
+
decorate?: (add: (from: number, to: number, decoration: Decoration) => void, from: number, to: number, match: RegExpExecArray, view: EditorView) => void;
|
|
1378
1389
|
/**
|
|
1379
1390
|
By default, changed lines are re-matched entirely. You can
|
|
1380
1391
|
provide a boundary expression, which should match single
|
package/dist/index.js
CHANGED
|
@@ -2720,6 +2720,7 @@ class DocView extends ContentView {
|
|
|
2720
2720
|
// If no workable line exists, force a layout of a measurable element
|
|
2721
2721
|
let dummy = document.createElement("div"), lineHeight, charWidth;
|
|
2722
2722
|
dummy.className = "cm-line";
|
|
2723
|
+
dummy.style.width = "99999px";
|
|
2723
2724
|
dummy.textContent = "abc def ghi jkl mno pqr stu";
|
|
2724
2725
|
this.view.observer.ignore(() => {
|
|
2725
2726
|
this.dom.appendChild(dummy);
|
|
@@ -3130,7 +3131,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3130
3131
|
let range = doc.caretRangeFromPoint(x, y);
|
|
3131
3132
|
if (range) {
|
|
3132
3133
|
({ startContainer: node, startOffset: offset } = range);
|
|
3133
|
-
if (browser.safari &&
|
|
3134
|
+
if (browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3135
|
+
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
|
|
3134
3136
|
node = undefined;
|
|
3135
3137
|
}
|
|
3136
3138
|
}
|
|
@@ -3157,7 +3159,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
|
3157
3159
|
// the space between lines as belonging to the last character of the
|
|
3158
3160
|
// line before. This is used to detect such a result so that it can be
|
|
3159
3161
|
// ignored (issue #401).
|
|
3160
|
-
function
|
|
3162
|
+
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3161
3163
|
let len;
|
|
3162
3164
|
if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
|
|
3163
3165
|
return false;
|
|
@@ -3166,6 +3168,22 @@ function isSuspiciousCaretResult(node, offset, x) {
|
|
|
3166
3168
|
return false;
|
|
3167
3169
|
return textRange(node, len - 1, len).getBoundingClientRect().left > x;
|
|
3168
3170
|
}
|
|
3171
|
+
// Chrome will move positions between lines to the start of the next line
|
|
3172
|
+
function isSuspiciousChromeCaretResult(node, offset, x) {
|
|
3173
|
+
if (offset != 0)
|
|
3174
|
+
return false;
|
|
3175
|
+
for (let cur = node;;) {
|
|
3176
|
+
let parent = cur.parentNode;
|
|
3177
|
+
if (!parent || parent.nodeType != 1 || parent.firstChild != cur)
|
|
3178
|
+
return false;
|
|
3179
|
+
if (parent.classList.contains("cm-line"))
|
|
3180
|
+
break;
|
|
3181
|
+
cur = parent;
|
|
3182
|
+
}
|
|
3183
|
+
let rect = node.nodeType == 1 ? node.getBoundingClientRect()
|
|
3184
|
+
: textRange(node, 0, Math.max(node.nodeValue.length, 1)).getBoundingClientRect();
|
|
3185
|
+
return x - rect.left > 5;
|
|
3186
|
+
}
|
|
3169
3187
|
function moveToLineBoundary(view, start, forward, includeWrap) {
|
|
3170
3188
|
let line = view.state.doc.lineAt(start.head);
|
|
3171
3189
|
let coords = !includeWrap || !view.lineWrapping ? null
|
|
@@ -3724,6 +3742,8 @@ function basicMouseSelection(view, event) {
|
|
|
3724
3742
|
}
|
|
3725
3743
|
if (extend)
|
|
3726
3744
|
return startSel.replaceRange(startSel.main.extend(range.from, range.to));
|
|
3745
|
+
else if (multiple && startSel.ranges.length > 1 && startSel.ranges.some(r => r.eq(range)))
|
|
3746
|
+
return removeRange(startSel, range);
|
|
3727
3747
|
else if (multiple)
|
|
3728
3748
|
return startSel.addRange(range);
|
|
3729
3749
|
else
|
|
@@ -3731,6 +3751,12 @@ function basicMouseSelection(view, event) {
|
|
|
3731
3751
|
}
|
|
3732
3752
|
};
|
|
3733
3753
|
}
|
|
3754
|
+
function removeRange(sel, range) {
|
|
3755
|
+
for (let i = 0;; i++) {
|
|
3756
|
+
if (sel.ranges[i].eq(range))
|
|
3757
|
+
return EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3734
3760
|
handlers.dragstart = (view, event) => {
|
|
3735
3761
|
let { selection: { main } } = view.state;
|
|
3736
3762
|
let { mouseSelection } = view.inputState;
|
|
@@ -5159,6 +5185,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5159
5185
|
".cm-content": {
|
|
5160
5186
|
margin: 0,
|
|
5161
5187
|
flexGrow: 2,
|
|
5188
|
+
flexShrink: 0,
|
|
5162
5189
|
minHeight: "100%",
|
|
5163
5190
|
display: "block",
|
|
5164
5191
|
whiteSpace: "pre",
|
|
@@ -5174,7 +5201,8 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5174
5201
|
whiteSpace_fallback: "pre-wrap",
|
|
5175
5202
|
whiteSpace: "break-spaces",
|
|
5176
5203
|
wordBreak: "break-word",
|
|
5177
|
-
overflowWrap: "anywhere"
|
|
5204
|
+
overflowWrap: "anywhere",
|
|
5205
|
+
flexShrink: 1
|
|
5178
5206
|
},
|
|
5179
5207
|
"&light .cm-content": { caretColor: "black" },
|
|
5180
5208
|
"&dark .cm-content": { caretColor: "white" },
|
|
@@ -5212,8 +5240,8 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5212
5240
|
// Two animations defined so that we can switch between them to
|
|
5213
5241
|
// restart the animation without forcing another style
|
|
5214
5242
|
// recomputation.
|
|
5215
|
-
"@keyframes cm-blink": { "0%": {}, "50%": {
|
|
5216
|
-
"@keyframes cm-blink2": { "0%": {}, "50%": {
|
|
5243
|
+
"@keyframes cm-blink": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5244
|
+
"@keyframes cm-blink2": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5217
5245
|
".cm-cursor, .cm-dropCursor": {
|
|
5218
5246
|
position: "absolute",
|
|
5219
5247
|
borderLeft: "1.2px solid black",
|
|
@@ -6880,11 +6908,11 @@ function modifiers(name, event, shift) {
|
|
|
6880
6908
|
name = "Shift-" + name;
|
|
6881
6909
|
return name;
|
|
6882
6910
|
}
|
|
6883
|
-
const handleKeyEvents = /*@__PURE__*/EditorView.domEventHandlers({
|
|
6911
|
+
const handleKeyEvents = /*@__PURE__*/Prec.default(/*@__PURE__*/EditorView.domEventHandlers({
|
|
6884
6912
|
keydown(event, view) {
|
|
6885
6913
|
return runHandlers(getKeymap(view.state), event, view, "editor");
|
|
6886
6914
|
}
|
|
6887
|
-
});
|
|
6915
|
+
}));
|
|
6888
6916
|
/**
|
|
6889
6917
|
Facet used for registering keymaps.
|
|
6890
6918
|
|
|
@@ -7346,7 +7374,7 @@ function iterMatches(doc, re, from, to, f) {
|
|
|
7346
7374
|
for (let cursor = doc.iterRange(from, to), pos = from, m; !cursor.next().done; pos += cursor.value.length) {
|
|
7347
7375
|
if (!cursor.lineBreak)
|
|
7348
7376
|
while (m = re.exec(cursor.value))
|
|
7349
|
-
f(pos + m.index,
|
|
7377
|
+
f(pos + m.index, m);
|
|
7350
7378
|
}
|
|
7351
7379
|
}
|
|
7352
7380
|
function matchRanges(view, maxLength) {
|
|
@@ -7376,11 +7404,20 @@ class MatchDecorator {
|
|
|
7376
7404
|
Create a decorator.
|
|
7377
7405
|
*/
|
|
7378
7406
|
constructor(config) {
|
|
7379
|
-
|
|
7407
|
+
const { regexp, decoration, decorate, boundary, maxLength = 1000 } = config;
|
|
7380
7408
|
if (!regexp.global)
|
|
7381
7409
|
throw new RangeError("The regular expression given to MatchDecorator should have its 'g' flag set");
|
|
7382
7410
|
this.regexp = regexp;
|
|
7383
|
-
|
|
7411
|
+
if (decorate) {
|
|
7412
|
+
this.addMatch = (match, view, from, add) => decorate(add, from, from + match[0].length, match, view);
|
|
7413
|
+
}
|
|
7414
|
+
else if (decoration) {
|
|
7415
|
+
let getDeco = typeof decoration == "function" ? decoration : () => decoration;
|
|
7416
|
+
this.addMatch = (match, view, from, add) => add(from, from + match[0].length, getDeco(match, view, from));
|
|
7417
|
+
}
|
|
7418
|
+
else {
|
|
7419
|
+
throw new RangeError("Either 'decorate' or 'decoration' should be provided to MatchDecorator");
|
|
7420
|
+
}
|
|
7384
7421
|
this.boundary = boundary;
|
|
7385
7422
|
this.maxLength = maxLength;
|
|
7386
7423
|
}
|
|
@@ -7390,9 +7427,9 @@ class MatchDecorator {
|
|
|
7390
7427
|
plugin.
|
|
7391
7428
|
*/
|
|
7392
7429
|
createDeco(view) {
|
|
7393
|
-
let build = new RangeSetBuilder();
|
|
7430
|
+
let build = new RangeSetBuilder(), add = build.add.bind(build);
|
|
7394
7431
|
for (let { from, to } of matchRanges(view, this.maxLength))
|
|
7395
|
-
iterMatches(view.state.doc, this.regexp, from, to, (
|
|
7432
|
+
iterMatches(view.state.doc, this.regexp, from, to, (from, m) => this.addMatch(m, view, from, add));
|
|
7396
7433
|
return build.finish();
|
|
7397
7434
|
}
|
|
7398
7435
|
/**
|
|
@@ -7434,15 +7471,14 @@ class MatchDecorator {
|
|
|
7434
7471
|
}
|
|
7435
7472
|
}
|
|
7436
7473
|
let ranges = [], m;
|
|
7474
|
+
let add = (from, to, deco) => ranges.push(deco.range(from, to));
|
|
7437
7475
|
if (fromLine == toLine) {
|
|
7438
7476
|
this.regexp.lastIndex = start - fromLine.from;
|
|
7439
|
-
while ((m = this.regexp.exec(fromLine.text)) && m.index < end - fromLine.from)
|
|
7440
|
-
|
|
7441
|
-
ranges.push(this.getDeco(m, view, pos).range(pos, pos + m[0].length));
|
|
7442
|
-
}
|
|
7477
|
+
while ((m = this.regexp.exec(fromLine.text)) && m.index < end - fromLine.from)
|
|
7478
|
+
this.addMatch(m, view, m.index + fromLine.from, add);
|
|
7443
7479
|
}
|
|
7444
7480
|
else {
|
|
7445
|
-
iterMatches(view.state.doc, this.regexp, start, end, (from,
|
|
7481
|
+
iterMatches(view.state.doc, this.regexp, start, end, (from, m) => this.addMatch(m, view, from, add));
|
|
7446
7482
|
}
|
|
7447
7483
|
deco = deco.update({ filterFrom: start, filterTo: end, filter: (from, to) => from < start || to > end, add: ranges });
|
|
7448
7484
|
}
|