mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-05 19:42:38 +02:00
add p2p support for HLS https://github.com/Novage/p2p-media-loader
This commit is contained in:
parent
64c36d9f4e
commit
0d0338876d
1197 changed files with 121461 additions and 179724 deletions
86
node_modules/@codemirror/autocomplete/CHANGELOG.md
generated
vendored
86
node_modules/@codemirror/autocomplete/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,89 @@
|
|||
## 6.4.0 (2022-12-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where the extension would sometimes try to draw a disabled dialog at an outdated position, leading to plugin crashes.
|
||||
|
||||
### New features
|
||||
|
||||
A `tooltipClass` option to autocompletion can now be used to add additional CSS classes to the completion tooltip.
|
||||
|
||||
## 6.3.4 (2022-11-24)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where completion lists could end up being higher than the tooltip they were in.
|
||||
|
||||
## 6.3.3 (2022-11-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Set an explicit `box-sizing` style on completion icons so CSS resets don't mess them up.
|
||||
|
||||
Allow closing braces in templates to be escaped with a backslash.
|
||||
|
||||
## 6.3.2 (2022-11-15)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a regression that could cause the completion dialog to stick around when it should be hidden.
|
||||
|
||||
## 6.3.1 (2022-11-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a regression where transactions for picking a completion (without custom `apply` method) no longer had the `pickedCompletion` annotation.
|
||||
|
||||
Reduce flickering for completion sources without `validFor` info by temporarily showing a disabled tooltip while the completion updates.
|
||||
|
||||
Make sure completion info tooltips are kept within the space provided by the `tooltipSpace` option.
|
||||
|
||||
## 6.3.0 (2022-09-22)
|
||||
|
||||
### New features
|
||||
|
||||
Close bracket configuration now supports a `stringPrefixes` property that can be used to allow autoclosing of prefixed strings.
|
||||
|
||||
## 6.2.0 (2022-09-13)
|
||||
|
||||
### New features
|
||||
|
||||
Autocompletion now takes an `interactionDelay` option that can be used to control the delay between the time where completion opens and the time where commands like `acceptCompletion` affect it.
|
||||
|
||||
## 6.1.1 (2022-09-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that prevented transactions produced by `deleteBracketPair` from being marked as deletion user events.
|
||||
|
||||
Improve positioning of completion info tooltips so they are less likely to stick out of the screen on small displays.
|
||||
|
||||
## 6.1.0 (2022-07-19)
|
||||
|
||||
### New features
|
||||
|
||||
You can now provide a `compareCompletions` option to autocompletion to influence the way completions with the same match score are sorted.
|
||||
|
||||
The `selectOnOpen` option to autocompletion can be used to require explicitly selecting a completion option before `acceptCompletion` does anything.
|
||||
|
||||
## 6.0.4 (2022-07-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Remove a leftover `console.log` in bracket closing code.
|
||||
|
||||
## 6.0.3 (2022-07-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused `closeBrackets` to not close quotes when at the end of a syntactic construct that starts with a similar quote.
|
||||
|
||||
## 6.0.2 (2022-06-15)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Declare package dependencies as peer dependencies as an attempt to avoid duplicated package issues.
|
||||
|
||||
## 6.0.1 (2022-06-09)
|
||||
|
||||
### Bug fixes
|
||||
|
|
314
node_modules/@codemirror/autocomplete/dist/index.cjs
generated
vendored
314
node_modules/@codemirror/autocomplete/dist/index.cjs
generated
vendored
|
@ -179,7 +179,7 @@ function applyCompletion(view, option) {
|
|||
const apply = option.completion.apply || option.completion.label;
|
||||
let result = option.source;
|
||||
if (typeof apply == "string")
|
||||
view.dispatch(insertCompletionText(view.state, apply, result.from, result.to));
|
||||
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
||||
else
|
||||
apply(view, option.completion, result.from, result.to);
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ class FuzzyMatcher {
|
|||
if (chars.length == 1) {
|
||||
let first = state.codePointAt(word, 0);
|
||||
return first == chars[0] ? [0, 0, state.codePointSize(first)]
|
||||
: first == folded[0] ? [-200 /* CaseFold */, 0, state.codePointSize(first)] : null;
|
||||
: first == folded[0] ? [-200 /* Penalty.CaseFold */, 0, state.codePointSize(first)] : null;
|
||||
}
|
||||
let direct = word.indexOf(this.pattern);
|
||||
if (direct == 0)
|
||||
|
@ -261,7 +261,7 @@ class FuzzyMatcher {
|
|||
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
||||
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
||||
// Go over the option's text, scanning for the various kinds of matches
|
||||
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
|
||||
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) {
|
||||
let next = state.codePointAt(word, i);
|
||||
if (direct < 0) {
|
||||
if (preciseTo < len && next == chars[preciseTo])
|
||||
|
@ -279,9 +279,9 @@ class FuzzyMatcher {
|
|||
}
|
||||
}
|
||||
let ch, type = next < 0xff
|
||||
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
|
||||
: ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
|
||||
if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
|
||||
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */)
|
||||
: ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */);
|
||||
if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) {
|
||||
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
||||
byWord[byWordTo++] = i;
|
||||
else if (byWord.length)
|
||||
|
@ -291,17 +291,17 @@ class FuzzyMatcher {
|
|||
i += state.codePointSize(next);
|
||||
}
|
||||
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
||||
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
||||
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
|
||||
if (adjacentTo == len && adjacentStart == 0)
|
||||
return [-200 /* CaseFold */ - word.length, 0, adjacentEnd];
|
||||
return [-200 /* Penalty.CaseFold */ - word.length, 0, adjacentEnd];
|
||||
if (direct > -1)
|
||||
return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
|
||||
return [-700 /* Penalty.NotStart */ - word.length, direct, direct + this.pattern.length];
|
||||
if (adjacentTo == len)
|
||||
return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
|
||||
return [-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, adjacentStart, adjacentEnd];
|
||||
if (byWordTo == len)
|
||||
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
||||
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
||||
return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
|
||||
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ +
|
||||
(wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word);
|
||||
return chars.length == 2 ? null : this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word);
|
||||
}
|
||||
result(score, positions, word) {
|
||||
let result = [score - word.length], i = 1;
|
||||
|
@ -322,18 +322,23 @@ const completionConfig = state.Facet.define({
|
|||
combine(configs) {
|
||||
return state.combineConfig(configs, {
|
||||
activateOnTyping: true,
|
||||
selectOnOpen: true,
|
||||
override: null,
|
||||
closeOnBlur: true,
|
||||
maxRenderedOptions: 100,
|
||||
defaultKeymap: true,
|
||||
tooltipClass: () => "",
|
||||
optionClass: () => "",
|
||||
aboveCursor: false,
|
||||
icons: true,
|
||||
addToOptions: []
|
||||
addToOptions: [],
|
||||
compareCompletions: (a, b) => a.label.localeCompare(b.label),
|
||||
interactionDelay: 75
|
||||
}, {
|
||||
defaultKeymap: (a, b) => a && b,
|
||||
closeOnBlur: (a, b) => a && b,
|
||||
icons: (a, b) => a && b,
|
||||
tooltipClass: (a, b) => c => joinClass(a(c), b(c)),
|
||||
optionClass: (a, b) => c => joinClass(a(c), b(c)),
|
||||
addToOptions: (a, b) => a.concat(b)
|
||||
});
|
||||
|
@ -392,6 +397,8 @@ function optionContent(config) {
|
|||
function rangeAroundSelected(total, selected, max) {
|
||||
if (total <= max)
|
||||
return { from: 0, to: total };
|
||||
if (selected < 0)
|
||||
selected = 0;
|
||||
if (selected <= (total >> 1)) {
|
||||
let off = Math.floor(selected / max);
|
||||
return { from: off * max, to: (off + 1) * max };
|
||||
|
@ -409,14 +416,18 @@ class CompletionTooltip {
|
|||
write: (pos) => this.positionInfo(pos),
|
||||
key: this
|
||||
};
|
||||
this.space = null;
|
||||
this.currentClass = "";
|
||||
let cState = view.state.field(stateField);
|
||||
let { options, selected } = cState.open;
|
||||
let config = view.state.facet(completionConfig);
|
||||
this.optionContent = optionContent(config);
|
||||
this.optionClass = config.optionClass;
|
||||
this.tooltipClass = config.tooltipClass;
|
||||
this.range = rangeAroundSelected(options.length, selected, config.maxRenderedOptions);
|
||||
this.dom = document.createElement("div");
|
||||
this.dom.className = "cm-tooltip-autocomplete";
|
||||
this.updateTooltipClass(view.state);
|
||||
this.dom.addEventListener("mousedown", (e) => {
|
||||
for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) {
|
||||
if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) {
|
||||
|
@ -434,16 +445,36 @@ class CompletionTooltip {
|
|||
}
|
||||
mount() { this.updateSel(); }
|
||||
update(update) {
|
||||
if (update.state.field(this.stateField) != update.startState.field(this.stateField))
|
||||
var _a, _b, _c;
|
||||
let cState = update.state.field(this.stateField);
|
||||
let prevState = update.startState.field(this.stateField);
|
||||
this.updateTooltipClass(update.state);
|
||||
if (cState != prevState) {
|
||||
this.updateSel();
|
||||
if (((_a = cState.open) === null || _a === void 0 ? void 0 : _a.disabled) != ((_b = prevState.open) === null || _b === void 0 ? void 0 : _b.disabled))
|
||||
this.dom.classList.toggle("cm-tooltip-autocomplete-disabled", !!((_c = cState.open) === null || _c === void 0 ? void 0 : _c.disabled));
|
||||
}
|
||||
}
|
||||
positioned() {
|
||||
updateTooltipClass(state) {
|
||||
let cls = this.tooltipClass(state);
|
||||
if (cls != this.currentClass) {
|
||||
for (let c of this.currentClass.split(" "))
|
||||
if (c)
|
||||
this.dom.classList.remove(c);
|
||||
for (let c of cls.split(" "))
|
||||
if (c)
|
||||
this.dom.classList.add(c);
|
||||
this.currentClass = cls;
|
||||
}
|
||||
}
|
||||
positioned(space) {
|
||||
this.space = space;
|
||||
if (this.info)
|
||||
this.view.requestMeasure(this.placeInfo);
|
||||
}
|
||||
updateSel() {
|
||||
let cState = this.view.state.field(this.stateField), open = cState.open;
|
||||
if (open.selected < this.range.from || open.selected >= this.range.to) {
|
||||
if (open.selected > -1 && open.selected < this.range.from || open.selected >= this.range.to) {
|
||||
this.range = rangeAroundSelected(open.options.length, open.selected, this.view.state.facet(completionConfig).maxRenderedOptions);
|
||||
this.list.remove();
|
||||
this.list = this.dom.appendChild(this.createListBox(open.options, cState.id, this.range));
|
||||
|
@ -507,23 +538,49 @@ class CompletionTooltip {
|
|||
let listRect = this.dom.getBoundingClientRect();
|
||||
let infoRect = this.info.getBoundingClientRect();
|
||||
let selRect = sel.getBoundingClientRect();
|
||||
if (selRect.top > Math.min(innerHeight, listRect.bottom) - 10 || selRect.bottom < Math.max(0, listRect.top) + 10)
|
||||
let space = this.space;
|
||||
if (!space) {
|
||||
let win = this.dom.ownerDocument.defaultView || window;
|
||||
space = { left: 0, top: 0, right: win.innerWidth, bottom: win.innerHeight };
|
||||
}
|
||||
if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
|
||||
selRect.bottom < Math.max(space.top, listRect.top) + 10)
|
||||
return null;
|
||||
let top = Math.max(0, Math.min(selRect.top, innerHeight - infoRect.height)) - listRect.top;
|
||||
let left = this.view.textDirection == view.Direction.RTL;
|
||||
let spaceLeft = listRect.left, spaceRight = innerWidth - listRect.right;
|
||||
let rtl = this.view.textDirection == view.Direction.RTL, left = rtl, narrow = false, maxWidth;
|
||||
let top = "", bottom = "";
|
||||
let spaceLeft = listRect.left - space.left, spaceRight = space.right - listRect.right;
|
||||
if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
|
||||
left = false;
|
||||
else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
|
||||
left = true;
|
||||
return { top, left };
|
||||
if (infoRect.width <= (left ? spaceLeft : spaceRight)) {
|
||||
top = (Math.max(space.top, Math.min(selRect.top, space.bottom - infoRect.height)) - listRect.top) + "px";
|
||||
maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight) + "px";
|
||||
}
|
||||
else {
|
||||
narrow = true;
|
||||
maxWidth = Math.min(400 /* Info.Width */, (rtl ? listRect.right : space.right - listRect.left) - 30 /* Info.Margin */) + "px";
|
||||
let spaceBelow = space.bottom - listRect.bottom;
|
||||
if (spaceBelow >= infoRect.height || spaceBelow > listRect.top) // Below the completion
|
||||
top = (selRect.bottom - listRect.top) + "px";
|
||||
else // Above it
|
||||
bottom = (listRect.bottom - selRect.top) + "px";
|
||||
}
|
||||
return {
|
||||
top, bottom, maxWidth,
|
||||
class: narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right",
|
||||
};
|
||||
}
|
||||
positionInfo(pos) {
|
||||
if (this.info) {
|
||||
this.info.style.top = (pos ? pos.top : -1e6) + "px";
|
||||
if (pos) {
|
||||
this.info.classList.toggle("cm-completionInfo-left", pos.left);
|
||||
this.info.classList.toggle("cm-completionInfo-right", !pos.left);
|
||||
this.info.style.top = pos.top;
|
||||
this.info.style.bottom = pos.bottom;
|
||||
this.info.style.maxWidth = pos.maxWidth;
|
||||
this.info.className = "cm-tooltip cm-completionInfo cm-completionInfo-" + pos.class;
|
||||
}
|
||||
else {
|
||||
this.info.style.top = "-1e6px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +656,8 @@ function sortOptions(active, state) {
|
|||
}
|
||||
}
|
||||
let result = [], prev = null;
|
||||
for (let opt of options.sort(cmpOption)) {
|
||||
let compare = state.facet(completionConfig).compareCompletions;
|
||||
for (let opt of options.sort((a, b) => (b.match[0] - a.match[0]) || compare(a.completion, b.completion))) {
|
||||
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail ||
|
||||
(prev.type != null && opt.completion.type != null && prev.type != opt.completion.type) ||
|
||||
prev.apply != opt.completion.apply)
|
||||
|
@ -611,23 +669,26 @@ function sortOptions(active, state) {
|
|||
return result;
|
||||
}
|
||||
class CompletionDialog {
|
||||
constructor(options, attrs, tooltip, timestamp, selected) {
|
||||
constructor(options, attrs, tooltip, timestamp, selected, disabled) {
|
||||
this.options = options;
|
||||
this.attrs = attrs;
|
||||
this.tooltip = tooltip;
|
||||
this.timestamp = timestamp;
|
||||
this.selected = selected;
|
||||
this.disabled = disabled;
|
||||
}
|
||||
setSelected(selected, id) {
|
||||
return selected == this.selected || selected >= this.options.length ? this
|
||||
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected);
|
||||
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected, this.disabled);
|
||||
}
|
||||
static build(active, state, id, prev, conf) {
|
||||
let options = sortOptions(active, state);
|
||||
if (!options.length)
|
||||
return null;
|
||||
let selected = 0;
|
||||
if (prev && prev.selected) {
|
||||
if (!options.length) {
|
||||
return prev && active.some(a => a.state == 1 /* State.Pending */) ?
|
||||
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
||||
}
|
||||
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
||||
if (prev && prev.selected != selected && prev.selected != -1) {
|
||||
let selectedValue = prev.options[prev.selected].completion;
|
||||
for (let i = 0; i < options.length; i++)
|
||||
if (options[i].completion == selectedValue) {
|
||||
|
@ -639,10 +700,10 @@ class CompletionDialog {
|
|||
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
||||
create: completionTooltip(completionState),
|
||||
above: conf.aboveCursor,
|
||||
}, prev ? prev.timestamp : Date.now(), selected);
|
||||
}, prev ? prev.timestamp : Date.now(), selected, false);
|
||||
}
|
||||
map(changes) {
|
||||
return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected);
|
||||
return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected, this.disabled);
|
||||
}
|
||||
}
|
||||
class CompletionState {
|
||||
|
@ -660,16 +721,21 @@ class CompletionState {
|
|||
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
||||
let active = sources.map(source => {
|
||||
let value = this.active.find(s => s.source == source) ||
|
||||
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
||||
new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
||||
return value.update(tr, conf);
|
||||
});
|
||||
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
||||
active = this.active;
|
||||
let open = tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
||||
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open, conf)
|
||||
: this.open && tr.docChanged ? this.open.map(tr.changes) : this.open;
|
||||
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
||||
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
||||
let open = this.open;
|
||||
if (open && tr.docChanged)
|
||||
open = open.map(tr.changes);
|
||||
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
||||
!sameResults(active, this.active))
|
||||
open = CompletionDialog.build(active, state, this.id, open, conf);
|
||||
else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */))
|
||||
open = null;
|
||||
if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult()))
|
||||
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a);
|
||||
for (let effect of tr.effects)
|
||||
if (effect.is(setSelectedEffect))
|
||||
open = open && open.setSelected(effect.value, this.id);
|
||||
|
@ -697,20 +763,16 @@ const baseAttrs = {
|
|||
"aria-autocomplete": "list"
|
||||
};
|
||||
function makeAttrs(id, selected) {
|
||||
return {
|
||||
let result = {
|
||||
"aria-autocomplete": "list",
|
||||
"aria-haspopup": "listbox",
|
||||
"aria-activedescendant": id + "-" + selected,
|
||||
"aria-controls": id
|
||||
};
|
||||
if (selected > -1)
|
||||
result["aria-activedescendant"] = id + "-" + selected;
|
||||
return result;
|
||||
}
|
||||
const none = [];
|
||||
function cmpOption(a, b) {
|
||||
let dScore = b.match[0] - a.match[0];
|
||||
if (dScore)
|
||||
return dScore;
|
||||
return a.completion.label.localeCompare(b.completion.label);
|
||||
}
|
||||
function getUserEvent(tr) {
|
||||
return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null;
|
||||
}
|
||||
|
@ -727,13 +789,13 @@ class ActiveSource {
|
|||
value = value.handleUserEvent(tr, event, conf);
|
||||
else if (tr.docChanged)
|
||||
value = value.handleChange(tr);
|
||||
else if (tr.selection && value.state != 0 /* Inactive */)
|
||||
value = new ActiveSource(value.source, 0 /* Inactive */);
|
||||
else if (tr.selection && value.state != 0 /* State.Inactive */)
|
||||
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
||||
for (let effect of tr.effects) {
|
||||
if (effect.is(startCompletionEffect))
|
||||
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
||||
value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
|
||||
else if (effect.is(closeCompletionEffect))
|
||||
value = new ActiveSource(value.source, 0 /* Inactive */);
|
||||
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
||||
else if (effect.is(setActiveEffect))
|
||||
for (let active of effect.value)
|
||||
if (active.source == value.source)
|
||||
|
@ -742,10 +804,10 @@ class ActiveSource {
|
|||
return value;
|
||||
}
|
||||
handleUserEvent(tr, type, conf) {
|
||||
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
||||
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
|
||||
}
|
||||
handleChange(tr) {
|
||||
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
||||
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
||||
}
|
||||
map(changes) {
|
||||
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
||||
|
@ -753,7 +815,7 @@ class ActiveSource {
|
|||
}
|
||||
class ActiveResult extends ActiveSource {
|
||||
constructor(source, explicitPos, result, from, to) {
|
||||
super(source, 2 /* Result */, explicitPos);
|
||||
super(source, 2 /* State.Result */, explicitPos);
|
||||
this.result = result;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
|
@ -766,17 +828,17 @@ class ActiveResult extends ActiveSource {
|
|||
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
||||
pos > to ||
|
||||
type == "delete" && cur(tr.startState) == this.from)
|
||||
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
||||
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
||||
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
||||
if (checkValid(this.result.validFor, tr.state, from, to))
|
||||
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
||||
if (this.result.update &&
|
||||
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
||||
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
||||
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
||||
return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
|
||||
}
|
||||
handleChange(tr) {
|
||||
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
||||
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
||||
}
|
||||
map(mapping) {
|
||||
return mapping.empty ? this :
|
||||
|
@ -804,7 +866,6 @@ const completionState = state.StateField.define({
|
|||
]
|
||||
});
|
||||
|
||||
const CompletionInteractMargin = 75;
|
||||
/**
|
||||
Returns a command that moves the completion selection forward or
|
||||
backward by the given amount.
|
||||
|
@ -812,13 +873,15 @@ backward by the given amount.
|
|||
function moveCompletionSelection(forward, by = "option") {
|
||||
return (view$1) => {
|
||||
let cState = view$1.state.field(completionState, false);
|
||||
if (!cState || !cState.open || Date.now() - cState.open.timestamp < CompletionInteractMargin)
|
||||
if (!cState || !cState.open || cState.open.disabled ||
|
||||
Date.now() - cState.open.timestamp < view$1.state.facet(completionConfig).interactionDelay)
|
||||
return false;
|
||||
let step = 1, tooltip;
|
||||
if (by == "page" && (tooltip = view.getTooltip(view$1, cState.open.tooltip)))
|
||||
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
||||
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
||||
let selected = cState.open.selected + step * (forward ? 1 : -1), { length } = cState.open.options;
|
||||
let { length } = cState.open.options;
|
||||
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
||||
if (selected < 0)
|
||||
selected = by == "page" ? 0 : length - 1;
|
||||
else if (selected >= length)
|
||||
|
@ -832,9 +895,11 @@ Accept the current completion.
|
|||
*/
|
||||
const acceptCompletion = (view) => {
|
||||
let cState = view.state.field(completionState, false);
|
||||
if (view.state.readOnly || !cState || !cState.open || Date.now() - cState.open.timestamp < CompletionInteractMargin)
|
||||
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
|
||||
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
||||
return false;
|
||||
applyCompletion(view, cState.open.options[cState.open.selected]);
|
||||
if (!cState.open.disabled)
|
||||
applyCompletion(view, cState.open.options[cState.open.selected]);
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
|
@ -852,7 +917,7 @@ Close the currently active completion.
|
|||
*/
|
||||
const closeCompletion = (view) => {
|
||||
let cState = view.state.field(completionState, false);
|
||||
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
||||
if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
|
||||
return false;
|
||||
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
||||
return true;
|
||||
|
@ -875,9 +940,9 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|||
this.debounceUpdate = -1;
|
||||
this.running = [];
|
||||
this.debounceAccept = -1;
|
||||
this.composing = 0 /* None */;
|
||||
this.composing = 0 /* CompositionState.None */;
|
||||
for (let active of view.state.field(completionState).active)
|
||||
if (active.state == 1 /* Pending */)
|
||||
if (active.state == 1 /* State.Pending */)
|
||||
this.startQuery(active);
|
||||
}
|
||||
update(update) {
|
||||
|
@ -908,21 +973,21 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|||
}
|
||||
if (this.debounceUpdate > -1)
|
||||
clearTimeout(this.debounceUpdate);
|
||||
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
||||
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
|
||||
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
||||
if (this.composing != 0 /* None */)
|
||||
if (this.composing != 0 /* CompositionState.None */)
|
||||
for (let tr of update.transactions) {
|
||||
if (getUserEvent(tr) == "input")
|
||||
this.composing = 2 /* Changed */;
|
||||
else if (this.composing == 2 /* Changed */ && tr.selection)
|
||||
this.composing = 3 /* ChangedAndMoved */;
|
||||
this.composing = 2 /* CompositionState.Changed */;
|
||||
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
|
||||
this.composing = 3 /* CompositionState.ChangedAndMoved */;
|
||||
}
|
||||
}
|
||||
startUpdate() {
|
||||
this.debounceUpdate = -1;
|
||||
let { state } = this.view, cState = state.field(completionState);
|
||||
for (let active of cState.active) {
|
||||
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
||||
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
|
||||
this.startQuery(active);
|
||||
}
|
||||
}
|
||||
|
@ -973,14 +1038,14 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|||
}
|
||||
}
|
||||
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
||||
if (current && current.state == 1 /* Pending */) {
|
||||
if (current && current.state == 1 /* State.Pending */) {
|
||||
if (query.done == null) {
|
||||
// Explicitly failed. Should clear the pending status if it
|
||||
// hasn't been re-set in the meantime.
|
||||
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
||||
let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
|
||||
for (let tr of query.updates)
|
||||
active = active.update(tr, conf);
|
||||
if (active.state != 1 /* Pending */)
|
||||
if (active.state != 1 /* State.Pending */)
|
||||
updated.push(active);
|
||||
}
|
||||
else {
|
||||
|
@ -1000,15 +1065,15 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|||
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
||||
},
|
||||
compositionstart() {
|
||||
this.composing = 1 /* Started */;
|
||||
this.composing = 1 /* CompositionState.Started */;
|
||||
},
|
||||
compositionend() {
|
||||
if (this.composing == 3 /* ChangedAndMoved */) {
|
||||
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
|
||||
// Safari fires compositionend events synchronously, possibly
|
||||
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
||||
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
||||
}
|
||||
this.composing = 0 /* None */;
|
||||
this.composing = 0 /* CompositionState.None */;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1023,6 +1088,7 @@ const baseTheme = view.EditorView.baseTheme({
|
|||
maxWidth: "min(700px, 95vw)",
|
||||
minWidth: "250px",
|
||||
maxHeight: "10em",
|
||||
height: "100%",
|
||||
listStyle: "none",
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
|
@ -1039,10 +1105,16 @@ const baseTheme = view.EditorView.baseTheme({
|
|||
background: "#17c",
|
||||
color: "white",
|
||||
},
|
||||
"&light .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
|
||||
background: "#777",
|
||||
},
|
||||
"&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
|
||||
background: "#347",
|
||||
color: "white",
|
||||
},
|
||||
"&dark .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
|
||||
background: "#444",
|
||||
},
|
||||
".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
|
||||
content: '"···"',
|
||||
opacity: 0.5,
|
||||
|
@ -1053,16 +1125,20 @@ const baseTheme = view.EditorView.baseTheme({
|
|||
position: "absolute",
|
||||
padding: "3px 9px",
|
||||
width: "max-content",
|
||||
maxWidth: "300px",
|
||||
maxWidth: `${400 /* Info.Width */}px`,
|
||||
boxSizing: "border-box"
|
||||
},
|
||||
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
||||
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
||||
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
|
||||
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
|
||||
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
||||
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
||||
".cm-snippetFieldPosition": {
|
||||
verticalAlign: "text-top",
|
||||
width: 0,
|
||||
height: "1.15em",
|
||||
display: "inline-block",
|
||||
margin: "0 -0.7px -.7em",
|
||||
borderLeft: "1.4px dotted #888"
|
||||
},
|
||||
|
@ -1079,7 +1155,8 @@ const baseTheme = view.EditorView.baseTheme({
|
|||
display: "inline-block",
|
||||
textAlign: "center",
|
||||
paddingRight: ".6em",
|
||||
opacity: "0.6"
|
||||
opacity: "0.6",
|
||||
boxSizing: "content-box"
|
||||
},
|
||||
".cm-completionIcon-function, .cm-completionIcon-method": {
|
||||
"&:after": { content: "'ƒ'" }
|
||||
|
@ -1181,8 +1258,8 @@ class Snippet {
|
|||
positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length));
|
||||
line = line.slice(0, m.index) + name + line.slice(m.index + m[0].length);
|
||||
}
|
||||
for (let esc; esc = /([$#])\\{/.exec(line);) {
|
||||
line = line.slice(0, esc.index) + esc[1] + "{" + line.slice(esc.index + esc[0].length);
|
||||
for (let esc; esc = /\\([{}])/.exec(line);) {
|
||||
line = line.slice(0, esc.index) + esc[1] + line.slice(esc.index + esc[0].length);
|
||||
for (let pos of positions)
|
||||
if (pos.line == lines.length && pos.from > esc.index) {
|
||||
pos.from--;
|
||||
|
@ -1273,10 +1350,9 @@ The order of fields defaults to textual order, but you can add
|
|||
numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
|
||||
a custom order.
|
||||
|
||||
To include a literal `${` or `#{` in your template, put a
|
||||
backslash after the dollar or hash and before the brace (`$\\{`).
|
||||
This will be removed and the sequence will not be interpreted as a
|
||||
placeholder.
|
||||
To include a literal `{` or `}` in your template, put a backslash
|
||||
in front of it. This will be removed and the brace will not be
|
||||
interpreted as indicating a placeholder.
|
||||
*/
|
||||
function snippet(template) {
|
||||
let snippet = Snippet.parse(template);
|
||||
|
@ -1391,7 +1467,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|||
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
||||
result.push({ type: "text", label: m[0] });
|
||||
seen[m[0]] = true;
|
||||
if (result.length >= 2000 /* MaxList */)
|
||||
if (result.length >= 2000 /* C.MaxList */)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1399,7 +1475,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|||
}
|
||||
}
|
||||
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
||||
let big = doc.length >= 1000 /* MinCacheLen */;
|
||||
let big = doc.length >= 1000 /* C.MinCacheLen */;
|
||||
let cached = big && cache.get(doc);
|
||||
if (cached)
|
||||
return cached;
|
||||
|
@ -1407,7 +1483,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|||
if (doc.children) {
|
||||
let pos = 0;
|
||||
for (let ch of doc.children) {
|
||||
if (ch.length >= 1000 /* MinCacheLen */) {
|
||||
if (ch.length >= 1000 /* C.MinCacheLen */) {
|
||||
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
||||
if (!seen[c.label]) {
|
||||
seen[c.label] = true;
|
||||
|
@ -1424,7 +1500,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|||
else {
|
||||
storeWords(doc, wordRE, result, seen, ignoreAt);
|
||||
}
|
||||
if (big && result.length < 2000 /* MaxList */)
|
||||
if (big && result.length < 2000 /* C.MaxList */)
|
||||
cache.set(doc, result);
|
||||
return result;
|
||||
}
|
||||
|
@ -1440,13 +1516,14 @@ const completeAnyWord = context => {
|
|||
if (!token && !context.explicit)
|
||||
return null;
|
||||
let from = token ? token.from : context.pos;
|
||||
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
||||
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from);
|
||||
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
||||
};
|
||||
|
||||
const defaults = {
|
||||
brackets: ["(", "[", "{", "'", '"'],
|
||||
before: ")]}:;>"
|
||||
before: ")]}:;>",
|
||||
stringPrefixes: []
|
||||
};
|
||||
const closeBracketEffect = state.StateEffect.define({
|
||||
map(value, mapping) {
|
||||
|
@ -1529,14 +1606,13 @@ const deleteBracketPair = ({ state: state$1, dispatch }) => {
|
|||
for (let token of tokens) {
|
||||
if (token == before && nextChar(state$1.doc, range.head) == closing(state.codePointAt(token, 0)))
|
||||
return { changes: { from: range.head - token.length, to: range.head + token.length },
|
||||
range: state.EditorSelection.cursor(range.head - token.length),
|
||||
userEvent: "delete.backward" };
|
||||
range: state.EditorSelection.cursor(range.head - token.length) };
|
||||
}
|
||||
}
|
||||
return { range: dont = range };
|
||||
});
|
||||
if (!dont)
|
||||
dispatch(state$1.update(changes, { scrollIntoView: true }));
|
||||
dispatch(state$1.update(changes, { scrollIntoView: true, userEvent: "delete.backward" }));
|
||||
return !dont;
|
||||
};
|
||||
/**
|
||||
|
@ -1563,7 +1639,7 @@ function insertBracket(state$1, bracket) {
|
|||
for (let tok of tokens) {
|
||||
let closed = closing(state.codePointAt(tok, 0));
|
||||
if (bracket == tok)
|
||||
return closed == tok ? handleSame(state$1, tok, tokens.indexOf(tok + tok + tok) > -1)
|
||||
return closed == tok ? handleSame(state$1, tok, tokens.indexOf(tok + tok + tok) > -1, conf)
|
||||
: handleOpen(state$1, tok, closed, conf.before || defaults.before);
|
||||
if (bracket == closed && closedBracketAt(state$1, state$1.selection.main.from))
|
||||
return handleClose(state$1, tok, closed);
|
||||
|
@ -1618,13 +1694,14 @@ function handleClose(state$1, _open, close) {
|
|||
}
|
||||
// Handles cases where the open and close token are the same, and
|
||||
// possibly triple quotes (as in `"""abc"""`-style quoting).
|
||||
function handleSame(state$1, token, allowTriple) {
|
||||
function handleSame(state$1, token, allowTriple, config) {
|
||||
let stringPrefixes = config.stringPrefixes || defaults.stringPrefixes;
|
||||
let dont = null, changes = state$1.changeByRange(range => {
|
||||
if (!range.empty)
|
||||
return { changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }],
|
||||
effects: closeBracketEffect.of(range.to + token.length),
|
||||
range: state.EditorSelection.range(range.anchor + token.length, range.head + token.length) };
|
||||
let pos = range.head, next = nextChar(state$1.doc, pos);
|
||||
let pos = range.head, next = nextChar(state$1.doc, pos), start;
|
||||
if (next == token) {
|
||||
if (nodeStart(state$1, pos)) {
|
||||
return { changes: { insert: token + token, from: pos },
|
||||
|
@ -1638,14 +1715,14 @@ function handleSame(state$1, token, allowTriple) {
|
|||
}
|
||||
}
|
||||
else if (allowTriple && state$1.sliceDoc(pos - 2 * token.length, pos) == token + token &&
|
||||
nodeStart(state$1, pos - 2 * token.length)) {
|
||||
(start = canStartStringAt(state$1, pos - 2 * token.length, stringPrefixes)) > -1 &&
|
||||
nodeStart(state$1, start)) {
|
||||
return { changes: { insert: token + token + token + token, from: pos },
|
||||
effects: closeBracketEffect.of(pos + token.length),
|
||||
range: state.EditorSelection.cursor(pos + token.length) };
|
||||
}
|
||||
else if (state$1.charCategorizer(pos)(next) != state.CharCategory.Word) {
|
||||
let prev = state$1.sliceDoc(pos - 1, pos);
|
||||
if (prev != token && state$1.charCategorizer(pos)(prev) != state.CharCategory.Word && !probablyInString(state$1, pos, token))
|
||||
if (canStartStringAt(state$1, pos, stringPrefixes) > -1 && !probablyInString(state$1, pos, token, stringPrefixes))
|
||||
return { changes: { insert: token + token, from: pos },
|
||||
effects: closeBracketEffect.of(pos + token.length),
|
||||
range: state.EditorSelection.cursor(pos + token.length) };
|
||||
|
@ -1661,11 +1738,21 @@ function nodeStart(state, pos) {
|
|||
let tree = language.syntaxTree(state).resolveInner(pos + 1);
|
||||
return tree.parent && tree.from == pos;
|
||||
}
|
||||
function probablyInString(state, pos, quoteToken) {
|
||||
function probablyInString(state, pos, quoteToken, prefixes) {
|
||||
let node = language.syntaxTree(state).resolveInner(pos, -1);
|
||||
let maxPrefix = prefixes.reduce((m, p) => Math.max(m, p.length), 0);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (state.sliceDoc(node.from, node.from + quoteToken.length) == quoteToken)
|
||||
let start = state.sliceDoc(node.from, Math.min(node.to, node.from + quoteToken.length + maxPrefix));
|
||||
let quotePos = start.indexOf(quoteToken);
|
||||
if (!quotePos || quotePos > -1 && prefixes.indexOf(start.slice(0, quotePos)) > -1) {
|
||||
let first = node.firstChild;
|
||||
while (first && first.from == node.from && first.to - first.from > quoteToken.length + quotePos) {
|
||||
if (state.sliceDoc(first.to - quoteToken.length, first.to) == quoteToken)
|
||||
return false;
|
||||
first = first.firstChild;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
let parent = node.to == pos && node.parent;
|
||||
if (!parent)
|
||||
break;
|
||||
|
@ -1673,6 +1760,17 @@ function probablyInString(state, pos, quoteToken) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
function canStartStringAt(state$1, pos, prefixes) {
|
||||
let charCat = state$1.charCategorizer(pos);
|
||||
if (charCat(state$1.sliceDoc(pos - 1, pos)) != state.CharCategory.Word)
|
||||
return pos;
|
||||
for (let prefix of prefixes) {
|
||||
let start = pos - prefix.length;
|
||||
if (state$1.sliceDoc(start, pos) == prefix && charCat(state$1.sliceDoc(start - 1, start)) != state.CharCategory.Word)
|
||||
return start;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an extension that enables autocompletion.
|
||||
|
@ -1715,8 +1813,8 @@ returns `null`.
|
|||
*/
|
||||
function completionStatus(state) {
|
||||
let cState = state.field(completionState, false);
|
||||
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
||||
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
||||
return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
|
||||
: cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
|
||||
}
|
||||
const completionArrayCache = new WeakMap;
|
||||
/**
|
||||
|
@ -1725,7 +1823,7 @@ Returns the available completions as an array.
|
|||
function currentCompletions(state) {
|
||||
var _a;
|
||||
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
||||
if (!open)
|
||||
if (!open || open.disabled)
|
||||
return [];
|
||||
let completions = completionArrayCache.get(open.options);
|
||||
if (!completions)
|
||||
|
@ -1738,7 +1836,7 @@ Return the currently selected completion, if any.
|
|||
function selectedCompletion(state) {
|
||||
var _a;
|
||||
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
||||
return open ? open.options[open.selected].completion : null;
|
||||
return open && !open.disabled && open.selected >= 0 ? open.options[open.selected].completion : null;
|
||||
}
|
||||
/**
|
||||
Returns the currently selected position in the active completion
|
||||
|
@ -1747,7 +1845,7 @@ list, or null if no completions are active.
|
|||
function selectedCompletionIndex(state) {
|
||||
var _a;
|
||||
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
||||
return open ? open.selected : null;
|
||||
return open && !open.disabled && open.selected >= 0 ? open.selected : null;
|
||||
}
|
||||
/**
|
||||
Create an effect that can be attached to a transaction to change
|
||||
|
|
42
node_modules/@codemirror/autocomplete/dist/index.d.ts
generated
vendored
42
node_modules/@codemirror/autocomplete/dist/index.d.ts
generated
vendored
|
@ -10,6 +10,15 @@ interface CompletionConfig {
|
|||
*/
|
||||
activateOnTyping?: boolean;
|
||||
/**
|
||||
By default, when completion opens, the first option is selected
|
||||
and can be confirmed with
|
||||
[`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion). When this
|
||||
is set to false, the completion widget starts with no completion
|
||||
selected, and the user has to explicitly move to a completion
|
||||
before you can confirm one.
|
||||
*/
|
||||
selectOnOpen?: boolean;
|
||||
/**
|
||||
Override the completion sources used. By default, they will be
|
||||
taken from the `"autocomplete"` [language
|
||||
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) (which should hold
|
||||
|
@ -41,6 +50,11 @@ interface CompletionConfig {
|
|||
*/
|
||||
aboveCursor?: boolean;
|
||||
/**
|
||||
When given, this may return an additional CSS class to add to
|
||||
the completion dialog element.
|
||||
*/
|
||||
tooltipClass?: (state: EditorState) => string;
|
||||
/**
|
||||
This can be used to add additional CSS classes to completion
|
||||
options.
|
||||
*/
|
||||
|
@ -57,12 +71,26 @@ interface CompletionConfig {
|
|||
completion, and should produce a DOM node to show. `position`
|
||||
determines where in the DOM the result appears, relative to
|
||||
other added widgets and the standard content. The default icons
|
||||
have position 20, the label position 50, and the detail position 70.
|
||||
have position 20, the label position 50, and the detail position
|
||||
80.
|
||||
*/
|
||||
addToOptions?: {
|
||||
render: (completion: Completion, state: EditorState) => Node | null;
|
||||
position: number;
|
||||
}[];
|
||||
/**
|
||||
The comparison function to use when sorting completions with the same
|
||||
match score. Defaults to using
|
||||
[`localeCompare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare).
|
||||
*/
|
||||
compareCompletions?: (a: Completion, b: Completion) => number;
|
||||
/**
|
||||
By default, commands relating to an open completion only take
|
||||
effect 75 milliseconds after the completion opened, so that key
|
||||
presses made before the user is aware of the tooltip don't go to
|
||||
the tooltip. This option can be used to configure that delay.
|
||||
*/
|
||||
interactionDelay?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -303,10 +331,9 @@ The order of fields defaults to textual order, but you can add
|
|||
numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
|
||||
a custom order.
|
||||
|
||||
To include a literal `${` or `#{` in your template, put a
|
||||
backslash after the dollar or hash and before the brace (`$\\{`).
|
||||
This will be removed and the sequence will not be interpreted as a
|
||||
placeholder.
|
||||
To include a literal `{` or `}` in your template, put a backslash
|
||||
in front of it. This will be removed and the brace will not be
|
||||
interpreted as indicating a placeholder.
|
||||
*/
|
||||
declare function snippet(template: string): (editor: {
|
||||
state: EditorState;
|
||||
|
@ -382,6 +409,11 @@ interface CloseBracketConfig {
|
|||
whitespace. Defaults to `")]}:;>"`.
|
||||
*/
|
||||
before?: string;
|
||||
/**
|
||||
When determining whether a given node may be a string, recognize
|
||||
these prefixes before the opening quote.
|
||||
*/
|
||||
stringPrefixes?: string[];
|
||||
}
|
||||
/**
|
||||
Extension to enable bracket-closing behavior. When a closeable
|
||||
|
|
314
node_modules/@codemirror/autocomplete/dist/index.js
generated
vendored
314
node_modules/@codemirror/autocomplete/dist/index.js
generated
vendored
|
@ -175,7 +175,7 @@ function applyCompletion(view, option) {
|
|||
const apply = option.completion.apply || option.completion.label;
|
||||
let result = option.source;
|
||||
if (typeof apply == "string")
|
||||
view.dispatch(insertCompletionText(view.state, apply, result.from, result.to));
|
||||
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
||||
else
|
||||
apply(view, option.completion, result.from, result.to);
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ class FuzzyMatcher {
|
|||
if (chars.length == 1) {
|
||||
let first = codePointAt(word, 0);
|
||||
return first == chars[0] ? [0, 0, codePointSize(first)]
|
||||
: first == folded[0] ? [-200 /* CaseFold */, 0, codePointSize(first)] : null;
|
||||
: first == folded[0] ? [-200 /* Penalty.CaseFold */, 0, codePointSize(first)] : null;
|
||||
}
|
||||
let direct = word.indexOf(this.pattern);
|
||||
if (direct == 0)
|
||||
|
@ -257,7 +257,7 @@ class FuzzyMatcher {
|
|||
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
||||
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
||||
// Go over the option's text, scanning for the various kinds of matches
|
||||
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
|
||||
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) {
|
||||
let next = codePointAt(word, i);
|
||||
if (direct < 0) {
|
||||
if (preciseTo < len && next == chars[preciseTo])
|
||||
|
@ -275,9 +275,9 @@ class FuzzyMatcher {
|
|||
}
|
||||
}
|
||||
let ch, type = next < 0xff
|
||||
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
|
||||
: ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
|
||||
if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
|
||||
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */)
|
||||
: ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */);
|
||||
if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) {
|
||||
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
||||
byWord[byWordTo++] = i;
|
||||
else if (byWord.length)
|
||||
|
@ -287,17 +287,17 @@ class FuzzyMatcher {
|
|||
i += codePointSize(next);
|
||||
}
|
||||
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
||||
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
||||
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
|
||||
if (adjacentTo == len && adjacentStart == 0)
|
||||
return [-200 /* CaseFold */ - word.length, 0, adjacentEnd];
|
||||
return [-200 /* Penalty.CaseFold */ - word.length, 0, adjacentEnd];
|
||||
if (direct > -1)
|
||||
return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
|
||||
return [-700 /* Penalty.NotStart */ - word.length, direct, direct + this.pattern.length];
|
||||
if (adjacentTo == len)
|
||||
return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
|
||||
return [-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, adjacentStart, adjacentEnd];
|
||||
if (byWordTo == len)
|
||||
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
||||
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
||||
return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
|
||||
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ +
|
||||
(wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word);
|
||||
return chars.length == 2 ? null : this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word);
|
||||
}
|
||||
result(score, positions, word) {
|
||||
let result = [score - word.length], i = 1;
|
||||
|
@ -318,18 +318,23 @@ const completionConfig = /*@__PURE__*/Facet.define({
|
|||
combine(configs) {
|
||||
return combineConfig(configs, {
|
||||
activateOnTyping: true,
|
||||
selectOnOpen: true,
|
||||
override: null,
|
||||
closeOnBlur: true,
|
||||
maxRenderedOptions: 100,
|
||||
defaultKeymap: true,
|
||||
tooltipClass: () => "",
|
||||
optionClass: () => "",
|
||||
aboveCursor: false,
|
||||
icons: true,
|
||||
addToOptions: []
|
||||
addToOptions: [],
|
||||
compareCompletions: (a, b) => a.label.localeCompare(b.label),
|
||||
interactionDelay: 75
|
||||
}, {
|
||||
defaultKeymap: (a, b) => a && b,
|
||||
closeOnBlur: (a, b) => a && b,
|
||||
icons: (a, b) => a && b,
|
||||
tooltipClass: (a, b) => c => joinClass(a(c), b(c)),
|
||||
optionClass: (a, b) => c => joinClass(a(c), b(c)),
|
||||
addToOptions: (a, b) => a.concat(b)
|
||||
});
|
||||
|
@ -388,6 +393,8 @@ function optionContent(config) {
|
|||
function rangeAroundSelected(total, selected, max) {
|
||||
if (total <= max)
|
||||
return { from: 0, to: total };
|
||||
if (selected < 0)
|
||||
selected = 0;
|
||||
if (selected <= (total >> 1)) {
|
||||
let off = Math.floor(selected / max);
|
||||
return { from: off * max, to: (off + 1) * max };
|
||||
|
@ -405,14 +412,18 @@ class CompletionTooltip {
|
|||
write: (pos) => this.positionInfo(pos),
|
||||
key: this
|
||||
};
|
||||
this.space = null;
|
||||
this.currentClass = "";
|
||||
let cState = view.state.field(stateField);
|
||||
let { options, selected } = cState.open;
|
||||
let config = view.state.facet(completionConfig);
|
||||
this.optionContent = optionContent(config);
|
||||
this.optionClass = config.optionClass;
|
||||
this.tooltipClass = config.tooltipClass;
|
||||
this.range = rangeAroundSelected(options.length, selected, config.maxRenderedOptions);
|
||||
this.dom = document.createElement("div");
|
||||
this.dom.className = "cm-tooltip-autocomplete";
|
||||
this.updateTooltipClass(view.state);
|
||||
this.dom.addEventListener("mousedown", (e) => {
|
||||
for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) {
|
||||
if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) {
|
||||
|
@ -430,16 +441,36 @@ class CompletionTooltip {
|
|||
}
|
||||
mount() { this.updateSel(); }
|
||||
update(update) {
|
||||
if (update.state.field(this.stateField) != update.startState.field(this.stateField))
|
||||
var _a, _b, _c;
|
||||
let cState = update.state.field(this.stateField);
|
||||
let prevState = update.startState.field(this.stateField);
|
||||
this.updateTooltipClass(update.state);
|
||||
if (cState != prevState) {
|
||||
this.updateSel();
|
||||
if (((_a = cState.open) === null || _a === void 0 ? void 0 : _a.disabled) != ((_b = prevState.open) === null || _b === void 0 ? void 0 : _b.disabled))
|
||||
this.dom.classList.toggle("cm-tooltip-autocomplete-disabled", !!((_c = cState.open) === null || _c === void 0 ? void 0 : _c.disabled));
|
||||
}
|
||||
}
|
||||
positioned() {
|
||||
updateTooltipClass(state) {
|
||||
let cls = this.tooltipClass(state);
|
||||
if (cls != this.currentClass) {
|
||||
for (let c of this.currentClass.split(" "))
|
||||
if (c)
|
||||
this.dom.classList.remove(c);
|
||||
for (let c of cls.split(" "))
|
||||
if (c)
|
||||
this.dom.classList.add(c);
|
||||
this.currentClass = cls;
|
||||
}
|
||||
}
|
||||
positioned(space) {
|
||||
this.space = space;
|
||||
if (this.info)
|
||||
this.view.requestMeasure(this.placeInfo);
|
||||
}
|
||||
updateSel() {
|
||||
let cState = this.view.state.field(this.stateField), open = cState.open;
|
||||
if (open.selected < this.range.from || open.selected >= this.range.to) {
|
||||
if (open.selected > -1 && open.selected < this.range.from || open.selected >= this.range.to) {
|
||||
this.range = rangeAroundSelected(open.options.length, open.selected, this.view.state.facet(completionConfig).maxRenderedOptions);
|
||||
this.list.remove();
|
||||
this.list = this.dom.appendChild(this.createListBox(open.options, cState.id, this.range));
|
||||
|
@ -503,23 +534,49 @@ class CompletionTooltip {
|
|||
let listRect = this.dom.getBoundingClientRect();
|
||||
let infoRect = this.info.getBoundingClientRect();
|
||||
let selRect = sel.getBoundingClientRect();
|
||||
if (selRect.top > Math.min(innerHeight, listRect.bottom) - 10 || selRect.bottom < Math.max(0, listRect.top) + 10)
|
||||
let space = this.space;
|
||||
if (!space) {
|
||||
let win = this.dom.ownerDocument.defaultView || window;
|
||||
space = { left: 0, top: 0, right: win.innerWidth, bottom: win.innerHeight };
|
||||
}
|
||||
if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
|
||||
selRect.bottom < Math.max(space.top, listRect.top) + 10)
|
||||
return null;
|
||||
let top = Math.max(0, Math.min(selRect.top, innerHeight - infoRect.height)) - listRect.top;
|
||||
let left = this.view.textDirection == Direction.RTL;
|
||||
let spaceLeft = listRect.left, spaceRight = innerWidth - listRect.right;
|
||||
let rtl = this.view.textDirection == Direction.RTL, left = rtl, narrow = false, maxWidth;
|
||||
let top = "", bottom = "";
|
||||
let spaceLeft = listRect.left - space.left, spaceRight = space.right - listRect.right;
|
||||
if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
|
||||
left = false;
|
||||
else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
|
||||
left = true;
|
||||
return { top, left };
|
||||
if (infoRect.width <= (left ? spaceLeft : spaceRight)) {
|
||||
top = (Math.max(space.top, Math.min(selRect.top, space.bottom - infoRect.height)) - listRect.top) + "px";
|
||||
maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight) + "px";
|
||||
}
|
||||
else {
|
||||
narrow = true;
|
||||
maxWidth = Math.min(400 /* Info.Width */, (rtl ? listRect.right : space.right - listRect.left) - 30 /* Info.Margin */) + "px";
|
||||
let spaceBelow = space.bottom - listRect.bottom;
|
||||
if (spaceBelow >= infoRect.height || spaceBelow > listRect.top) // Below the completion
|
||||
top = (selRect.bottom - listRect.top) + "px";
|
||||
else // Above it
|
||||
bottom = (listRect.bottom - selRect.top) + "px";
|
||||
}
|
||||
return {
|
||||
top, bottom, maxWidth,
|
||||
class: narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right",
|
||||
};
|
||||
}
|
||||
positionInfo(pos) {
|
||||
if (this.info) {
|
||||
this.info.style.top = (pos ? pos.top : -1e6) + "px";
|
||||
if (pos) {
|
||||
this.info.classList.toggle("cm-completionInfo-left", pos.left);
|
||||
this.info.classList.toggle("cm-completionInfo-right", !pos.left);
|
||||
this.info.style.top = pos.top;
|
||||
this.info.style.bottom = pos.bottom;
|
||||
this.info.style.maxWidth = pos.maxWidth;
|
||||
this.info.className = "cm-tooltip cm-completionInfo cm-completionInfo-" + pos.class;
|
||||
}
|
||||
else {
|
||||
this.info.style.top = "-1e6px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -595,7 +652,8 @@ function sortOptions(active, state) {
|
|||
}
|
||||
}
|
||||
let result = [], prev = null;
|
||||
for (let opt of options.sort(cmpOption)) {
|
||||
let compare = state.facet(completionConfig).compareCompletions;
|
||||
for (let opt of options.sort((a, b) => (b.match[0] - a.match[0]) || compare(a.completion, b.completion))) {
|
||||
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail ||
|
||||
(prev.type != null && opt.completion.type != null && prev.type != opt.completion.type) ||
|
||||
prev.apply != opt.completion.apply)
|
||||
|
@ -607,23 +665,26 @@ function sortOptions(active, state) {
|
|||
return result;
|
||||
}
|
||||
class CompletionDialog {
|
||||
constructor(options, attrs, tooltip, timestamp, selected) {
|
||||
constructor(options, attrs, tooltip, timestamp, selected, disabled) {
|
||||
this.options = options;
|
||||
this.attrs = attrs;
|
||||
this.tooltip = tooltip;
|
||||
this.timestamp = timestamp;
|
||||
this.selected = selected;
|
||||
this.disabled = disabled;
|
||||
}
|
||||
setSelected(selected, id) {
|
||||
return selected == this.selected || selected >= this.options.length ? this
|
||||
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected);
|
||||
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected, this.disabled);
|
||||
}
|
||||
static build(active, state, id, prev, conf) {
|
||||
let options = sortOptions(active, state);
|
||||
if (!options.length)
|
||||
return null;
|
||||
let selected = 0;
|
||||
if (prev && prev.selected) {
|
||||
if (!options.length) {
|
||||
return prev && active.some(a => a.state == 1 /* State.Pending */) ?
|
||||
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
||||
}
|
||||
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
||||
if (prev && prev.selected != selected && prev.selected != -1) {
|
||||
let selectedValue = prev.options[prev.selected].completion;
|
||||
for (let i = 0; i < options.length; i++)
|
||||
if (options[i].completion == selectedValue) {
|
||||
|
@ -635,10 +696,10 @@ class CompletionDialog {
|
|||
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
||||
create: completionTooltip(completionState),
|
||||
above: conf.aboveCursor,
|
||||
}, prev ? prev.timestamp : Date.now(), selected);
|
||||
}, prev ? prev.timestamp : Date.now(), selected, false);
|
||||
}
|
||||
map(changes) {
|
||||
return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected);
|
||||
return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected, this.disabled);
|
||||
}
|
||||
}
|
||||
class CompletionState {
|
||||
|
@ -656,16 +717,21 @@ class CompletionState {
|
|||
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
||||
let active = sources.map(source => {
|
||||
let value = this.active.find(s => s.source == source) ||
|
||||
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
||||
new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
||||
return value.update(tr, conf);
|
||||
});
|
||||
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
||||
active = this.active;
|
||||
let open = tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
||||
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open, conf)
|
||||
: this.open && tr.docChanged ? this.open.map(tr.changes) : this.open;
|
||||
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
||||
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
||||
let open = this.open;
|
||||
if (open && tr.docChanged)
|
||||
open = open.map(tr.changes);
|
||||
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
||||
!sameResults(active, this.active))
|
||||
open = CompletionDialog.build(active, state, this.id, open, conf);
|
||||
else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */))
|
||||
open = null;
|
||||
if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult()))
|
||||
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a);
|
||||
for (let effect of tr.effects)
|
||||
if (effect.is(setSelectedEffect))
|
||||
open = open && open.setSelected(effect.value, this.id);
|
||||
|
@ -693,20 +759,16 @@ const baseAttrs = {
|
|||
"aria-autocomplete": "list"
|
||||
};
|
||||
function makeAttrs(id, selected) {
|
||||
return {
|
||||
let result = {
|
||||
"aria-autocomplete": "list",
|
||||
"aria-haspopup": "listbox",
|
||||
"aria-activedescendant": id + "-" + selected,
|
||||
"aria-controls": id
|
||||
};
|
||||
if (selected > -1)
|
||||
result["aria-activedescendant"] = id + "-" + selected;
|
||||
return result;
|
||||
}
|
||||
const none = [];
|
||||
function cmpOption(a, b) {
|
||||
let dScore = b.match[0] - a.match[0];
|
||||
if (dScore)
|
||||
return dScore;
|
||||
return a.completion.label.localeCompare(b.completion.label);
|
||||
}
|
||||
function getUserEvent(tr) {
|
||||
return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null;
|
||||
}
|
||||
|
@ -723,13 +785,13 @@ class ActiveSource {
|
|||
value = value.handleUserEvent(tr, event, conf);
|
||||
else if (tr.docChanged)
|
||||
value = value.handleChange(tr);
|
||||
else if (tr.selection && value.state != 0 /* Inactive */)
|
||||
value = new ActiveSource(value.source, 0 /* Inactive */);
|
||||
else if (tr.selection && value.state != 0 /* State.Inactive */)
|
||||
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
||||
for (let effect of tr.effects) {
|
||||
if (effect.is(startCompletionEffect))
|
||||
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
||||
value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
|
||||
else if (effect.is(closeCompletionEffect))
|
||||
value = new ActiveSource(value.source, 0 /* Inactive */);
|
||||
value = new ActiveSource(value.source, 0 /* State.Inactive */);
|
||||
else if (effect.is(setActiveEffect))
|
||||
for (let active of effect.value)
|
||||
if (active.source == value.source)
|
||||
|
@ -738,10 +800,10 @@ class ActiveSource {
|
|||
return value;
|
||||
}
|
||||
handleUserEvent(tr, type, conf) {
|
||||
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
||||
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
|
||||
}
|
||||
handleChange(tr) {
|
||||
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
||||
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
||||
}
|
||||
map(changes) {
|
||||
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
||||
|
@ -749,7 +811,7 @@ class ActiveSource {
|
|||
}
|
||||
class ActiveResult extends ActiveSource {
|
||||
constructor(source, explicitPos, result, from, to) {
|
||||
super(source, 2 /* Result */, explicitPos);
|
||||
super(source, 2 /* State.Result */, explicitPos);
|
||||
this.result = result;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
|
@ -762,17 +824,17 @@ class ActiveResult extends ActiveSource {
|
|||
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
||||
pos > to ||
|
||||
type == "delete" && cur(tr.startState) == this.from)
|
||||
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
||||
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
|
||||
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
||||
if (checkValid(this.result.validFor, tr.state, from, to))
|
||||
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
||||
if (this.result.update &&
|
||||
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
||||
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
||||
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
||||
return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
|
||||
}
|
||||
handleChange(tr) {
|
||||
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
||||
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
|
||||
}
|
||||
map(mapping) {
|
||||
return mapping.empty ? this :
|
||||
|
@ -800,7 +862,6 @@ const completionState = /*@__PURE__*/StateField.define({
|
|||
]
|
||||
});
|
||||
|
||||
const CompletionInteractMargin = 75;
|
||||
/**
|
||||
Returns a command that moves the completion selection forward or
|
||||
backward by the given amount.
|
||||
|
@ -808,13 +869,15 @@ backward by the given amount.
|
|||
function moveCompletionSelection(forward, by = "option") {
|
||||
return (view) => {
|
||||
let cState = view.state.field(completionState, false);
|
||||
if (!cState || !cState.open || Date.now() - cState.open.timestamp < CompletionInteractMargin)
|
||||
if (!cState || !cState.open || cState.open.disabled ||
|
||||
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
||||
return false;
|
||||
let step = 1, tooltip;
|
||||
if (by == "page" && (tooltip = getTooltip(view, cState.open.tooltip)))
|
||||
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
||||
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
||||
let selected = cState.open.selected + step * (forward ? 1 : -1), { length } = cState.open.options;
|
||||
let { length } = cState.open.options;
|
||||
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
||||
if (selected < 0)
|
||||
selected = by == "page" ? 0 : length - 1;
|
||||
else if (selected >= length)
|
||||
|
@ -828,9 +891,11 @@ Accept the current completion.
|
|||
*/
|
||||
const acceptCompletion = (view) => {
|
||||
let cState = view.state.field(completionState, false);
|
||||
if (view.state.readOnly || !cState || !cState.open || Date.now() - cState.open.timestamp < CompletionInteractMargin)
|
||||
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
|
||||
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
||||
return false;
|
||||
applyCompletion(view, cState.open.options[cState.open.selected]);
|
||||
if (!cState.open.disabled)
|
||||
applyCompletion(view, cState.open.options[cState.open.selected]);
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
|
@ -848,7 +913,7 @@ Close the currently active completion.
|
|||
*/
|
||||
const closeCompletion = (view) => {
|
||||
let cState = view.state.field(completionState, false);
|
||||
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
||||
if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
|
||||
return false;
|
||||
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
||||
return true;
|
||||
|
@ -871,9 +936,9 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|||
this.debounceUpdate = -1;
|
||||
this.running = [];
|
||||
this.debounceAccept = -1;
|
||||
this.composing = 0 /* None */;
|
||||
this.composing = 0 /* CompositionState.None */;
|
||||
for (let active of view.state.field(completionState).active)
|
||||
if (active.state == 1 /* Pending */)
|
||||
if (active.state == 1 /* State.Pending */)
|
||||
this.startQuery(active);
|
||||
}
|
||||
update(update) {
|
||||
|
@ -904,21 +969,21 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|||
}
|
||||
if (this.debounceUpdate > -1)
|
||||
clearTimeout(this.debounceUpdate);
|
||||
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
||||
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
|
||||
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
||||
if (this.composing != 0 /* None */)
|
||||
if (this.composing != 0 /* CompositionState.None */)
|
||||
for (let tr of update.transactions) {
|
||||
if (getUserEvent(tr) == "input")
|
||||
this.composing = 2 /* Changed */;
|
||||
else if (this.composing == 2 /* Changed */ && tr.selection)
|
||||
this.composing = 3 /* ChangedAndMoved */;
|
||||
this.composing = 2 /* CompositionState.Changed */;
|
||||
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
|
||||
this.composing = 3 /* CompositionState.ChangedAndMoved */;
|
||||
}
|
||||
}
|
||||
startUpdate() {
|
||||
this.debounceUpdate = -1;
|
||||
let { state } = this.view, cState = state.field(completionState);
|
||||
for (let active of cState.active) {
|
||||
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
||||
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
|
||||
this.startQuery(active);
|
||||
}
|
||||
}
|
||||
|
@ -969,14 +1034,14 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|||
}
|
||||
}
|
||||
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
||||
if (current && current.state == 1 /* Pending */) {
|
||||
if (current && current.state == 1 /* State.Pending */) {
|
||||
if (query.done == null) {
|
||||
// Explicitly failed. Should clear the pending status if it
|
||||
// hasn't been re-set in the meantime.
|
||||
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
||||
let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
|
||||
for (let tr of query.updates)
|
||||
active = active.update(tr, conf);
|
||||
if (active.state != 1 /* Pending */)
|
||||
if (active.state != 1 /* State.Pending */)
|
||||
updated.push(active);
|
||||
}
|
||||
else {
|
||||
|
@ -996,15 +1061,15 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|||
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
||||
},
|
||||
compositionstart() {
|
||||
this.composing = 1 /* Started */;
|
||||
this.composing = 1 /* CompositionState.Started */;
|
||||
},
|
||||
compositionend() {
|
||||
if (this.composing == 3 /* ChangedAndMoved */) {
|
||||
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
|
||||
// Safari fires compositionend events synchronously, possibly
|
||||
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
||||
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
||||
}
|
||||
this.composing = 0 /* None */;
|
||||
this.composing = 0 /* CompositionState.None */;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1019,6 +1084,7 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|||
maxWidth: "min(700px, 95vw)",
|
||||
minWidth: "250px",
|
||||
maxHeight: "10em",
|
||||
height: "100%",
|
||||
listStyle: "none",
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
|
@ -1035,10 +1101,16 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|||
background: "#17c",
|
||||
color: "white",
|
||||
},
|
||||
"&light .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
|
||||
background: "#777",
|
||||
},
|
||||
"&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
|
||||
background: "#347",
|
||||
color: "white",
|
||||
},
|
||||
"&dark .cm-tooltip-autocomplete-disabled ul li[aria-selected]": {
|
||||
background: "#444",
|
||||
},
|
||||
".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
|
||||
content: '"···"',
|
||||
opacity: 0.5,
|
||||
|
@ -1049,16 +1121,20 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|||
position: "absolute",
|
||||
padding: "3px 9px",
|
||||
width: "max-content",
|
||||
maxWidth: "300px",
|
||||
maxWidth: `${400 /* Info.Width */}px`,
|
||||
boxSizing: "border-box"
|
||||
},
|
||||
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
||||
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
||||
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
|
||||
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
|
||||
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
||||
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
||||
".cm-snippetFieldPosition": {
|
||||
verticalAlign: "text-top",
|
||||
width: 0,
|
||||
height: "1.15em",
|
||||
display: "inline-block",
|
||||
margin: "0 -0.7px -.7em",
|
||||
borderLeft: "1.4px dotted #888"
|
||||
},
|
||||
|
@ -1075,7 +1151,8 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|||
display: "inline-block",
|
||||
textAlign: "center",
|
||||
paddingRight: ".6em",
|
||||
opacity: "0.6"
|
||||
opacity: "0.6",
|
||||
boxSizing: "content-box"
|
||||
},
|
||||
".cm-completionIcon-function, .cm-completionIcon-method": {
|
||||
"&:after": { content: "'ƒ'" }
|
||||
|
@ -1177,8 +1254,8 @@ class Snippet {
|
|||
positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length));
|
||||
line = line.slice(0, m.index) + name + line.slice(m.index + m[0].length);
|
||||
}
|
||||
for (let esc; esc = /([$#])\\{/.exec(line);) {
|
||||
line = line.slice(0, esc.index) + esc[1] + "{" + line.slice(esc.index + esc[0].length);
|
||||
for (let esc; esc = /\\([{}])/.exec(line);) {
|
||||
line = line.slice(0, esc.index) + esc[1] + line.slice(esc.index + esc[0].length);
|
||||
for (let pos of positions)
|
||||
if (pos.line == lines.length && pos.from > esc.index) {
|
||||
pos.from--;
|
||||
|
@ -1269,10 +1346,9 @@ The order of fields defaults to textual order, but you can add
|
|||
numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
|
||||
a custom order.
|
||||
|
||||
To include a literal `${` or `#{` in your template, put a
|
||||
backslash after the dollar or hash and before the brace (`$\\{`).
|
||||
This will be removed and the sequence will not be interpreted as a
|
||||
placeholder.
|
||||
To include a literal `{` or `}` in your template, put a backslash
|
||||
in front of it. This will be removed and the brace will not be
|
||||
interpreted as indicating a placeholder.
|
||||
*/
|
||||
function snippet(template) {
|
||||
let snippet = Snippet.parse(template);
|
||||
|
@ -1387,7 +1463,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|||
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
||||
result.push({ type: "text", label: m[0] });
|
||||
seen[m[0]] = true;
|
||||
if (result.length >= 2000 /* MaxList */)
|
||||
if (result.length >= 2000 /* C.MaxList */)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1395,7 +1471,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|||
}
|
||||
}
|
||||
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
||||
let big = doc.length >= 1000 /* MinCacheLen */;
|
||||
let big = doc.length >= 1000 /* C.MinCacheLen */;
|
||||
let cached = big && cache.get(doc);
|
||||
if (cached)
|
||||
return cached;
|
||||
|
@ -1403,7 +1479,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|||
if (doc.children) {
|
||||
let pos = 0;
|
||||
for (let ch of doc.children) {
|
||||
if (ch.length >= 1000 /* MinCacheLen */) {
|
||||
if (ch.length >= 1000 /* C.MinCacheLen */) {
|
||||
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
||||
if (!seen[c.label]) {
|
||||
seen[c.label] = true;
|
||||
|
@ -1420,7 +1496,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|||
else {
|
||||
storeWords(doc, wordRE, result, seen, ignoreAt);
|
||||
}
|
||||
if (big && result.length < 2000 /* MaxList */)
|
||||
if (big && result.length < 2000 /* C.MaxList */)
|
||||
cache.set(doc, result);
|
||||
return result;
|
||||
}
|
||||
|
@ -1436,13 +1512,14 @@ const completeAnyWord = context => {
|
|||
if (!token && !context.explicit)
|
||||
return null;
|
||||
let from = token ? token.from : context.pos;
|
||||
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
||||
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from);
|
||||
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
||||
};
|
||||
|
||||
const defaults = {
|
||||
brackets: ["(", "[", "{", "'", '"'],
|
||||
before: ")]}:;>"
|
||||
before: ")]}:;>",
|
||||
stringPrefixes: []
|
||||
};
|
||||
const closeBracketEffect = /*@__PURE__*/StateEffect.define({
|
||||
map(value, mapping) {
|
||||
|
@ -1525,14 +1602,13 @@ const deleteBracketPair = ({ state, dispatch }) => {
|
|||
for (let token of tokens) {
|
||||
if (token == before && nextChar(state.doc, range.head) == closing(codePointAt(token, 0)))
|
||||
return { changes: { from: range.head - token.length, to: range.head + token.length },
|
||||
range: EditorSelection.cursor(range.head - token.length),
|
||||
userEvent: "delete.backward" };
|
||||
range: EditorSelection.cursor(range.head - token.length) };
|
||||
}
|
||||
}
|
||||
return { range: dont = range };
|
||||
});
|
||||
if (!dont)
|
||||
dispatch(state.update(changes, { scrollIntoView: true }));
|
||||
dispatch(state.update(changes, { scrollIntoView: true, userEvent: "delete.backward" }));
|
||||
return !dont;
|
||||
};
|
||||
/**
|
||||
|
@ -1559,7 +1635,7 @@ function insertBracket(state, bracket) {
|
|||
for (let tok of tokens) {
|
||||
let closed = closing(codePointAt(tok, 0));
|
||||
if (bracket == tok)
|
||||
return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1)
|
||||
return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1, conf)
|
||||
: handleOpen(state, tok, closed, conf.before || defaults.before);
|
||||
if (bracket == closed && closedBracketAt(state, state.selection.main.from))
|
||||
return handleClose(state, tok, closed);
|
||||
|
@ -1614,13 +1690,14 @@ function handleClose(state, _open, close) {
|
|||
}
|
||||
// Handles cases where the open and close token are the same, and
|
||||
// possibly triple quotes (as in `"""abc"""`-style quoting).
|
||||
function handleSame(state, token, allowTriple) {
|
||||
function handleSame(state, token, allowTriple, config) {
|
||||
let stringPrefixes = config.stringPrefixes || defaults.stringPrefixes;
|
||||
let dont = null, changes = state.changeByRange(range => {
|
||||
if (!range.empty)
|
||||
return { changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }],
|
||||
effects: closeBracketEffect.of(range.to + token.length),
|
||||
range: EditorSelection.range(range.anchor + token.length, range.head + token.length) };
|
||||
let pos = range.head, next = nextChar(state.doc, pos);
|
||||
let pos = range.head, next = nextChar(state.doc, pos), start;
|
||||
if (next == token) {
|
||||
if (nodeStart(state, pos)) {
|
||||
return { changes: { insert: token + token, from: pos },
|
||||
|
@ -1634,14 +1711,14 @@ function handleSame(state, token, allowTriple) {
|
|||
}
|
||||
}
|
||||
else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token &&
|
||||
nodeStart(state, pos - 2 * token.length)) {
|
||||
(start = canStartStringAt(state, pos - 2 * token.length, stringPrefixes)) > -1 &&
|
||||
nodeStart(state, start)) {
|
||||
return { changes: { insert: token + token + token + token, from: pos },
|
||||
effects: closeBracketEffect.of(pos + token.length),
|
||||
range: EditorSelection.cursor(pos + token.length) };
|
||||
}
|
||||
else if (state.charCategorizer(pos)(next) != CharCategory.Word) {
|
||||
let prev = state.sliceDoc(pos - 1, pos);
|
||||
if (prev != token && state.charCategorizer(pos)(prev) != CharCategory.Word && !probablyInString(state, pos, token))
|
||||
if (canStartStringAt(state, pos, stringPrefixes) > -1 && !probablyInString(state, pos, token, stringPrefixes))
|
||||
return { changes: { insert: token + token, from: pos },
|
||||
effects: closeBracketEffect.of(pos + token.length),
|
||||
range: EditorSelection.cursor(pos + token.length) };
|
||||
|
@ -1657,11 +1734,21 @@ function nodeStart(state, pos) {
|
|||
let tree = syntaxTree(state).resolveInner(pos + 1);
|
||||
return tree.parent && tree.from == pos;
|
||||
}
|
||||
function probablyInString(state, pos, quoteToken) {
|
||||
function probablyInString(state, pos, quoteToken, prefixes) {
|
||||
let node = syntaxTree(state).resolveInner(pos, -1);
|
||||
let maxPrefix = prefixes.reduce((m, p) => Math.max(m, p.length), 0);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (state.sliceDoc(node.from, node.from + quoteToken.length) == quoteToken)
|
||||
let start = state.sliceDoc(node.from, Math.min(node.to, node.from + quoteToken.length + maxPrefix));
|
||||
let quotePos = start.indexOf(quoteToken);
|
||||
if (!quotePos || quotePos > -1 && prefixes.indexOf(start.slice(0, quotePos)) > -1) {
|
||||
let first = node.firstChild;
|
||||
while (first && first.from == node.from && first.to - first.from > quoteToken.length + quotePos) {
|
||||
if (state.sliceDoc(first.to - quoteToken.length, first.to) == quoteToken)
|
||||
return false;
|
||||
first = first.firstChild;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
let parent = node.to == pos && node.parent;
|
||||
if (!parent)
|
||||
break;
|
||||
|
@ -1669,6 +1756,17 @@ function probablyInString(state, pos, quoteToken) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
function canStartStringAt(state, pos, prefixes) {
|
||||
let charCat = state.charCategorizer(pos);
|
||||
if (charCat(state.sliceDoc(pos - 1, pos)) != CharCategory.Word)
|
||||
return pos;
|
||||
for (let prefix of prefixes) {
|
||||
let start = pos - prefix.length;
|
||||
if (state.sliceDoc(start, pos) == prefix && charCat(state.sliceDoc(start - 1, start)) != CharCategory.Word)
|
||||
return start;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an extension that enables autocompletion.
|
||||
|
@ -1711,8 +1809,8 @@ returns `null`.
|
|||
*/
|
||||
function completionStatus(state) {
|
||||
let cState = state.field(completionState, false);
|
||||
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
||||
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
||||
return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
|
||||
: cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
|
||||
}
|
||||
const completionArrayCache = /*@__PURE__*/new WeakMap;
|
||||
/**
|
||||
|
@ -1721,7 +1819,7 @@ Returns the available completions as an array.
|
|||
function currentCompletions(state) {
|
||||
var _a;
|
||||
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
||||
if (!open)
|
||||
if (!open || open.disabled)
|
||||
return [];
|
||||
let completions = completionArrayCache.get(open.options);
|
||||
if (!completions)
|
||||
|
@ -1734,7 +1832,7 @@ Return the currently selected completion, if any.
|
|||
function selectedCompletion(state) {
|
||||
var _a;
|
||||
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
||||
return open ? open.options[open.selected].completion : null;
|
||||
return open && !open.disabled && open.selected >= 0 ? open.options[open.selected].completion : null;
|
||||
}
|
||||
/**
|
||||
Returns the currently selected position in the active completion
|
||||
|
@ -1743,7 +1841,7 @@ list, or null if no completions are active.
|
|||
function selectedCompletionIndex(state) {
|
||||
var _a;
|
||||
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
||||
return open ? open.selected : null;
|
||||
return open && !open.disabled && open.selected >= 0 ? open.selected : null;
|
||||
}
|
||||
/**
|
||||
Create an effect that can be attached to a transaction to change
|
||||
|
|
8
node_modules/@codemirror/autocomplete/package.json
generated
vendored
8
node_modules/@codemirror/autocomplete/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/autocomplete",
|
||||
"version": "6.0.1",
|
||||
"version": "6.4.0",
|
||||
"description": "Autocompletion for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
@ -26,6 +26,12 @@
|
|||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.6.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
|
|
2
node_modules/@codemirror/commands/.github/workflows/dispatch.yml
generated
vendored
2
node_modules/@codemirror/commands/.github/workflows/dispatch.yml
generated
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
with:
|
||||
# You should create a personal access token and store it in your repository
|
||||
token: ${{ secrets.DISPATCH_AUTH }}
|
||||
repo: codemirror.next
|
||||
repo: dev
|
||||
owner: codemirror
|
||||
event_type: push
|
||||
|
|
44
node_modules/@codemirror/commands/CHANGELOG.md
generated
vendored
44
node_modules/@codemirror/commands/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,47 @@
|
|||
## 6.2.0 (2023-01-18)
|
||||
|
||||
### New features
|
||||
|
||||
The new `joinToEvent` history configuration option allows you to provide custom logic that determines whether a new transaction is added to an existing history event.
|
||||
|
||||
## 6.1.3 (2022-12-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Preserve selection bidi level when extending the selection, to prevent shift-selection from getting stuck in some kinds of bidirectional text.
|
||||
|
||||
## 6.1.2 (2022-10-13)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused deletion commands on non-empty ranges to incorrectly return false and do nothing, causing the editor to fall back to native behavior.
|
||||
|
||||
## 6.1.1 (2022-09-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make sure the selection endpoints are moved out of atomic ranges when applying a deletion command to a non-empty selection.
|
||||
|
||||
## 6.1.0 (2022-08-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Prevent native behavior on Ctrl/Cmd-ArrowLeft/ArrowRight bindings, so that browsers with odd bidi behavior won't do the wrong thing at start/end of line.
|
||||
|
||||
Cmd-ArrowLeft/Right on macOS now moves the cursor in the direction of the arrow even in right-to-left content.
|
||||
|
||||
### New features
|
||||
|
||||
The new `cursorLineBoundaryLeft`/`Right` and `selectLineBoundaryLeft`/`Right` commands allow directional motion to line boundaries.
|
||||
|
||||
## 6.0.1 (2022-06-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Announce to the screen reader when the selection is deleted.
|
||||
|
||||
Also bind Ctrl-Shift-z to redo on Linux.
|
||||
|
||||
## 6.0.0 (2022-06-08)
|
||||
|
||||
### Bug fixes
|
||||
|
|
10
node_modules/@codemirror/commands/README.md
generated
vendored
10
node_modules/@codemirror/commands/README.md
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
# @codemirror/commands [](https://www.npmjs.org/package/@codemirror/commands)
|
||||
|
||||
[ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#commands) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/commands/blob/main/CHANGELOG.md) ]
|
||||
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#commands) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/commands/blob/main/CHANGELOG.md) ]
|
||||
|
||||
This package implements a collection of editing commands for the
|
||||
[CodeMirror](https://codemirror.net/6/) code editor.
|
||||
[CodeMirror](https://codemirror.net/) code editor.
|
||||
|
||||
The [project page](https://codemirror.net/6/) has more information, a
|
||||
number of [examples](https://codemirror.net/6/examples/) and the
|
||||
[documentation](https://codemirror.net/6/docs/).
|
||||
The [project page](https://codemirror.net/) has more information, a
|
||||
number of [examples](https://codemirror.net/examples/) and the
|
||||
[documentation](https://codemirror.net/docs/).
|
||||
|
||||
This code is released under an
|
||||
[MIT license](https://github.com/codemirror/commands/tree/main/LICENSE).
|
||||
|
|
137
node_modules/@codemirror/commands/dist/index.cjs
generated
vendored
137
node_modules/@codemirror/commands/dist/index.cjs
generated
vendored
|
@ -32,35 +32,35 @@ The line comment syntax is taken from the
|
|||
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||
*/
|
||||
const toggleLineComment = command(changeLineComment, 0 /* Toggle */);
|
||||
const toggleLineComment = command(changeLineComment, 0 /* CommentOption.Toggle */);
|
||||
/**
|
||||
Comment the current selection using line comments.
|
||||
*/
|
||||
const lineComment = command(changeLineComment, 1 /* Comment */);
|
||||
const lineComment = command(changeLineComment, 1 /* CommentOption.Comment */);
|
||||
/**
|
||||
Uncomment the current selection using line comments.
|
||||
*/
|
||||
const lineUncomment = command(changeLineComment, 2 /* Uncomment */);
|
||||
const lineUncomment = command(changeLineComment, 2 /* CommentOption.Uncomment */);
|
||||
/**
|
||||
Comment or uncomment the current selection using block comments.
|
||||
The block comment syntax is taken from the
|
||||
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||
*/
|
||||
const toggleBlockComment = command(changeBlockComment, 0 /* Toggle */);
|
||||
const toggleBlockComment = command(changeBlockComment, 0 /* CommentOption.Toggle */);
|
||||
/**
|
||||
Comment the current selection using block comments.
|
||||
*/
|
||||
const blockComment = command(changeBlockComment, 1 /* Comment */);
|
||||
const blockComment = command(changeBlockComment, 1 /* CommentOption.Comment */);
|
||||
/**
|
||||
Uncomment the current selection using block comments.
|
||||
*/
|
||||
const blockUncomment = command(changeBlockComment, 2 /* Uncomment */);
|
||||
const blockUncomment = command(changeBlockComment, 2 /* CommentOption.Uncomment */);
|
||||
/**
|
||||
Comment or uncomment the lines around the current selection using
|
||||
block comments.
|
||||
*/
|
||||
const toggleBlockCommentByLine = command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* Toggle */);
|
||||
const toggleBlockCommentByLine = command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* CommentOption.Toggle */);
|
||||
function getConfig(state, pos = state.selection.main.head) {
|
||||
let data = state.languageDataAt("commentTokens", pos);
|
||||
return data.length ? data[0] : {};
|
||||
|
@ -119,14 +119,14 @@ function changeBlockComment(option, state, ranges = state.selection.ranges) {
|
|||
if (!tokens.every(c => c))
|
||||
return null;
|
||||
let comments = ranges.map((r, i) => findBlockComment(state, tokens[i], r.from, r.to));
|
||||
if (option != 2 /* Uncomment */ && !comments.every(c => c)) {
|
||||
if (option != 2 /* CommentOption.Uncomment */ && !comments.every(c => c)) {
|
||||
return { changes: state.changes(ranges.map((range, i) => {
|
||||
if (comments[i])
|
||||
return [];
|
||||
return [{ from: range.from, insert: tokens[i].open + " " }, { from: range.to, insert: " " + tokens[i].close }];
|
||||
})) };
|
||||
}
|
||||
else if (option != 1 /* Comment */ && comments.some(c => c)) {
|
||||
else if (option != 1 /* CommentOption.Comment */ && comments.some(c => c)) {
|
||||
let changes = [];
|
||||
for (let i = 0, comment; i < comments.length; i++)
|
||||
if (comment = comments[i]) {
|
||||
|
@ -166,7 +166,7 @@ function changeLineComment(option, state, ranges = state.selection.ranges) {
|
|||
if (lines.length == startI + 1)
|
||||
lines[startI].single = true;
|
||||
}
|
||||
if (option != 2 /* Uncomment */ && lines.some(l => l.comment < 0 && (!l.empty || l.single))) {
|
||||
if (option != 2 /* CommentOption.Uncomment */ && lines.some(l => l.comment < 0 && (!l.empty || l.single))) {
|
||||
let changes = [];
|
||||
for (let { line, token, indent, empty, single } of lines)
|
||||
if (single || !empty)
|
||||
|
@ -174,7 +174,7 @@ function changeLineComment(option, state, ranges = state.selection.ranges) {
|
|||
let changeSet = state.changes(changes);
|
||||
return { changes: changeSet, selection: state.selection.map(changeSet, 1) };
|
||||
}
|
||||
else if (option != 1 /* Comment */ && lines.some(l => l.comment >= 0)) {
|
||||
else if (option != 1 /* CommentOption.Comment */ && lines.some(l => l.comment >= 0)) {
|
||||
let changes = [];
|
||||
for (let { line, comment, token } of lines)
|
||||
if (comment >= 0) {
|
||||
|
@ -209,8 +209,13 @@ const historyConfig = state.Facet.define({
|
|||
combine(configs) {
|
||||
return state.combineConfig(configs, {
|
||||
minDepth: 100,
|
||||
newGroupDelay: 500
|
||||
}, { minDepth: Math.max, newGroupDelay: Math.min });
|
||||
newGroupDelay: 500,
|
||||
joinToEvent: (_t, isAdjacent) => isAdjacent,
|
||||
}, {
|
||||
minDepth: Math.max,
|
||||
newGroupDelay: Math.min,
|
||||
joinToEvent: (a, b) => (tr, adj) => a(tr, adj) || b(tr, adj)
|
||||
});
|
||||
}
|
||||
});
|
||||
function changeEnd(changes) {
|
||||
|
@ -228,12 +233,12 @@ const historyField_ = state.StateField.define({
|
|||
if (fromHist) {
|
||||
let selection = tr.docChanged ? state.EditorSelection.single(changeEnd(tr.changes)) : undefined;
|
||||
let item = HistEvent.fromTransaction(tr, selection), from = fromHist.side;
|
||||
let other = from == 0 /* Done */ ? state$1.undone : state$1.done;
|
||||
let other = from == 0 /* BranchName.Done */ ? state$1.undone : state$1.done;
|
||||
if (item)
|
||||
other = updateBranch(other, other.length, config.minDepth, item);
|
||||
else
|
||||
other = addSelection(other, tr.startState.selection);
|
||||
return new HistoryState(from == 0 /* Done */ ? fromHist.rest : other, from == 0 /* Done */ ? other : fromHist.rest);
|
||||
return new HistoryState(from == 0 /* BranchName.Done */ ? fromHist.rest : other, from == 0 /* BranchName.Done */ ? other : fromHist.rest);
|
||||
}
|
||||
let isolate = tr.annotation(isolateHistory);
|
||||
if (isolate == "full" || isolate == "before")
|
||||
|
@ -243,7 +248,7 @@ const historyField_ = state.StateField.define({
|
|||
let event = HistEvent.fromTransaction(tr);
|
||||
let time = tr.annotation(state.Transaction.time), userEvent = tr.annotation(state.Transaction.userEvent);
|
||||
if (event)
|
||||
state$1 = state$1.addChanges(event, time, userEvent, config.newGroupDelay, config.minDepth);
|
||||
state$1 = state$1.addChanges(event, time, userEvent, config, tr);
|
||||
else if (tr.selection)
|
||||
state$1 = state$1.addSelection(tr.startState.selection, time, userEvent, config.newGroupDelay);
|
||||
if (isolate == "full" || isolate == "after")
|
||||
|
@ -301,37 +306,37 @@ function cmd(side, selection) {
|
|||
Undo a single group of history events. Returns false if no group
|
||||
was available.
|
||||
*/
|
||||
const undo = cmd(0 /* Done */, false);
|
||||
const undo = cmd(0 /* BranchName.Done */, false);
|
||||
/**
|
||||
Redo a group of history events. Returns false if no group was
|
||||
available.
|
||||
*/
|
||||
const redo = cmd(1 /* Undone */, false);
|
||||
const redo = cmd(1 /* BranchName.Undone */, false);
|
||||
/**
|
||||
Undo a change or selection change.
|
||||
*/
|
||||
const undoSelection = cmd(0 /* Done */, true);
|
||||
const undoSelection = cmd(0 /* BranchName.Done */, true);
|
||||
/**
|
||||
Redo a change or selection change.
|
||||
*/
|
||||
const redoSelection = cmd(1 /* Undone */, true);
|
||||
const redoSelection = cmd(1 /* BranchName.Undone */, true);
|
||||
function depth(side) {
|
||||
return function (state) {
|
||||
let histState = state.field(historyField_, false);
|
||||
if (!histState)
|
||||
return 0;
|
||||
let branch = side == 0 /* Done */ ? histState.done : histState.undone;
|
||||
let branch = side == 0 /* BranchName.Done */ ? histState.done : histState.undone;
|
||||
return branch.length - (branch.length && !branch[0].changes ? 1 : 0);
|
||||
};
|
||||
}
|
||||
/**
|
||||
The amount of undoable change events available in a given state.
|
||||
*/
|
||||
const undoDepth = depth(0 /* Done */);
|
||||
const undoDepth = depth(0 /* BranchName.Done */);
|
||||
/**
|
||||
The amount of redoable change events available in a given state.
|
||||
*/
|
||||
const redoDepth = depth(1 /* Undone */);
|
||||
const redoDepth = depth(1 /* BranchName.Undone */);
|
||||
// History events store groups of changes or effects that need to be
|
||||
// undone/redone together.
|
||||
class HistEvent {
|
||||
|
@ -343,7 +348,10 @@ class HistEvent {
|
|||
// changes == startSelection == undefined
|
||||
changes,
|
||||
// The effects associated with this event
|
||||
effects, mapped,
|
||||
effects,
|
||||
// Accumulated mapping (from addToHistory==false) that should be
|
||||
// applied to events below this one.
|
||||
mapped,
|
||||
// The selection before this event
|
||||
startSelection,
|
||||
// Stores selection changes after this event, to be used for
|
||||
|
@ -477,19 +485,19 @@ class HistoryState {
|
|||
isolate() {
|
||||
return this.prevTime ? new HistoryState(this.done, this.undone) : this;
|
||||
}
|
||||
addChanges(event, time, userEvent, newGroupDelay, maxLen) {
|
||||
addChanges(event, time, userEvent, config, tr) {
|
||||
let done = this.done, lastEvent = done[done.length - 1];
|
||||
if (lastEvent && lastEvent.changes && !lastEvent.changes.empty && event.changes &&
|
||||
(!userEvent || joinableUserEvent.test(userEvent)) &&
|
||||
((!lastEvent.selectionsAfter.length &&
|
||||
time - this.prevTime < newGroupDelay &&
|
||||
isAdjacent(lastEvent.changes, event.changes)) ||
|
||||
time - this.prevTime < config.newGroupDelay &&
|
||||
config.joinToEvent(tr, isAdjacent(lastEvent.changes, event.changes))) ||
|
||||
// For compose (but not compose.start) events, always join with previous event
|
||||
userEvent == "input.type.compose")) {
|
||||
done = updateBranch(done, done.length - 1, maxLen, new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects), lastEvent.mapped, lastEvent.startSelection, none));
|
||||
done = updateBranch(done, done.length - 1, config.minDepth, new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects), lastEvent.mapped, lastEvent.startSelection, none));
|
||||
}
|
||||
else {
|
||||
done = updateBranch(done, done.length, maxLen, event);
|
||||
done = updateBranch(done, done.length, config.minDepth, event);
|
||||
}
|
||||
return new HistoryState(done, none, time, userEvent);
|
||||
}
|
||||
|
@ -506,7 +514,7 @@ class HistoryState {
|
|||
return new HistoryState(addMappingToBranch(this.done, mapping), addMappingToBranch(this.undone, mapping), this.prevTime, this.prevUserEvent);
|
||||
}
|
||||
pop(side, state, selection) {
|
||||
let branch = side == 0 /* Done */ ? this.done : this.undone;
|
||||
let branch = side == 0 /* BranchName.Done */ ? this.done : this.undone;
|
||||
if (branch.length == 0)
|
||||
return null;
|
||||
let event = branch[branch.length - 1];
|
||||
|
@ -514,7 +522,7 @@ class HistoryState {
|
|||
return state.update({
|
||||
selection: event.selectionsAfter[event.selectionsAfter.length - 1],
|
||||
annotations: fromHistory.of({ side, rest: popSelection(branch) }),
|
||||
userEvent: side == 0 /* Done */ ? "select.undo" : "select.redo",
|
||||
userEvent: side == 0 /* BranchName.Done */ ? "select.undo" : "select.redo",
|
||||
scrollIntoView: true
|
||||
});
|
||||
}
|
||||
|
@ -531,7 +539,7 @@ class HistoryState {
|
|||
effects: event.effects,
|
||||
annotations: fromHistory.of({ side, rest }),
|
||||
filter: false,
|
||||
userEvent: side == 0 /* Done */ ? "undo" : "redo",
|
||||
userEvent: side == 0 /* BranchName.Done */ ? "undo" : "redo",
|
||||
scrollIntoView: true
|
||||
});
|
||||
}
|
||||
|
@ -542,13 +550,14 @@ HistoryState.empty = new HistoryState(none, none);
|
|||
Default key bindings for the undo history.
|
||||
|
||||
- Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo).
|
||||
- Mod-y (Mod-Shift-z on macOS): [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||
- Mod-y (Mod-Shift-z on macOS) + Ctrl-Shift-z on Linux: [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||
- Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection).
|
||||
- Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection).
|
||||
*/
|
||||
const historyKeymap = [
|
||||
{ key: "Mod-z", run: undo, preventDefault: true },
|
||||
{ key: "Mod-y", mac: "Mod-Shift-z", run: redo, preventDefault: true },
|
||||
{ linux: "Ctrl-Shift-z", run: redo, preventDefault: true },
|
||||
{ key: "Mod-u", run: undoSelection, preventDefault: true },
|
||||
{ key: "Alt-u", mac: "Mod-Shift-u", run: redoSelection, preventDefault: true }
|
||||
];
|
||||
|
@ -762,6 +771,14 @@ end of the indentation instead of the start of the line.
|
|||
*/
|
||||
const cursorLineBoundaryBackward = view => moveSel(view, range => moveByLineBoundary(view, range, false));
|
||||
/**
|
||||
Move the selection one line wrap point to the left.
|
||||
*/
|
||||
const cursorLineBoundaryLeft = view => moveSel(view, range => moveByLineBoundary(view, range, !ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection one line wrap point to the right.
|
||||
*/
|
||||
const cursorLineBoundaryRight = view => moveSel(view, range => moveByLineBoundary(view, range, ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection to the start of the line.
|
||||
*/
|
||||
const cursorLineStart = view => moveSel(view, range => state.EditorSelection.cursor(view.lineBlockAt(range.head).from, 1));
|
||||
|
@ -799,7 +816,7 @@ const selectMatchingBracket = ({ state, dispatch }) => toMatchingBracket(state,
|
|||
function extendSel(view, how) {
|
||||
let selection = updateSel(view.state.selection, range => {
|
||||
let head = how(range);
|
||||
return state.EditorSelection.range(range.anchor, head.head, head.goalColumn);
|
||||
return state.EditorSelection.range(range.anchor, head.head, head.goalColumn, head.bidiLevel || undefined);
|
||||
});
|
||||
if (selection.eq(view.state.selection))
|
||||
return false;
|
||||
|
@ -896,6 +913,14 @@ Move the selection head to the previous line boundary.
|
|||
*/
|
||||
const selectLineBoundaryBackward = view => extendSel(view, range => moveByLineBoundary(view, range, false));
|
||||
/**
|
||||
Move the selection head one line boundary to the left.
|
||||
*/
|
||||
const selectLineBoundaryLeft = view => extendSel(view, range => moveByLineBoundary(view, range, !ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection head one line boundary to the right.
|
||||
*/
|
||||
const selectLineBoundaryRight = view => extendSel(view, range => moveByLineBoundary(view, range, ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection head to the start of the line.
|
||||
*/
|
||||
const selectLineStart = view => extendSel(view, range => state.EditorSelection.cursor(view.lineBlockAt(range.head).from));
|
||||
|
@ -981,26 +1006,38 @@ const simplifySelection = ({ state: state$1, dispatch }) => {
|
|||
dispatch(setSel(state$1, selection));
|
||||
return true;
|
||||
};
|
||||
function deleteBy({ state: state$1, dispatch }, by) {
|
||||
if (state$1.readOnly)
|
||||
function deleteBy(target, by) {
|
||||
if (target.state.readOnly)
|
||||
return false;
|
||||
let event = "delete.selection";
|
||||
let event = "delete.selection", { state: state$1 } = target;
|
||||
let changes = state$1.changeByRange(range => {
|
||||
let { from, to } = range;
|
||||
if (from == to) {
|
||||
let towards = by(from);
|
||||
if (towards < from)
|
||||
if (towards < from) {
|
||||
event = "delete.backward";
|
||||
else if (towards > from)
|
||||
towards = skipAtomic(target, towards, false);
|
||||
}
|
||||
else if (towards > from) {
|
||||
event = "delete.forward";
|
||||
towards = skipAtomic(target, towards, true);
|
||||
}
|
||||
from = Math.min(from, towards);
|
||||
to = Math.max(to, towards);
|
||||
}
|
||||
else {
|
||||
from = skipAtomic(target, from, false);
|
||||
to = skipAtomic(target, to, true);
|
||||
}
|
||||
return from == to ? { range } : { changes: { from, to }, range: state.EditorSelection.cursor(from) };
|
||||
});
|
||||
if (changes.changes.empty)
|
||||
return false;
|
||||
dispatch(state$1.update(changes, { scrollIntoView: true, userEvent: event }));
|
||||
target.dispatch(state$1.update(changes, {
|
||||
scrollIntoView: true,
|
||||
userEvent: event,
|
||||
effects: event == "delete.selection" ? view.EditorView.announce.of(state$1.phrase("Selection deleted")) : undefined
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
function skipAtomic(target, pos, forward) {
|
||||
|
@ -1028,7 +1065,7 @@ const deleteByChar = (target, forward) => deleteBy(target, pos => {
|
|||
if (targetPos == pos && line.number != (forward ? state$1.doc.lines : 1))
|
||||
targetPos += forward ? 1 : -1;
|
||||
}
|
||||
return skipAtomic(target, targetPos, forward);
|
||||
return targetPos;
|
||||
});
|
||||
/**
|
||||
Delete the selection, or, for cursor selections, the character
|
||||
|
@ -1057,7 +1094,7 @@ const deleteByGroup = (target, forward) => deleteBy(target, start => {
|
|||
cat = nextCat;
|
||||
pos = next;
|
||||
}
|
||||
return skipAtomic(target, pos, forward);
|
||||
return pos;
|
||||
});
|
||||
/**
|
||||
Delete the selection or backward until the end of the next
|
||||
|
@ -1076,7 +1113,7 @@ line, delete the line break after it.
|
|||
*/
|
||||
const deleteToLineEnd = view => deleteBy(view, pos => {
|
||||
let lineEnd = view.lineBlockAt(pos).to;
|
||||
return skipAtomic(view, pos < lineEnd ? lineEnd : Math.min(view.state.doc.length, pos + 1), true);
|
||||
return pos < lineEnd ? lineEnd : Math.min(view.state.doc.length, pos + 1);
|
||||
});
|
||||
/**
|
||||
Delete the selection, or, if it is a cursor selection, delete to
|
||||
|
@ -1085,7 +1122,7 @@ line, delete the line break before it.
|
|||
*/
|
||||
const deleteToLineStart = view => deleteBy(view, pos => {
|
||||
let lineStart = view.lineBlockAt(pos).from;
|
||||
return skipAtomic(view, pos > lineStart ? lineStart : Math.max(0, pos - 1), false);
|
||||
return pos > lineStart ? lineStart : Math.max(0, pos - 1);
|
||||
});
|
||||
/**
|
||||
Delete all whitespace directly before a line end from the
|
||||
|
@ -1460,11 +1497,11 @@ property changed to `mac`.)
|
|||
*/
|
||||
const standardKeymap = [
|
||||
{ key: "ArrowLeft", run: cursorCharLeft, shift: selectCharLeft, preventDefault: true },
|
||||
{ key: "Mod-ArrowLeft", mac: "Alt-ArrowLeft", run: cursorGroupLeft, shift: selectGroupLeft },
|
||||
{ mac: "Cmd-ArrowLeft", run: cursorLineBoundaryBackward, shift: selectLineBoundaryBackward },
|
||||
{ key: "Mod-ArrowLeft", mac: "Alt-ArrowLeft", run: cursorGroupLeft, shift: selectGroupLeft, preventDefault: true },
|
||||
{ mac: "Cmd-ArrowLeft", run: cursorLineBoundaryLeft, shift: selectLineBoundaryLeft, preventDefault: true },
|
||||
{ key: "ArrowRight", run: cursorCharRight, shift: selectCharRight, preventDefault: true },
|
||||
{ key: "Mod-ArrowRight", mac: "Alt-ArrowRight", run: cursorGroupRight, shift: selectGroupRight },
|
||||
{ mac: "Cmd-ArrowRight", run: cursorLineBoundaryForward, shift: selectLineBoundaryForward },
|
||||
{ key: "Mod-ArrowRight", mac: "Alt-ArrowRight", run: cursorGroupRight, shift: selectGroupRight, preventDefault: true },
|
||||
{ mac: "Cmd-ArrowRight", run: cursorLineBoundaryRight, shift: selectLineBoundaryRight, preventDefault: true },
|
||||
{ key: "ArrowUp", run: cursorLineUp, shift: selectLineUp, preventDefault: true },
|
||||
{ mac: "Cmd-ArrowUp", run: cursorDocStart, shift: selectDocStart },
|
||||
{ mac: "Ctrl-ArrowUp", run: cursorPageUp, shift: selectPageUp },
|
||||
|
@ -1551,6 +1588,8 @@ exports.cursorGroupLeft = cursorGroupLeft;
|
|||
exports.cursorGroupRight = cursorGroupRight;
|
||||
exports.cursorLineBoundaryBackward = cursorLineBoundaryBackward;
|
||||
exports.cursorLineBoundaryForward = cursorLineBoundaryForward;
|
||||
exports.cursorLineBoundaryLeft = cursorLineBoundaryLeft;
|
||||
exports.cursorLineBoundaryRight = cursorLineBoundaryRight;
|
||||
exports.cursorLineDown = cursorLineDown;
|
||||
exports.cursorLineEnd = cursorLineEnd;
|
||||
exports.cursorLineStart = cursorLineStart;
|
||||
|
@ -1606,6 +1645,8 @@ exports.selectGroupRight = selectGroupRight;
|
|||
exports.selectLine = selectLine;
|
||||
exports.selectLineBoundaryBackward = selectLineBoundaryBackward;
|
||||
exports.selectLineBoundaryForward = selectLineBoundaryForward;
|
||||
exports.selectLineBoundaryLeft = selectLineBoundaryLeft;
|
||||
exports.selectLineBoundaryRight = selectLineBoundaryRight;
|
||||
exports.selectLineDown = selectLineDown;
|
||||
exports.selectLineEnd = selectLineEnd;
|
||||
exports.selectLineStart = selectLineStart;
|
||||
|
|
27
node_modules/@codemirror/commands/dist/index.d.ts
generated
vendored
27
node_modules/@codemirror/commands/dist/index.d.ts
generated
vendored
|
@ -88,6 +88,13 @@ interface HistoryConfig {
|
|||
apart and still be grouped together. Defaults to 500.
|
||||
*/
|
||||
newGroupDelay?: number;
|
||||
/**
|
||||
By default, when close enough together in time, changes are
|
||||
joined into an existing undo event if they touch any of the
|
||||
changed ranges from that event. You can pass a custom predicate
|
||||
here to influence that logic.
|
||||
*/
|
||||
joinToEvent?: (tr: Transaction, isAdjacent: boolean) => boolean;
|
||||
}
|
||||
/**
|
||||
Create a history extension with the given configuration.
|
||||
|
@ -131,7 +138,7 @@ declare const redoDepth: (state: EditorState) => number;
|
|||
Default key bindings for the undo history.
|
||||
|
||||
- Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo).
|
||||
- Mod-y (Mod-Shift-z on macOS): [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||
- Mod-y (Mod-Shift-z on macOS) + Ctrl-Shift-z on Linux: [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||
- Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection).
|
||||
- Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection).
|
||||
*/
|
||||
|
@ -216,6 +223,14 @@ end of the indentation instead of the start of the line.
|
|||
*/
|
||||
declare const cursorLineBoundaryBackward: Command;
|
||||
/**
|
||||
Move the selection one line wrap point to the left.
|
||||
*/
|
||||
declare const cursorLineBoundaryLeft: Command;
|
||||
/**
|
||||
Move the selection one line wrap point to the right.
|
||||
*/
|
||||
declare const cursorLineBoundaryRight: Command;
|
||||
/**
|
||||
Move the selection to the start of the line.
|
||||
*/
|
||||
declare const cursorLineStart: Command;
|
||||
|
@ -308,6 +323,14 @@ Move the selection head to the previous line boundary.
|
|||
*/
|
||||
declare const selectLineBoundaryBackward: Command;
|
||||
/**
|
||||
Move the selection head one line boundary to the left.
|
||||
*/
|
||||
declare const selectLineBoundaryLeft: Command;
|
||||
/**
|
||||
Move the selection head one line boundary to the right.
|
||||
*/
|
||||
declare const selectLineBoundaryRight: Command;
|
||||
/**
|
||||
Move the selection head to the start of the line.
|
||||
*/
|
||||
declare const selectLineStart: Command;
|
||||
|
@ -540,4 +563,4 @@ this.
|
|||
*/
|
||||
declare const indentWithTab: KeyBinding;
|
||||
|
||||
export { CommentTokens, blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharForward, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, defaultKeymap, deleteCharBackward, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteLine, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, history, historyField, historyKeymap, indentLess, indentMore, indentSelection, indentWithTab, insertBlankLine, insertNewline, insertNewlineAndIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharForward, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, transposeChars, undo, undoDepth, undoSelection };
|
||||
export { CommentTokens, blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharForward, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineBoundaryLeft, cursorLineBoundaryRight, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, defaultKeymap, deleteCharBackward, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteLine, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, history, historyField, historyKeymap, indentLess, indentMore, indentSelection, indentWithTab, insertBlankLine, insertNewline, insertNewlineAndIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharForward, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineBoundaryLeft, selectLineBoundaryRight, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, transposeChars, undo, undoDepth, undoSelection };
|
||||
|
|
137
node_modules/@codemirror/commands/dist/index.js
generated
vendored
137
node_modules/@codemirror/commands/dist/index.js
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
import { Annotation, Facet, combineConfig, StateField, EditorSelection, Transaction, ChangeSet, ChangeDesc, StateEffect, Text, findClusterBreak, countColumn, CharCategory } from '@codemirror/state';
|
||||
import { EditorView, Direction } from '@codemirror/view';
|
||||
import { IndentContext, getIndentation, indentString, indentUnit, getIndentUnit, matchBrackets, syntaxTree } from '@codemirror/language';
|
||||
import { IndentContext, getIndentation, indentString, matchBrackets, syntaxTree, getIndentUnit, indentUnit } from '@codemirror/language';
|
||||
import { NodeProp } from '@lezer/common';
|
||||
|
||||
/**
|
||||
|
@ -28,35 +28,35 @@ The line comment syntax is taken from the
|
|||
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||
*/
|
||||
const toggleLineComment = /*@__PURE__*/command(changeLineComment, 0 /* Toggle */);
|
||||
const toggleLineComment = /*@__PURE__*/command(changeLineComment, 0 /* CommentOption.Toggle */);
|
||||
/**
|
||||
Comment the current selection using line comments.
|
||||
*/
|
||||
const lineComment = /*@__PURE__*/command(changeLineComment, 1 /* Comment */);
|
||||
const lineComment = /*@__PURE__*/command(changeLineComment, 1 /* CommentOption.Comment */);
|
||||
/**
|
||||
Uncomment the current selection using line comments.
|
||||
*/
|
||||
const lineUncomment = /*@__PURE__*/command(changeLineComment, 2 /* Uncomment */);
|
||||
const lineUncomment = /*@__PURE__*/command(changeLineComment, 2 /* CommentOption.Uncomment */);
|
||||
/**
|
||||
Comment or uncomment the current selection using block comments.
|
||||
The block comment syntax is taken from the
|
||||
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
||||
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
||||
*/
|
||||
const toggleBlockComment = /*@__PURE__*/command(changeBlockComment, 0 /* Toggle */);
|
||||
const toggleBlockComment = /*@__PURE__*/command(changeBlockComment, 0 /* CommentOption.Toggle */);
|
||||
/**
|
||||
Comment the current selection using block comments.
|
||||
*/
|
||||
const blockComment = /*@__PURE__*/command(changeBlockComment, 1 /* Comment */);
|
||||
const blockComment = /*@__PURE__*/command(changeBlockComment, 1 /* CommentOption.Comment */);
|
||||
/**
|
||||
Uncomment the current selection using block comments.
|
||||
*/
|
||||
const blockUncomment = /*@__PURE__*/command(changeBlockComment, 2 /* Uncomment */);
|
||||
const blockUncomment = /*@__PURE__*/command(changeBlockComment, 2 /* CommentOption.Uncomment */);
|
||||
/**
|
||||
Comment or uncomment the lines around the current selection using
|
||||
block comments.
|
||||
*/
|
||||
const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* Toggle */);
|
||||
const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* CommentOption.Toggle */);
|
||||
function getConfig(state, pos = state.selection.main.head) {
|
||||
let data = state.languageDataAt("commentTokens", pos);
|
||||
return data.length ? data[0] : {};
|
||||
|
@ -115,14 +115,14 @@ function changeBlockComment(option, state, ranges = state.selection.ranges) {
|
|||
if (!tokens.every(c => c))
|
||||
return null;
|
||||
let comments = ranges.map((r, i) => findBlockComment(state, tokens[i], r.from, r.to));
|
||||
if (option != 2 /* Uncomment */ && !comments.every(c => c)) {
|
||||
if (option != 2 /* CommentOption.Uncomment */ && !comments.every(c => c)) {
|
||||
return { changes: state.changes(ranges.map((range, i) => {
|
||||
if (comments[i])
|
||||
return [];
|
||||
return [{ from: range.from, insert: tokens[i].open + " " }, { from: range.to, insert: " " + tokens[i].close }];
|
||||
})) };
|
||||
}
|
||||
else if (option != 1 /* Comment */ && comments.some(c => c)) {
|
||||
else if (option != 1 /* CommentOption.Comment */ && comments.some(c => c)) {
|
||||
let changes = [];
|
||||
for (let i = 0, comment; i < comments.length; i++)
|
||||
if (comment = comments[i]) {
|
||||
|
@ -162,7 +162,7 @@ function changeLineComment(option, state, ranges = state.selection.ranges) {
|
|||
if (lines.length == startI + 1)
|
||||
lines[startI].single = true;
|
||||
}
|
||||
if (option != 2 /* Uncomment */ && lines.some(l => l.comment < 0 && (!l.empty || l.single))) {
|
||||
if (option != 2 /* CommentOption.Uncomment */ && lines.some(l => l.comment < 0 && (!l.empty || l.single))) {
|
||||
let changes = [];
|
||||
for (let { line, token, indent, empty, single } of lines)
|
||||
if (single || !empty)
|
||||
|
@ -170,7 +170,7 @@ function changeLineComment(option, state, ranges = state.selection.ranges) {
|
|||
let changeSet = state.changes(changes);
|
||||
return { changes: changeSet, selection: state.selection.map(changeSet, 1) };
|
||||
}
|
||||
else if (option != 1 /* Comment */ && lines.some(l => l.comment >= 0)) {
|
||||
else if (option != 1 /* CommentOption.Comment */ && lines.some(l => l.comment >= 0)) {
|
||||
let changes = [];
|
||||
for (let { line, comment, token } of lines)
|
||||
if (comment >= 0) {
|
||||
|
@ -205,8 +205,13 @@ const historyConfig = /*@__PURE__*/Facet.define({
|
|||
combine(configs) {
|
||||
return combineConfig(configs, {
|
||||
minDepth: 100,
|
||||
newGroupDelay: 500
|
||||
}, { minDepth: Math.max, newGroupDelay: Math.min });
|
||||
newGroupDelay: 500,
|
||||
joinToEvent: (_t, isAdjacent) => isAdjacent,
|
||||
}, {
|
||||
minDepth: Math.max,
|
||||
newGroupDelay: Math.min,
|
||||
joinToEvent: (a, b) => (tr, adj) => a(tr, adj) || b(tr, adj)
|
||||
});
|
||||
}
|
||||
});
|
||||
function changeEnd(changes) {
|
||||
|
@ -224,12 +229,12 @@ const historyField_ = /*@__PURE__*/StateField.define({
|
|||
if (fromHist) {
|
||||
let selection = tr.docChanged ? EditorSelection.single(changeEnd(tr.changes)) : undefined;
|
||||
let item = HistEvent.fromTransaction(tr, selection), from = fromHist.side;
|
||||
let other = from == 0 /* Done */ ? state.undone : state.done;
|
||||
let other = from == 0 /* BranchName.Done */ ? state.undone : state.done;
|
||||
if (item)
|
||||
other = updateBranch(other, other.length, config.minDepth, item);
|
||||
else
|
||||
other = addSelection(other, tr.startState.selection);
|
||||
return new HistoryState(from == 0 /* Done */ ? fromHist.rest : other, from == 0 /* Done */ ? other : fromHist.rest);
|
||||
return new HistoryState(from == 0 /* BranchName.Done */ ? fromHist.rest : other, from == 0 /* BranchName.Done */ ? other : fromHist.rest);
|
||||
}
|
||||
let isolate = tr.annotation(isolateHistory);
|
||||
if (isolate == "full" || isolate == "before")
|
||||
|
@ -239,7 +244,7 @@ const historyField_ = /*@__PURE__*/StateField.define({
|
|||
let event = HistEvent.fromTransaction(tr);
|
||||
let time = tr.annotation(Transaction.time), userEvent = tr.annotation(Transaction.userEvent);
|
||||
if (event)
|
||||
state = state.addChanges(event, time, userEvent, config.newGroupDelay, config.minDepth);
|
||||
state = state.addChanges(event, time, userEvent, config, tr);
|
||||
else if (tr.selection)
|
||||
state = state.addSelection(tr.startState.selection, time, userEvent, config.newGroupDelay);
|
||||
if (isolate == "full" || isolate == "after")
|
||||
|
@ -297,37 +302,37 @@ function cmd(side, selection) {
|
|||
Undo a single group of history events. Returns false if no group
|
||||
was available.
|
||||
*/
|
||||
const undo = /*@__PURE__*/cmd(0 /* Done */, false);
|
||||
const undo = /*@__PURE__*/cmd(0 /* BranchName.Done */, false);
|
||||
/**
|
||||
Redo a group of history events. Returns false if no group was
|
||||
available.
|
||||
*/
|
||||
const redo = /*@__PURE__*/cmd(1 /* Undone */, false);
|
||||
const redo = /*@__PURE__*/cmd(1 /* BranchName.Undone */, false);
|
||||
/**
|
||||
Undo a change or selection change.
|
||||
*/
|
||||
const undoSelection = /*@__PURE__*/cmd(0 /* Done */, true);
|
||||
const undoSelection = /*@__PURE__*/cmd(0 /* BranchName.Done */, true);
|
||||
/**
|
||||
Redo a change or selection change.
|
||||
*/
|
||||
const redoSelection = /*@__PURE__*/cmd(1 /* Undone */, true);
|
||||
const redoSelection = /*@__PURE__*/cmd(1 /* BranchName.Undone */, true);
|
||||
function depth(side) {
|
||||
return function (state) {
|
||||
let histState = state.field(historyField_, false);
|
||||
if (!histState)
|
||||
return 0;
|
||||
let branch = side == 0 /* Done */ ? histState.done : histState.undone;
|
||||
let branch = side == 0 /* BranchName.Done */ ? histState.done : histState.undone;
|
||||
return branch.length - (branch.length && !branch[0].changes ? 1 : 0);
|
||||
};
|
||||
}
|
||||
/**
|
||||
The amount of undoable change events available in a given state.
|
||||
*/
|
||||
const undoDepth = /*@__PURE__*/depth(0 /* Done */);
|
||||
const undoDepth = /*@__PURE__*/depth(0 /* BranchName.Done */);
|
||||
/**
|
||||
The amount of redoable change events available in a given state.
|
||||
*/
|
||||
const redoDepth = /*@__PURE__*/depth(1 /* Undone */);
|
||||
const redoDepth = /*@__PURE__*/depth(1 /* BranchName.Undone */);
|
||||
// History events store groups of changes or effects that need to be
|
||||
// undone/redone together.
|
||||
class HistEvent {
|
||||
|
@ -339,7 +344,10 @@ class HistEvent {
|
|||
// changes == startSelection == undefined
|
||||
changes,
|
||||
// The effects associated with this event
|
||||
effects, mapped,
|
||||
effects,
|
||||
// Accumulated mapping (from addToHistory==false) that should be
|
||||
// applied to events below this one.
|
||||
mapped,
|
||||
// The selection before this event
|
||||
startSelection,
|
||||
// Stores selection changes after this event, to be used for
|
||||
|
@ -473,19 +481,19 @@ class HistoryState {
|
|||
isolate() {
|
||||
return this.prevTime ? new HistoryState(this.done, this.undone) : this;
|
||||
}
|
||||
addChanges(event, time, userEvent, newGroupDelay, maxLen) {
|
||||
addChanges(event, time, userEvent, config, tr) {
|
||||
let done = this.done, lastEvent = done[done.length - 1];
|
||||
if (lastEvent && lastEvent.changes && !lastEvent.changes.empty && event.changes &&
|
||||
(!userEvent || joinableUserEvent.test(userEvent)) &&
|
||||
((!lastEvent.selectionsAfter.length &&
|
||||
time - this.prevTime < newGroupDelay &&
|
||||
isAdjacent(lastEvent.changes, event.changes)) ||
|
||||
time - this.prevTime < config.newGroupDelay &&
|
||||
config.joinToEvent(tr, isAdjacent(lastEvent.changes, event.changes))) ||
|
||||
// For compose (but not compose.start) events, always join with previous event
|
||||
userEvent == "input.type.compose")) {
|
||||
done = updateBranch(done, done.length - 1, maxLen, new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects), lastEvent.mapped, lastEvent.startSelection, none));
|
||||
done = updateBranch(done, done.length - 1, config.minDepth, new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects), lastEvent.mapped, lastEvent.startSelection, none));
|
||||
}
|
||||
else {
|
||||
done = updateBranch(done, done.length, maxLen, event);
|
||||
done = updateBranch(done, done.length, config.minDepth, event);
|
||||
}
|
||||
return new HistoryState(done, none, time, userEvent);
|
||||
}
|
||||
|
@ -502,7 +510,7 @@ class HistoryState {
|
|||
return new HistoryState(addMappingToBranch(this.done, mapping), addMappingToBranch(this.undone, mapping), this.prevTime, this.prevUserEvent);
|
||||
}
|
||||
pop(side, state, selection) {
|
||||
let branch = side == 0 /* Done */ ? this.done : this.undone;
|
||||
let branch = side == 0 /* BranchName.Done */ ? this.done : this.undone;
|
||||
if (branch.length == 0)
|
||||
return null;
|
||||
let event = branch[branch.length - 1];
|
||||
|
@ -510,7 +518,7 @@ class HistoryState {
|
|||
return state.update({
|
||||
selection: event.selectionsAfter[event.selectionsAfter.length - 1],
|
||||
annotations: fromHistory.of({ side, rest: popSelection(branch) }),
|
||||
userEvent: side == 0 /* Done */ ? "select.undo" : "select.redo",
|
||||
userEvent: side == 0 /* BranchName.Done */ ? "select.undo" : "select.redo",
|
||||
scrollIntoView: true
|
||||
});
|
||||
}
|
||||
|
@ -527,7 +535,7 @@ class HistoryState {
|
|||
effects: event.effects,
|
||||
annotations: fromHistory.of({ side, rest }),
|
||||
filter: false,
|
||||
userEvent: side == 0 /* Done */ ? "undo" : "redo",
|
||||
userEvent: side == 0 /* BranchName.Done */ ? "undo" : "redo",
|
||||
scrollIntoView: true
|
||||
});
|
||||
}
|
||||
|
@ -538,13 +546,14 @@ HistoryState.empty = /*@__PURE__*/new HistoryState(none, none);
|
|||
Default key bindings for the undo history.
|
||||
|
||||
- Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo).
|
||||
- Mod-y (Mod-Shift-z on macOS): [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||
- Mod-y (Mod-Shift-z on macOS) + Ctrl-Shift-z on Linux: [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
||||
- Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection).
|
||||
- Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection).
|
||||
*/
|
||||
const historyKeymap = [
|
||||
{ key: "Mod-z", run: undo, preventDefault: true },
|
||||
{ key: "Mod-y", mac: "Mod-Shift-z", run: redo, preventDefault: true },
|
||||
{ linux: "Ctrl-Shift-z", run: redo, preventDefault: true },
|
||||
{ key: "Mod-u", run: undoSelection, preventDefault: true },
|
||||
{ key: "Alt-u", mac: "Mod-Shift-u", run: redoSelection, preventDefault: true }
|
||||
];
|
||||
|
@ -758,6 +767,14 @@ end of the indentation instead of the start of the line.
|
|||
*/
|
||||
const cursorLineBoundaryBackward = view => moveSel(view, range => moveByLineBoundary(view, range, false));
|
||||
/**
|
||||
Move the selection one line wrap point to the left.
|
||||
*/
|
||||
const cursorLineBoundaryLeft = view => moveSel(view, range => moveByLineBoundary(view, range, !ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection one line wrap point to the right.
|
||||
*/
|
||||
const cursorLineBoundaryRight = view => moveSel(view, range => moveByLineBoundary(view, range, ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection to the start of the line.
|
||||
*/
|
||||
const cursorLineStart = view => moveSel(view, range => EditorSelection.cursor(view.lineBlockAt(range.head).from, 1));
|
||||
|
@ -795,7 +812,7 @@ const selectMatchingBracket = ({ state, dispatch }) => toMatchingBracket(state,
|
|||
function extendSel(view, how) {
|
||||
let selection = updateSel(view.state.selection, range => {
|
||||
let head = how(range);
|
||||
return EditorSelection.range(range.anchor, head.head, head.goalColumn);
|
||||
return EditorSelection.range(range.anchor, head.head, head.goalColumn, head.bidiLevel || undefined);
|
||||
});
|
||||
if (selection.eq(view.state.selection))
|
||||
return false;
|
||||
|
@ -892,6 +909,14 @@ Move the selection head to the previous line boundary.
|
|||
*/
|
||||
const selectLineBoundaryBackward = view => extendSel(view, range => moveByLineBoundary(view, range, false));
|
||||
/**
|
||||
Move the selection head one line boundary to the left.
|
||||
*/
|
||||
const selectLineBoundaryLeft = view => extendSel(view, range => moveByLineBoundary(view, range, !ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection head one line boundary to the right.
|
||||
*/
|
||||
const selectLineBoundaryRight = view => extendSel(view, range => moveByLineBoundary(view, range, ltrAtCursor(view)));
|
||||
/**
|
||||
Move the selection head to the start of the line.
|
||||
*/
|
||||
const selectLineStart = view => extendSel(view, range => EditorSelection.cursor(view.lineBlockAt(range.head).from));
|
||||
|
@ -977,26 +1002,38 @@ const simplifySelection = ({ state, dispatch }) => {
|
|||
dispatch(setSel(state, selection));
|
||||
return true;
|
||||
};
|
||||
function deleteBy({ state, dispatch }, by) {
|
||||
if (state.readOnly)
|
||||
function deleteBy(target, by) {
|
||||
if (target.state.readOnly)
|
||||
return false;
|
||||
let event = "delete.selection";
|
||||
let event = "delete.selection", { state } = target;
|
||||
let changes = state.changeByRange(range => {
|
||||
let { from, to } = range;
|
||||
if (from == to) {
|
||||
let towards = by(from);
|
||||
if (towards < from)
|
||||
if (towards < from) {
|
||||
event = "delete.backward";
|
||||
else if (towards > from)
|
||||
towards = skipAtomic(target, towards, false);
|
||||
}
|
||||
else if (towards > from) {
|
||||
event = "delete.forward";
|
||||
towards = skipAtomic(target, towards, true);
|
||||
}
|
||||
from = Math.min(from, towards);
|
||||
to = Math.max(to, towards);
|
||||
}
|
||||
else {
|
||||
from = skipAtomic(target, from, false);
|
||||
to = skipAtomic(target, to, true);
|
||||
}
|
||||
return from == to ? { range } : { changes: { from, to }, range: EditorSelection.cursor(from) };
|
||||
});
|
||||
if (changes.changes.empty)
|
||||
return false;
|
||||
dispatch(state.update(changes, { scrollIntoView: true, userEvent: event }));
|
||||
target.dispatch(state.update(changes, {
|
||||
scrollIntoView: true,
|
||||
userEvent: event,
|
||||
effects: event == "delete.selection" ? EditorView.announce.of(state.phrase("Selection deleted")) : undefined
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
function skipAtomic(target, pos, forward) {
|
||||
|
@ -1024,7 +1061,7 @@ const deleteByChar = (target, forward) => deleteBy(target, pos => {
|
|||
if (targetPos == pos && line.number != (forward ? state.doc.lines : 1))
|
||||
targetPos += forward ? 1 : -1;
|
||||
}
|
||||
return skipAtomic(target, targetPos, forward);
|
||||
return targetPos;
|
||||
});
|
||||
/**
|
||||
Delete the selection, or, for cursor selections, the character
|
||||
|
@ -1053,7 +1090,7 @@ const deleteByGroup = (target, forward) => deleteBy(target, start => {
|
|||
cat = nextCat;
|
||||
pos = next;
|
||||
}
|
||||
return skipAtomic(target, pos, forward);
|
||||
return pos;
|
||||
});
|
||||
/**
|
||||
Delete the selection or backward until the end of the next
|
||||
|
@ -1072,7 +1109,7 @@ line, delete the line break after it.
|
|||
*/
|
||||
const deleteToLineEnd = view => deleteBy(view, pos => {
|
||||
let lineEnd = view.lineBlockAt(pos).to;
|
||||
return skipAtomic(view, pos < lineEnd ? lineEnd : Math.min(view.state.doc.length, pos + 1), true);
|
||||
return pos < lineEnd ? lineEnd : Math.min(view.state.doc.length, pos + 1);
|
||||
});
|
||||
/**
|
||||
Delete the selection, or, if it is a cursor selection, delete to
|
||||
|
@ -1081,7 +1118,7 @@ line, delete the line break before it.
|
|||
*/
|
||||
const deleteToLineStart = view => deleteBy(view, pos => {
|
||||
let lineStart = view.lineBlockAt(pos).from;
|
||||
return skipAtomic(view, pos > lineStart ? lineStart : Math.max(0, pos - 1), false);
|
||||
return pos > lineStart ? lineStart : Math.max(0, pos - 1);
|
||||
});
|
||||
/**
|
||||
Delete all whitespace directly before a line end from the
|
||||
|
@ -1456,11 +1493,11 @@ property changed to `mac`.)
|
|||
*/
|
||||
const standardKeymap = /*@__PURE__*/[
|
||||
{ key: "ArrowLeft", run: cursorCharLeft, shift: selectCharLeft, preventDefault: true },
|
||||
{ key: "Mod-ArrowLeft", mac: "Alt-ArrowLeft", run: cursorGroupLeft, shift: selectGroupLeft },
|
||||
{ mac: "Cmd-ArrowLeft", run: cursorLineBoundaryBackward, shift: selectLineBoundaryBackward },
|
||||
{ key: "Mod-ArrowLeft", mac: "Alt-ArrowLeft", run: cursorGroupLeft, shift: selectGroupLeft, preventDefault: true },
|
||||
{ mac: "Cmd-ArrowLeft", run: cursorLineBoundaryLeft, shift: selectLineBoundaryLeft, preventDefault: true },
|
||||
{ key: "ArrowRight", run: cursorCharRight, shift: selectCharRight, preventDefault: true },
|
||||
{ key: "Mod-ArrowRight", mac: "Alt-ArrowRight", run: cursorGroupRight, shift: selectGroupRight },
|
||||
{ mac: "Cmd-ArrowRight", run: cursorLineBoundaryForward, shift: selectLineBoundaryForward },
|
||||
{ key: "Mod-ArrowRight", mac: "Alt-ArrowRight", run: cursorGroupRight, shift: selectGroupRight, preventDefault: true },
|
||||
{ mac: "Cmd-ArrowRight", run: cursorLineBoundaryRight, shift: selectLineBoundaryRight, preventDefault: true },
|
||||
{ key: "ArrowUp", run: cursorLineUp, shift: selectLineUp, preventDefault: true },
|
||||
{ mac: "Cmd-ArrowUp", run: cursorDocStart, shift: selectDocStart },
|
||||
{ mac: "Ctrl-ArrowUp", run: cursorPageUp, shift: selectPageUp },
|
||||
|
@ -1531,4 +1568,4 @@ this.
|
|||
*/
|
||||
const indentWithTab = { key: "Tab", run: indentMore, shift: indentLess };
|
||||
|
||||
export { blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharForward, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, defaultKeymap, deleteCharBackward, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteLine, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, history, historyField, historyKeymap, indentLess, indentMore, indentSelection, indentWithTab, insertBlankLine, insertNewline, insertNewlineAndIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharForward, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, transposeChars, undo, undoDepth, undoSelection };
|
||||
export { blockComment, blockUncomment, copyLineDown, copyLineUp, cursorCharBackward, cursorCharForward, cursorCharLeft, cursorCharRight, cursorDocEnd, cursorDocStart, cursorGroupBackward, cursorGroupForward, cursorGroupLeft, cursorGroupRight, cursorLineBoundaryBackward, cursorLineBoundaryForward, cursorLineBoundaryLeft, cursorLineBoundaryRight, cursorLineDown, cursorLineEnd, cursorLineStart, cursorLineUp, cursorMatchingBracket, cursorPageDown, cursorPageUp, cursorSubwordBackward, cursorSubwordForward, cursorSyntaxLeft, cursorSyntaxRight, defaultKeymap, deleteCharBackward, deleteCharForward, deleteGroupBackward, deleteGroupForward, deleteLine, deleteToLineEnd, deleteToLineStart, deleteTrailingWhitespace, emacsStyleKeymap, history, historyField, historyKeymap, indentLess, indentMore, indentSelection, indentWithTab, insertBlankLine, insertNewline, insertNewlineAndIndent, insertTab, invertedEffects, isolateHistory, lineComment, lineUncomment, moveLineDown, moveLineUp, redo, redoDepth, redoSelection, selectAll, selectCharBackward, selectCharForward, selectCharLeft, selectCharRight, selectDocEnd, selectDocStart, selectGroupBackward, selectGroupForward, selectGroupLeft, selectGroupRight, selectLine, selectLineBoundaryBackward, selectLineBoundaryForward, selectLineBoundaryLeft, selectLineBoundaryRight, selectLineDown, selectLineEnd, selectLineStart, selectLineUp, selectMatchingBracket, selectPageDown, selectPageUp, selectParentSyntax, selectSubwordBackward, selectSubwordForward, selectSyntaxLeft, selectSyntaxRight, simplifySelection, splitLine, standardKeymap, toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment, transposeChars, undo, undoDepth, undoSelection };
|
||||
|
|
4
node_modules/@codemirror/commands/package.json
generated
vendored
4
node_modules/@codemirror/commands/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/commands",
|
||||
"version": "6.0.0",
|
||||
"version": "6.2.0",
|
||||
"description": "Collection of editing commands for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
@ -27,7 +27,7 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/state": "^6.2.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
},
|
||||
|
|
2
node_modules/@codemirror/language/.github/workflows/dispatch.yml
generated
vendored
2
node_modules/@codemirror/language/.github/workflows/dispatch.yml
generated
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
with:
|
||||
# You should create a personal access token and store it in your repository
|
||||
token: ${{ secrets.DISPATCH_AUTH }}
|
||||
repo: codemirror.next
|
||||
repo: dev
|
||||
owner: codemirror
|
||||
event_type: push
|
||||
|
|
64
node_modules/@codemirror/language/CHANGELOG.md
generated
vendored
64
node_modules/@codemirror/language/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,67 @@
|
|||
## 6.5.0 (2023-02-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make indentation for stream languages more reliable by having `StringStream.indentation` return overridden indentations from the indent context.
|
||||
|
||||
### New features
|
||||
|
||||
The `toggleFold` command folds or unfolds depending on whether there's an existing folded range on the current line.
|
||||
|
||||
`indentUnit` now accepts any (repeated) whitespace character, not just spaces and tabs.
|
||||
|
||||
## 6.4.0 (2023-01-12)
|
||||
|
||||
### New features
|
||||
|
||||
The `bracketMatchingHandle` node prop can now be used to limit bracket matching behavior for larger nodes to a single subnode (for example the tag name of an HTML tag).
|
||||
|
||||
## 6.3.2 (2022-12-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused `ensureSyntaxTree` to return incomplete trees when using a viewport-aware parser like `StreamLanguage`.
|
||||
|
||||
## 6.3.1 (2022-11-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make syntax-based folding include syntax nodes that start right at the end of a line as potential fold targets.
|
||||
|
||||
Fix the `indentService` protocol to allow a distinction between declining to handle the indentation and returning null to indicate the line has no definite indentation.
|
||||
|
||||
## 6.3.0 (2022-10-24)
|
||||
|
||||
### New features
|
||||
|
||||
`HighlightStyle` objects now have a `specs` property holding the tag styles that were used to define them.
|
||||
|
||||
`Language` objects now have a `name` field holding the language name.
|
||||
|
||||
## 6.2.1 (2022-07-21)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug where `bracketMatching` would incorrectly match nested brackets in syntax trees that put multiple pairs of brackets in the same parent node.
|
||||
|
||||
Fix a bug that could cause `indentRange` to loop infinitely.
|
||||
|
||||
## 6.2.0 (2022-06-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that prevented bracket matching to recognize plain brackets inside a language parsed as an overlay.
|
||||
|
||||
### New features
|
||||
|
||||
The `indentRange` function provides an easy way to programatically auto-indent a range of the document.
|
||||
|
||||
## 6.1.0 (2022-06-20)
|
||||
|
||||
### New features
|
||||
|
||||
The `foldState` field is now public, and can be used to serialize and deserialize the fold state.
|
||||
|
||||
## 6.0.0 (2022-06-08)
|
||||
|
||||
### New features
|
||||
|
|
2
node_modules/@codemirror/language/LICENSE
generated
vendored
2
node_modules/@codemirror/language/LICENSE
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (C) 2018-2021 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
10
node_modules/@codemirror/language/README.md
generated
vendored
10
node_modules/@codemirror/language/README.md
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
# @codemirror/language [](https://www.npmjs.org/package/@codemirror/language)
|
||||
|
||||
[ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#language) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/language/blob/main/CHANGELOG.md) ]
|
||||
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#language) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/language/blob/main/CHANGELOG.md) ]
|
||||
|
||||
This package implements the language support infrastructure for the
|
||||
[CodeMirror](https://codemirror.net/6/) code editor.
|
||||
[CodeMirror](https://codemirror.net/) code editor.
|
||||
|
||||
The [project page](https://codemirror.net/6/) has more information, a
|
||||
number of [examples](https://codemirror.net/6/examples/) and the
|
||||
[documentation](https://codemirror.net/6/docs/).
|
||||
The [project page](https://codemirror.net/) has more information, a
|
||||
number of [examples](https://codemirror.net/examples/) and the
|
||||
[documentation](https://codemirror.net/docs/).
|
||||
|
||||
This code is released under an
|
||||
[MIT license](https://github.com/codemirror/language/tree/main/LICENSE).
|
||||
|
|
298
node_modules/@codemirror/language/dist/index.cjs
generated
vendored
298
node_modules/@codemirror/language/dist/index.cjs
generated
vendored
|
@ -49,8 +49,13 @@ class Language {
|
|||
The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet
|
||||
used for this language.
|
||||
*/
|
||||
data, parser, extraExtensions = []) {
|
||||
data, parser, extraExtensions = [],
|
||||
/**
|
||||
A language name.
|
||||
*/
|
||||
name = "") {
|
||||
this.data = data;
|
||||
this.name = name;
|
||||
// Kludge to define EditorState.tree as a debugging helper,
|
||||
// without the EditorState package actually knowing about
|
||||
// languages and lezer trees.
|
||||
|
@ -138,8 +143,8 @@ A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language)
|
|||
parsers.
|
||||
*/
|
||||
class LRLanguage extends Language {
|
||||
constructor(data, parser) {
|
||||
super(data, parser);
|
||||
constructor(data, parser, name) {
|
||||
super(data, parser, [], name);
|
||||
this.parser = parser;
|
||||
}
|
||||
/**
|
||||
|
@ -149,14 +154,14 @@ class LRLanguage extends Language {
|
|||
let data = defineLanguageFacet(spec.languageData);
|
||||
return new LRLanguage(data, spec.parser.configure({
|
||||
props: [languageDataProp.add(type => type.isTop ? data : undefined)]
|
||||
}));
|
||||
}), spec.name);
|
||||
}
|
||||
/**
|
||||
Create a new instance of this language with a reconfigured
|
||||
version of its parser.
|
||||
version of its parser and optionally a new name.
|
||||
*/
|
||||
configure(options) {
|
||||
return new LRLanguage(this.data, this.parser.configure(options));
|
||||
configure(options, name) {
|
||||
return new LRLanguage(this.data, this.parser.configure(options), name || this.name);
|
||||
}
|
||||
get allowsNesting() { return this.parser.hasWrappers(); }
|
||||
}
|
||||
|
@ -178,7 +183,13 @@ up to that point if the tree isn't already available.
|
|||
function ensureSyntaxTree(state, upto, timeout = 50) {
|
||||
var _a;
|
||||
let parse = (_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context;
|
||||
return !parse ? null : parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
|
||||
if (!parse)
|
||||
return null;
|
||||
let oldVieport = parse.viewport;
|
||||
parse.updateViewport({ from: 0, to: upto });
|
||||
let result = parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
|
||||
parse.updateViewport(oldVieport);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
Queries whether there is a full syntax tree available up to the
|
||||
|
@ -218,13 +229,13 @@ function syntaxParserRunning(view) {
|
|||
}
|
||||
// Lezer-style Input object for a Text document.
|
||||
class DocInput {
|
||||
constructor(doc, length = doc.length) {
|
||||
constructor(doc) {
|
||||
this.doc = doc;
|
||||
this.length = length;
|
||||
this.cursorPos = 0;
|
||||
this.string = "";
|
||||
this.cursor = doc.iter();
|
||||
}
|
||||
get length() { return this.doc.length; }
|
||||
syncTo(pos) {
|
||||
this.string = this.cursor.next(pos - this.cursorPos).value;
|
||||
this.cursorPos = pos + this.string.length;
|
||||
|
@ -503,14 +514,14 @@ class LanguageState {
|
|||
// state updates with parse work beyond the viewport.
|
||||
let upto = this.context.treeLen == tr.startState.doc.length ? undefined
|
||||
: Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
||||
if (!newCx.work(20 /* Apply */, upto))
|
||||
if (!newCx.work(20 /* Work.Apply */, upto))
|
||||
newCx.takeTree();
|
||||
return new LanguageState(newCx);
|
||||
}
|
||||
static init(state) {
|
||||
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
||||
let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
|
||||
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
||||
if (!parseState.work(20 /* Apply */, vpTo))
|
||||
if (!parseState.work(20 /* Work.Apply */, vpTo))
|
||||
parseState.takeTree();
|
||||
return new LanguageState(parseState);
|
||||
}
|
||||
|
@ -527,14 +538,14 @@ Language.state = state.StateField.define({
|
|||
}
|
||||
});
|
||||
let requestIdle = (callback) => {
|
||||
let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
|
||||
let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
|
||||
return () => clearTimeout(timeout);
|
||||
};
|
||||
if (typeof requestIdleCallback != "undefined")
|
||||
requestIdle = (callback) => {
|
||||
let idle = -1, timeout = setTimeout(() => {
|
||||
idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
|
||||
}, 100 /* MinPause */);
|
||||
idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
|
||||
}, 100 /* Work.MinPause */);
|
||||
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
||||
};
|
||||
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
||||
|
@ -557,7 +568,7 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|||
this.scheduleWork();
|
||||
if (update.docChanged) {
|
||||
if (this.view.hasFocus)
|
||||
this.chunkBudget += 50 /* ChangeBonus */;
|
||||
this.chunkBudget += 50 /* Work.ChangeBonus */;
|
||||
this.scheduleWork();
|
||||
}
|
||||
this.checkAsyncSchedule(cx);
|
||||
|
@ -573,19 +584,19 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|||
this.working = null;
|
||||
let now = Date.now();
|
||||
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
|
||||
this.chunkEnd = now + 30000 /* ChunkTime */;
|
||||
this.chunkBudget = 3000 /* ChunkBudget */;
|
||||
this.chunkEnd = now + 30000 /* Work.ChunkTime */;
|
||||
this.chunkBudget = 3000 /* Work.ChunkBudget */;
|
||||
}
|
||||
if (this.chunkBudget <= 0)
|
||||
return; // No more budget
|
||||
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
||||
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
||||
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
|
||||
return;
|
||||
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
||||
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
||||
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
||||
let done = field.context.work(() => {
|
||||
return isInputPending && isInputPending() || Date.now() > endTime;
|
||||
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
||||
}, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
|
||||
this.chunkBudget -= Date.now() - now;
|
||||
if (done || this.chunkBudget <= 0) {
|
||||
field.context.takeTree();
|
||||
|
@ -616,11 +627,21 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|||
eventHandlers: { focus() { this.scheduleWork(); } }
|
||||
});
|
||||
/**
|
||||
The facet used to associate a language with an editor state.
|
||||
The facet used to associate a language with an editor state. Used
|
||||
by `Language` object's `extension` property (so you don't need to
|
||||
manually wrap your languages in this). Can be used to access the
|
||||
current language on a state.
|
||||
*/
|
||||
const language = state.Facet.define({
|
||||
combine(languages) { return languages.length ? languages[0] : null; },
|
||||
enables: [Language.state, parseWorker]
|
||||
enables: language => [
|
||||
Language.state,
|
||||
parseWorker,
|
||||
view.EditorView.contentAttributes.compute([language], state => {
|
||||
let lang = state.facet(language);
|
||||
return lang && lang.name ? { "data-language": lang.name } : {};
|
||||
})
|
||||
]
|
||||
});
|
||||
/**
|
||||
This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an
|
||||
|
@ -750,22 +771,27 @@ class LanguageDescription {
|
|||
|
||||
/**
|
||||
Facet that defines a way to provide a function that computes the
|
||||
appropriate indentation depth at the start of a given line, or
|
||||
`null` to indicate no appropriate indentation could be determined.
|
||||
appropriate indentation depth, as a column number (see
|
||||
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
|
||||
line. A return value of `null` indicates no indentation can be
|
||||
determined, and the line should inherit the indentation of the one
|
||||
above it. A return value of `undefined` defers to the next indent
|
||||
service.
|
||||
*/
|
||||
const indentService = state.Facet.define();
|
||||
/**
|
||||
Facet for overriding the unit by which indentation happens.
|
||||
Should be a string consisting either entirely of spaces or
|
||||
entirely of tabs. When not set, this defaults to 2 spaces.
|
||||
Facet for overriding the unit by which indentation happens. Should
|
||||
be a string consisting either entirely of the same whitespace
|
||||
character. When not set, this defaults to 2 spaces.
|
||||
*/
|
||||
const indentUnit = state.Facet.define({
|
||||
combine: values => {
|
||||
if (!values.length)
|
||||
return " ";
|
||||
if (!/^(?: +|\t+)$/.test(values[0]))
|
||||
let unit = values[0];
|
||||
if (!unit || /\S/.test(unit) || Array.from(unit).some(e => e != unit[0]))
|
||||
throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));
|
||||
return values[0];
|
||||
return unit;
|
||||
}
|
||||
});
|
||||
/**
|
||||
|
@ -785,36 +811,64 @@ Will use tabs for as much of the columns as possible when the
|
|||
tabs.
|
||||
*/
|
||||
function indentString(state, cols) {
|
||||
let result = "", ts = state.tabSize;
|
||||
if (state.facet(indentUnit).charCodeAt(0) == 9)
|
||||
let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];
|
||||
if (ch == "\t") {
|
||||
while (cols >= ts) {
|
||||
result += "\t";
|
||||
cols -= ts;
|
||||
}
|
||||
ch = " ";
|
||||
}
|
||||
for (let i = 0; i < cols; i++)
|
||||
result += " ";
|
||||
result += ch;
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
Get the indentation at the given position. Will first consult any
|
||||
[indent services](https://codemirror.net/6/docs/ref/#language.indentService) that are registered,
|
||||
and if none of those return an indentation, this will check the
|
||||
syntax tree for the [indent node prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp)
|
||||
and use that if found. Returns a number when an indentation could
|
||||
be determined, and null otherwise.
|
||||
Get the indentation, as a column number, at the given position.
|
||||
Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
||||
that are registered, and if none of those return an indentation,
|
||||
this will check the syntax tree for the [indent node
|
||||
prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
|
||||
number when an indentation could be determined, and null
|
||||
otherwise.
|
||||
*/
|
||||
function getIndentation(context, pos) {
|
||||
if (context instanceof state.EditorState)
|
||||
context = new IndentContext(context);
|
||||
for (let service of context.state.facet(indentService)) {
|
||||
let result = service(context, pos);
|
||||
if (result != null)
|
||||
if (result !== undefined)
|
||||
return result;
|
||||
}
|
||||
let tree = syntaxTree(context.state);
|
||||
return tree ? syntaxIndentation(context, tree, pos) : null;
|
||||
}
|
||||
/**
|
||||
Create a change set that auto-indents all lines touched by the
|
||||
given document range.
|
||||
*/
|
||||
function indentRange(state, from, to) {
|
||||
let updated = Object.create(null);
|
||||
let context = new IndentContext(state, { overrideIndentation: start => { var _a; return (_a = updated[start]) !== null && _a !== void 0 ? _a : -1; } });
|
||||
let changes = [];
|
||||
for (let pos = from; pos <= to;) {
|
||||
let line = state.doc.lineAt(pos);
|
||||
pos = line.to + 1;
|
||||
let indent = getIndentation(context, line.from);
|
||||
if (indent == null)
|
||||
continue;
|
||||
if (!/\S/.test(line.text))
|
||||
indent = 0;
|
||||
let cur = /^\s*/.exec(line.text)[0];
|
||||
let norm = indentString(state, indent);
|
||||
if (cur != norm) {
|
||||
updated[line.from] = indent;
|
||||
changes.push({ from: line.from, to: line.from + cur.length, insert: norm });
|
||||
}
|
||||
}
|
||||
return state.changes(changes);
|
||||
}
|
||||
/**
|
||||
Indentation contexts are used when calling [indentation
|
||||
services](https://codemirror.net/6/docs/ref/#language.indentService). They provide helper utilities
|
||||
useful in indentation logic, and can selectively override the
|
||||
|
@ -911,8 +965,9 @@ class IndentContext {
|
|||
/**
|
||||
A syntax tree node prop used to associate indentation strategies
|
||||
with node types. Such a strategy is a function from an indentation
|
||||
context to a column number or null, where null indicates that no
|
||||
definitive indentation can be determined.
|
||||
context to a column number (see also
|
||||
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
|
||||
indicates that no definitive indentation can be determined.
|
||||
*/
|
||||
const indentNodeProp = new common.NodeProp();
|
||||
// Compute the indentation for a given position from the syntax tree.
|
||||
|
@ -1143,7 +1198,7 @@ function syntaxFolding(state, start, end) {
|
|||
let tree = syntaxTree(state);
|
||||
if (tree.length < end)
|
||||
return null;
|
||||
let inner = tree.resolveInner(end);
|
||||
let inner = tree.resolveInner(end, 1);
|
||||
let found = null;
|
||||
for (let cur = inner; cur; cur = cur.parent) {
|
||||
if (cur.to <= end || cur.from > end)
|
||||
|
@ -1204,6 +1259,13 @@ function selectedLines(view) {
|
|||
}
|
||||
return lines;
|
||||
}
|
||||
/**
|
||||
The state field that stores the folded ranges (as a [decoration
|
||||
set](https://codemirror.net/6/docs/ref/#view.DecorationSet)). Can be passed to
|
||||
[`EditorState.toJSON`](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) and
|
||||
[`fromJSON`](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) to serialize the fold
|
||||
state.
|
||||
*/
|
||||
const foldState = state.StateField.define({
|
||||
create() {
|
||||
return view.Decoration.none;
|
||||
|
@ -1231,7 +1293,24 @@ const foldState = state.StateField.define({
|
|||
}
|
||||
return folded;
|
||||
},
|
||||
provide: f => view.EditorView.decorations.from(f)
|
||||
provide: f => view.EditorView.decorations.from(f),
|
||||
toJSON(folded, state) {
|
||||
let ranges = [];
|
||||
folded.between(0, state.doc.length, (from, to) => { ranges.push(from, to); });
|
||||
return ranges;
|
||||
},
|
||||
fromJSON(value) {
|
||||
if (!Array.isArray(value) || value.length % 2)
|
||||
throw new RangeError("Invalid JSON for fold state");
|
||||
let ranges = [];
|
||||
for (let i = 0; i < value.length;) {
|
||||
let from = value[i++], to = value[i++];
|
||||
if (typeof from != "number" || typeof to != "number")
|
||||
throw new RangeError("Invalid JSON for fold state");
|
||||
ranges.push(foldWidget.range(from, to));
|
||||
}
|
||||
return view.Decoration.set(ranges, true);
|
||||
}
|
||||
});
|
||||
/**
|
||||
Get a [range set](https://codemirror.net/6/docs/ref/#state.RangeSet) containing the folded ranges
|
||||
|
@ -1324,6 +1403,41 @@ const unfoldAll = view => {
|
|||
view.dispatch({ effects });
|
||||
return true;
|
||||
};
|
||||
// Find the foldable region containing the given line, if one exists
|
||||
function foldableContainer(view, lineBlock) {
|
||||
// Look backwards through line blocks until we find a foldable region that
|
||||
// intersects with the line
|
||||
for (let line = lineBlock;;) {
|
||||
let foldableRegion = foldable(view.state, line.from, line.to);
|
||||
if (foldableRegion && foldableRegion.to > lineBlock.from)
|
||||
return foldableRegion;
|
||||
if (!line.from)
|
||||
return null;
|
||||
line = view.lineBlockAt(line.from - 1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
Toggle folding at cursors. Unfolds if there is an existing fold
|
||||
starting in that line, tries to find a foldable range around it
|
||||
otherwise.
|
||||
*/
|
||||
const toggleFold = (view) => {
|
||||
let effects = [];
|
||||
for (let line of selectedLines(view)) {
|
||||
let folded = findFold(view.state, line.from, line.to);
|
||||
if (folded) {
|
||||
effects.push(unfoldEffect.of(folded), announceFold(view, folded, false));
|
||||
}
|
||||
else {
|
||||
let foldRange = foldableContainer(view, line);
|
||||
if (foldRange)
|
||||
effects.push(foldEffect.of(foldRange), announceFold(view, foldRange));
|
||||
}
|
||||
}
|
||||
if (effects.length > 0)
|
||||
view.dispatch({ effects: maybeEnable(view.state, effects) });
|
||||
return !!effects.length;
|
||||
};
|
||||
/**
|
||||
Default fold-related key bindings.
|
||||
|
||||
|
@ -1479,7 +1593,12 @@ A highlight style associates CSS styles with higlighting
|
|||
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
||||
*/
|
||||
class HighlightStyle {
|
||||
constructor(spec, options) {
|
||||
constructor(
|
||||
/**
|
||||
The tag styles used to create this highlight style.
|
||||
*/
|
||||
specs, options) {
|
||||
this.specs = specs;
|
||||
let modSpec;
|
||||
function def(spec) {
|
||||
let cls = styleMod.StyleModule.newName();
|
||||
|
@ -1490,7 +1609,7 @@ class HighlightStyle {
|
|||
const scopeOpt = options.scope;
|
||||
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
|
||||
: scopeOpt ? (type) => type == scopeOpt : undefined;
|
||||
this.style = highlight.tagHighlighter(spec.map(style => ({
|
||||
this.style = highlight.tagHighlighter(specs.map(style => ({
|
||||
tag: style.tag,
|
||||
class: style.class || def(Object.assign({}, style, { tag: null }))
|
||||
})), {
|
||||
|
@ -1607,7 +1726,7 @@ A default highlight style (works well with light themes).
|
|||
*/
|
||||
const defaultHighlightStyle = HighlightStyle.define([
|
||||
{ tag: highlight.tags.meta,
|
||||
color: "#7a757a" },
|
||||
color: "#404740" },
|
||||
{ tag: highlight.tags.link,
|
||||
textDecoration: "underline" },
|
||||
{ tag: highlight.tags.heading,
|
||||
|
@ -1706,6 +1825,15 @@ highlighting style is used to indicate this.
|
|||
function bracketMatching(config = {}) {
|
||||
return [bracketMatchingConfig.of(config), bracketMatchingUnique];
|
||||
}
|
||||
/**
|
||||
When larger syntax nodes, such as HTML tags, are marked as
|
||||
opening/closing, it can be a bit messy to treat the whole node as
|
||||
a matchable bracket. This node prop allows you to define, for such
|
||||
a node, a ‘handle’—the part of the node that is highlighted, and
|
||||
that the cursor must be on to activate highlighting in the first
|
||||
place.
|
||||
*/
|
||||
const bracketMatchingHandle = new common.NodeProp();
|
||||
function matchingNodes(node, dir, brackets) {
|
||||
let byProp = node.prop(dir < 0 ? common.NodeProp.openedBy : common.NodeProp.closedBy);
|
||||
if (byProp)
|
||||
|
@ -1717,6 +1845,10 @@ function matchingNodes(node, dir, brackets) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
function findHandle(node) {
|
||||
let hasHandle = node.type.prop(bracketMatchingHandle);
|
||||
return hasHandle ? hasHandle(node.node) : node;
|
||||
}
|
||||
/**
|
||||
Find the matching bracket for the token at `pos`, scanning
|
||||
direction `dir`. Only the `brackets` and `maxScanDistance`
|
||||
|
@ -1728,31 +1860,37 @@ function matchBrackets(state, pos, dir, config = {}) {
|
|||
let tree = syntaxTree(state), node = tree.resolveInner(pos, dir);
|
||||
for (let cur = node; cur; cur = cur.parent) {
|
||||
let matches = matchingNodes(cur.type, dir, brackets);
|
||||
if (matches && cur.from < cur.to)
|
||||
return matchMarkedBrackets(state, pos, dir, cur, matches, brackets);
|
||||
if (matches && cur.from < cur.to) {
|
||||
let handle = findHandle(cur);
|
||||
if (handle && (dir > 0 ? pos >= handle.from && pos < handle.to : pos > handle.from && pos <= handle.to))
|
||||
return matchMarkedBrackets(state, pos, dir, cur, handle, matches, brackets);
|
||||
}
|
||||
}
|
||||
return matchPlainBrackets(state, pos, dir, tree, node.type, maxScanDistance, brackets);
|
||||
}
|
||||
function matchMarkedBrackets(_state, _pos, dir, token, matching, brackets) {
|
||||
let parent = token.parent, firstToken = { from: token.from, to: token.to };
|
||||
function matchMarkedBrackets(_state, _pos, dir, token, handle, matching, brackets) {
|
||||
let parent = token.parent, firstToken = { from: handle.from, to: handle.to };
|
||||
let depth = 0, cursor = parent === null || parent === void 0 ? void 0 : parent.cursor();
|
||||
if (cursor && (dir < 0 ? cursor.childBefore(token.from) : cursor.childAfter(token.to)))
|
||||
do {
|
||||
if (dir < 0 ? cursor.to <= token.from : cursor.from >= token.to) {
|
||||
if (depth == 0 && matching.indexOf(cursor.type.name) > -1 && cursor.from < cursor.to) {
|
||||
return { start: firstToken, end: { from: cursor.from, to: cursor.to }, matched: true };
|
||||
let endHandle = findHandle(cursor);
|
||||
return { start: firstToken, end: endHandle ? { from: endHandle.from, to: endHandle.to } : undefined, matched: true };
|
||||
}
|
||||
else if (matchingNodes(cursor.type, dir, brackets)) {
|
||||
depth++;
|
||||
}
|
||||
else if (matchingNodes(cursor.type, -dir, brackets)) {
|
||||
depth--;
|
||||
if (depth == 0)
|
||||
if (depth == 0) {
|
||||
let endHandle = findHandle(cursor);
|
||||
return {
|
||||
start: firstToken,
|
||||
end: cursor.from == cursor.to ? undefined : { from: cursor.from, to: cursor.to },
|
||||
end: endHandle && endHandle.from < endHandle.to ? { from: endHandle.from, to: endHandle.to } : undefined,
|
||||
matched: false
|
||||
};
|
||||
}
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
} while (dir < 0 ? cursor.prevSibling() : cursor.nextSibling());
|
||||
|
@ -1772,7 +1910,7 @@ function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, b
|
|||
let basePos = pos + distance * dir;
|
||||
for (let pos = dir > 0 ? 0 : text.length - 1, end = dir > 0 ? text.length : -1; pos != end; pos += dir) {
|
||||
let found = brackets.indexOf(text[pos]);
|
||||
if (found < 0 || tree.resolve(basePos + pos, 1).type != tokenType)
|
||||
if (found < 0 || tree.resolveInner(basePos + pos, 1).type != tokenType)
|
||||
continue;
|
||||
if ((found % 2 == 0) == (dir > 0)) {
|
||||
depth++;
|
||||
|
@ -1823,10 +1961,11 @@ class StringStream {
|
|||
/**
|
||||
The current indent unit size.
|
||||
*/
|
||||
indentUnit) {
|
||||
indentUnit, overrideIndent) {
|
||||
this.string = string;
|
||||
this.tabSize = tabSize;
|
||||
this.indentUnit = indentUnit;
|
||||
this.overrideIndent = overrideIndent;
|
||||
/**
|
||||
The current position on the line.
|
||||
*/
|
||||
|
@ -1927,7 +2066,8 @@ class StringStream {
|
|||
Get the indentation column of the current line.
|
||||
*/
|
||||
indentation() {
|
||||
return countCol(this.string, null, this.tabSize);
|
||||
var _a;
|
||||
return (_a = this.overrideIndent) !== null && _a !== void 0 ? _a : countCol(this.string, null, this.tabSize);
|
||||
}
|
||||
/**
|
||||
Match the input against the given string or regular expression
|
||||
|
@ -1969,6 +2109,7 @@ class StringStream {
|
|||
|
||||
function fullParser(spec) {
|
||||
return {
|
||||
name: spec.name || "",
|
||||
token: spec.token,
|
||||
blankLine: spec.blankLine || (() => { }),
|
||||
startState: spec.startState || (() => true),
|
||||
|
@ -1988,6 +2129,7 @@ function defaultCopyState(state) {
|
|||
}
|
||||
return newState;
|
||||
}
|
||||
const IndentedFrom = new WeakMap();
|
||||
/**
|
||||
A [language](https://codemirror.net/6/docs/ref/#language.Language) class based on a CodeMirror
|
||||
5-style [streaming parser](https://codemirror.net/6/docs/ref/#language.StreamParser).
|
||||
|
@ -2001,7 +2143,7 @@ class StreamLanguage extends Language {
|
|||
return new Parse(self, input, fragments, ranges);
|
||||
}
|
||||
};
|
||||
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))]);
|
||||
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
|
||||
this.topNode = docID(data);
|
||||
self = this;
|
||||
this.streamParser = p;
|
||||
|
@ -2018,7 +2160,14 @@ class StreamLanguage extends Language {
|
|||
at = at.parent;
|
||||
if (!at)
|
||||
return null;
|
||||
let start = findState(this, tree, 0, at.from, pos), statePos, state;
|
||||
let from = undefined;
|
||||
let { overrideIndentation } = cx.options;
|
||||
if (overrideIndentation) {
|
||||
from = IndentedFrom.get(cx.state);
|
||||
if (from != null && from < pos - 1e4)
|
||||
from = undefined;
|
||||
}
|
||||
let start = findState(this, tree, 0, at.from, from !== null && from !== void 0 ? from : pos), statePos, state;
|
||||
if (start) {
|
||||
state = start.state;
|
||||
statePos = start.pos + 1;
|
||||
|
@ -2027,12 +2176,13 @@ class StreamLanguage extends Language {
|
|||
state = this.streamParser.startState(cx.unit);
|
||||
statePos = 0;
|
||||
}
|
||||
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
||||
if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
|
||||
return null;
|
||||
while (statePos < pos) {
|
||||
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
||||
if (line.length) {
|
||||
let stream = new StringStream(line.text, cx.state.tabSize, cx.unit);
|
||||
let indentation = overrideIndentation ? overrideIndentation(line.from) : -1;
|
||||
let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation);
|
||||
while (stream.pos < end - line.from)
|
||||
readToken(this.streamParser.token, stream, state);
|
||||
}
|
||||
|
@ -2043,8 +2193,10 @@ class StreamLanguage extends Language {
|
|||
break;
|
||||
statePos = line.to + 1;
|
||||
}
|
||||
let { text } = cx.lineAt(pos);
|
||||
return this.streamParser.indent(state, /^\s*(.*)/.exec(text)[1], cx);
|
||||
let line = cx.lineAt(pos);
|
||||
if (overrideIndentation && from == null)
|
||||
IndentedFrom.set(cx.state, line.from);
|
||||
return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
|
||||
}
|
||||
get allowsNesting() { return false; }
|
||||
}
|
||||
|
@ -2106,7 +2258,7 @@ class Parse {
|
|||
this.chunks.push(tree.children[i]);
|
||||
this.chunkPos.push(tree.positions[i]);
|
||||
}
|
||||
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
||||
if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) {
|
||||
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
||||
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
||||
this.parsedPos = context.viewport.from;
|
||||
|
@ -2116,7 +2268,7 @@ class Parse {
|
|||
advance() {
|
||||
let context = ParseContext.get();
|
||||
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
||||
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
||||
let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */);
|
||||
if (context)
|
||||
end = Math.min(end, context.viewport.to);
|
||||
while (this.parsedPos < end)
|
||||
|
@ -2200,7 +2352,7 @@ class Parse {
|
|||
let token = readToken(streamParser.token, stream, this.state);
|
||||
if (token)
|
||||
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
||||
if (stream.start > 10000 /* MaxLineLength */)
|
||||
if (stream.start > 10000 /* C.MaxLineLength */)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2216,7 +2368,7 @@ class Parse {
|
|||
length: this.parsedPos - this.chunkStart,
|
||||
nodeSet,
|
||||
topID: 0,
|
||||
maxBufferLength: 2048 /* ChunkSize */,
|
||||
maxBufferLength: 2048 /* C.ChunkSize */,
|
||||
reused: this.chunkReused
|
||||
});
|
||||
tree = new common.Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|
||||
|
@ -2249,8 +2401,8 @@ for (let [legacyName, name] of [
|
|||
["variable-2", "variableName.special"],
|
||||
["string-2", "string.special"],
|
||||
["def", "variableName.definition"],
|
||||
["tag", "typeName"],
|
||||
["attribute", "propertyName"],
|
||||
["tag", "tagName"],
|
||||
["attribute", "attributeName"],
|
||||
["type", "typeName"],
|
||||
["builtin", "variableName.standard"],
|
||||
["qualifier", "modifier"],
|
||||
|
@ -2322,6 +2474,7 @@ exports.StreamLanguage = StreamLanguage;
|
|||
exports.StringStream = StringStream;
|
||||
exports.TreeIndentContext = TreeIndentContext;
|
||||
exports.bracketMatching = bracketMatching;
|
||||
exports.bracketMatchingHandle = bracketMatchingHandle;
|
||||
exports.codeFolding = codeFolding;
|
||||
exports.continuedIndent = continuedIndent;
|
||||
exports.defaultHighlightStyle = defaultHighlightStyle;
|
||||
|
@ -2337,6 +2490,7 @@ exports.foldInside = foldInside;
|
|||
exports.foldKeymap = foldKeymap;
|
||||
exports.foldNodeProp = foldNodeProp;
|
||||
exports.foldService = foldService;
|
||||
exports.foldState = foldState;
|
||||
exports.foldable = foldable;
|
||||
exports.foldedRanges = foldedRanges;
|
||||
exports.forceParsing = forceParsing;
|
||||
|
@ -2345,6 +2499,7 @@ exports.getIndentation = getIndentation;
|
|||
exports.highlightingFor = highlightingFor;
|
||||
exports.indentNodeProp = indentNodeProp;
|
||||
exports.indentOnInput = indentOnInput;
|
||||
exports.indentRange = indentRange;
|
||||
exports.indentService = indentService;
|
||||
exports.indentString = indentString;
|
||||
exports.indentUnit = indentUnit;
|
||||
|
@ -2355,6 +2510,7 @@ exports.syntaxHighlighting = syntaxHighlighting;
|
|||
exports.syntaxParserRunning = syntaxParserRunning;
|
||||
exports.syntaxTree = syntaxTree;
|
||||
exports.syntaxTreeAvailable = syntaxTreeAvailable;
|
||||
exports.toggleFold = toggleFold;
|
||||
exports.unfoldAll = unfoldAll;
|
||||
exports.unfoldCode = unfoldCode;
|
||||
exports.unfoldEffect = unfoldEffect;
|
||||
|
|
102
node_modules/@codemirror/language/dist/index.d.ts
generated
vendored
102
node_modules/@codemirror/language/dist/index.d.ts
generated
vendored
|
@ -1,7 +1,7 @@
|
|||
import { NodeProp, Parser, Tree, TreeFragment, SyntaxNode, NodeType } from '@lezer/common';
|
||||
import { LRParser, ParserConfig } from '@lezer/lr';
|
||||
import * as _codemirror_state from '@codemirror/state';
|
||||
import { Facet, Extension, EditorState, Range } from '@codemirror/state';
|
||||
import { Facet, Extension, EditorState, StateField, Range } from '@codemirror/state';
|
||||
import { EditorView, DecorationSet, Command, KeyBinding, ViewUpdate, BlockInfo, Decoration } from '@codemirror/view';
|
||||
import { Highlighter, Tag } from '@lezer/highlight';
|
||||
import { StyleModule, StyleSpec } from 'style-mod';
|
||||
|
@ -48,6 +48,10 @@ declare class Language {
|
|||
[name: string]: any;
|
||||
}>;
|
||||
/**
|
||||
A language name.
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
The extension value to install this as the document language.
|
||||
*/
|
||||
readonly extension: Extension;
|
||||
|
@ -70,7 +74,11 @@ declare class Language {
|
|||
*/
|
||||
data: Facet<{
|
||||
[name: string]: any;
|
||||
}>, parser: Parser, extraExtensions?: Extension[]);
|
||||
}>, parser: Parser, extraExtensions?: Extension[],
|
||||
/**
|
||||
A language name.
|
||||
*/
|
||||
name?: string);
|
||||
/**
|
||||
Query whether this language is active at the given position.
|
||||
*/
|
||||
|
@ -102,6 +110,10 @@ declare class LRLanguage extends Language {
|
|||
Define a language from a parser.
|
||||
*/
|
||||
static define(spec: {
|
||||
/**
|
||||
The [name](https://codemirror.net/6/docs/ref/#Language.name) of the language.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
The parser to use. Should already have added editor-relevant
|
||||
node props (and optionally things like dialect and top rule)
|
||||
|
@ -118,9 +130,9 @@ declare class LRLanguage extends Language {
|
|||
}): LRLanguage;
|
||||
/**
|
||||
Create a new instance of this language with a reconfigured
|
||||
version of its parser.
|
||||
version of its parser and optionally a new name.
|
||||
*/
|
||||
configure(options: ParserConfig): LRLanguage;
|
||||
configure(options: ParserConfig, name?: string): LRLanguage;
|
||||
get allowsNesting(): boolean;
|
||||
}
|
||||
/**
|
||||
|
@ -214,7 +226,10 @@ declare class ParseContext {
|
|||
static get(): ParseContext | null;
|
||||
}
|
||||
/**
|
||||
The facet used to associate a language with an editor state.
|
||||
The facet used to associate a language with an editor state. Used
|
||||
by `Language` object's `extension` property (so you don't need to
|
||||
manually wrap your languages in this). Can be used to access the
|
||||
current language on a state.
|
||||
*/
|
||||
declare const language: Facet<Language, Language | null>;
|
||||
/**
|
||||
|
@ -346,14 +361,18 @@ declare class LanguageDescription {
|
|||
|
||||
/**
|
||||
Facet that defines a way to provide a function that computes the
|
||||
appropriate indentation depth at the start of a given line, or
|
||||
`null` to indicate no appropriate indentation could be determined.
|
||||
appropriate indentation depth, as a column number (see
|
||||
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
|
||||
line. A return value of `null` indicates no indentation can be
|
||||
determined, and the line should inherit the indentation of the one
|
||||
above it. A return value of `undefined` defers to the next indent
|
||||
service.
|
||||
*/
|
||||
declare const indentService: Facet<(context: IndentContext, pos: number) => number | null, readonly ((context: IndentContext, pos: number) => number | null)[]>;
|
||||
declare const indentService: Facet<(context: IndentContext, pos: number) => number | null | undefined, readonly ((context: IndentContext, pos: number) => number | null | undefined)[]>;
|
||||
/**
|
||||
Facet for overriding the unit by which indentation happens.
|
||||
Should be a string consisting either entirely of spaces or
|
||||
entirely of tabs. When not set, this defaults to 2 spaces.
|
||||
Facet for overriding the unit by which indentation happens. Should
|
||||
be a string consisting either entirely of the same whitespace
|
||||
character. When not set, this defaults to 2 spaces.
|
||||
*/
|
||||
declare const indentUnit: Facet<string, string>;
|
||||
/**
|
||||
|
@ -371,15 +390,21 @@ tabs.
|
|||
*/
|
||||
declare function indentString(state: EditorState, cols: number): string;
|
||||
/**
|
||||
Get the indentation at the given position. Will first consult any
|
||||
[indent services](https://codemirror.net/6/docs/ref/#language.indentService) that are registered,
|
||||
and if none of those return an indentation, this will check the
|
||||
syntax tree for the [indent node prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp)
|
||||
and use that if found. Returns a number when an indentation could
|
||||
be determined, and null otherwise.
|
||||
Get the indentation, as a column number, at the given position.
|
||||
Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
||||
that are registered, and if none of those return an indentation,
|
||||
this will check the syntax tree for the [indent node
|
||||
prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
|
||||
number when an indentation could be determined, and null
|
||||
otherwise.
|
||||
*/
|
||||
declare function getIndentation(context: IndentContext | EditorState, pos: number): number | null;
|
||||
/**
|
||||
Create a change set that auto-indents all lines touched by the
|
||||
given document range.
|
||||
*/
|
||||
declare function indentRange(state: EditorState, from: number, to: number): _codemirror_state.ChangeSet;
|
||||
/**
|
||||
Indentation contexts are used when calling [indentation
|
||||
services](https://codemirror.net/6/docs/ref/#language.indentService). They provide helper utilities
|
||||
useful in indentation logic, and can selectively override the
|
||||
|
@ -425,7 +450,7 @@ declare class IndentContext {
|
|||
simulateBreak?: number;
|
||||
/**
|
||||
When `simulateBreak` is given, this can be used to make the
|
||||
simulate break behave like a double line break.
|
||||
simulated break behave like a double line break.
|
||||
*/
|
||||
simulateDoubleBreak?: boolean;
|
||||
});
|
||||
|
@ -469,8 +494,9 @@ declare class IndentContext {
|
|||
/**
|
||||
A syntax tree node prop used to associate indentation strategies
|
||||
with node types. Such a strategy is a function from an indentation
|
||||
context to a column number or null, where null indicates that no
|
||||
definitive indentation can be determined.
|
||||
context to a column number (see also
|
||||
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
|
||||
indicates that no definitive indentation can be determined.
|
||||
*/
|
||||
declare const indentNodeProp: NodeProp<(context: TreeIndentContext) => number | null>;
|
||||
/**
|
||||
|
@ -617,6 +643,14 @@ State effect that unfolds the given range (if it was folded).
|
|||
*/
|
||||
declare const unfoldEffect: _codemirror_state.StateEffectType<DocRange>;
|
||||
/**
|
||||
The state field that stores the folded ranges (as a [decoration
|
||||
set](https://codemirror.net/6/docs/ref/#view.DecorationSet)). Can be passed to
|
||||
[`EditorState.toJSON`](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) and
|
||||
[`fromJSON`](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) to serialize the fold
|
||||
state.
|
||||
*/
|
||||
declare const foldState: StateField<DecorationSet>;
|
||||
/**
|
||||
Get a [range set](https://codemirror.net/6/docs/ref/#state.RangeSet) containing the folded ranges
|
||||
in the given state.
|
||||
*/
|
||||
|
@ -644,6 +678,12 @@ Unfold all folded code.
|
|||
*/
|
||||
declare const unfoldAll: Command;
|
||||
/**
|
||||
Toggle folding at cursors. Unfolds if there is an existing fold
|
||||
starting in that line, tries to find a foldable range around it
|
||||
otherwise.
|
||||
*/
|
||||
declare const toggleFold: Command;
|
||||
/**
|
||||
Default fold-related key bindings.
|
||||
|
||||
- Ctrl-Shift-[ (Cmd-Alt-[ on macOS): [`foldCode`](https://codemirror.net/6/docs/ref/#language.foldCode).
|
||||
|
@ -716,6 +756,10 @@ A highlight style associates CSS styles with higlighting
|
|||
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
||||
*/
|
||||
declare class HighlightStyle implements Highlighter {
|
||||
/**
|
||||
The tag styles used to create this highlight style.
|
||||
*/
|
||||
readonly specs: readonly TagStyle[];
|
||||
/**
|
||||
A style module holding the CSS rules for this highlight style.
|
||||
When using
|
||||
|
@ -851,6 +895,15 @@ highlighting style is used to indicate this.
|
|||
*/
|
||||
declare function bracketMatching(config?: Config): Extension;
|
||||
/**
|
||||
When larger syntax nodes, such as HTML tags, are marked as
|
||||
opening/closing, it can be a bit messy to treat the whole node as
|
||||
a matchable bracket. This node prop allows you to define, for such
|
||||
a node, a ‘handle’—the part of the node that is highlighted, and
|
||||
that the cursor must be on to activate highlighting in the first
|
||||
place.
|
||||
*/
|
||||
declare const bracketMatchingHandle: NodeProp<(node: SyntaxNode) => SyntaxNode | null>;
|
||||
/**
|
||||
The result returned from `matchBrackets`.
|
||||
*/
|
||||
interface MatchResult {
|
||||
|
@ -896,6 +949,7 @@ declare class StringStream {
|
|||
The current indent unit size.
|
||||
*/
|
||||
indentUnit: number;
|
||||
private overrideIndent?;
|
||||
/**
|
||||
The current position on the line.
|
||||
*/
|
||||
|
@ -917,7 +971,7 @@ declare class StringStream {
|
|||
/**
|
||||
The current indent unit size.
|
||||
*/
|
||||
indentUnit: number);
|
||||
indentUnit: number, overrideIndent?: number | undefined);
|
||||
/**
|
||||
True if we are at the end of the line.
|
||||
*/
|
||||
|
@ -997,6 +1051,10 @@ copyable) object with state, in which it can store information
|
|||
about the current context.
|
||||
*/
|
||||
interface StreamParser<State> {
|
||||
/**
|
||||
A name for this language.
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
Produce a start state for the parser.
|
||||
*/
|
||||
|
@ -1061,4 +1119,4 @@ declare class StreamLanguage<State> extends Language {
|
|||
get allowsNesting(): boolean;
|
||||
}
|
||||
|
||||
export { Config, HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, MatchResult, ParseContext, StreamLanguage, StreamParser, StringStream, TagStyle, TreeIndentContext, bracketMatching, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, unfoldAll, unfoldCode, unfoldEffect };
|
||||
export { Config, HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, MatchResult, ParseContext, StreamLanguage, StreamParser, StringStream, TagStyle, TreeIndentContext, bracketMatching, bracketMatchingHandle, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentRange, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect };
|
||||
|
|
300
node_modules/@codemirror/language/dist/index.js
generated
vendored
300
node_modules/@codemirror/language/dist/index.js
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
import { NodeProp, Tree, IterMode, TreeFragment, Parser, NodeType, NodeSet } from '@lezer/common';
|
||||
import { NodeProp, IterMode, Tree, TreeFragment, Parser, NodeType, NodeSet } from '@lezer/common';
|
||||
import { StateEffect, StateField, Facet, EditorState, countColumn, combineConfig, RangeSet, RangeSetBuilder, Prec } from '@codemirror/state';
|
||||
import { ViewPlugin, logException, Decoration, EditorView, WidgetType, gutter, GutterMarker } from '@codemirror/view';
|
||||
import { ViewPlugin, logException, EditorView, Decoration, WidgetType, gutter, GutterMarker } from '@codemirror/view';
|
||||
import { tags, tagHighlighter, highlightTree, styleTags } from '@lezer/highlight';
|
||||
import { StyleModule } from 'style-mod';
|
||||
|
||||
|
@ -45,8 +45,13 @@ class Language {
|
|||
The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet
|
||||
used for this language.
|
||||
*/
|
||||
data, parser, extraExtensions = []) {
|
||||
data, parser, extraExtensions = [],
|
||||
/**
|
||||
A language name.
|
||||
*/
|
||||
name = "") {
|
||||
this.data = data;
|
||||
this.name = name;
|
||||
// Kludge to define EditorState.tree as a debugging helper,
|
||||
// without the EditorState package actually knowing about
|
||||
// languages and lezer trees.
|
||||
|
@ -134,8 +139,8 @@ A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language)
|
|||
parsers.
|
||||
*/
|
||||
class LRLanguage extends Language {
|
||||
constructor(data, parser) {
|
||||
super(data, parser);
|
||||
constructor(data, parser, name) {
|
||||
super(data, parser, [], name);
|
||||
this.parser = parser;
|
||||
}
|
||||
/**
|
||||
|
@ -145,14 +150,14 @@ class LRLanguage extends Language {
|
|||
let data = defineLanguageFacet(spec.languageData);
|
||||
return new LRLanguage(data, spec.parser.configure({
|
||||
props: [languageDataProp.add(type => type.isTop ? data : undefined)]
|
||||
}));
|
||||
}), spec.name);
|
||||
}
|
||||
/**
|
||||
Create a new instance of this language with a reconfigured
|
||||
version of its parser.
|
||||
version of its parser and optionally a new name.
|
||||
*/
|
||||
configure(options) {
|
||||
return new LRLanguage(this.data, this.parser.configure(options));
|
||||
configure(options, name) {
|
||||
return new LRLanguage(this.data, this.parser.configure(options), name || this.name);
|
||||
}
|
||||
get allowsNesting() { return this.parser.hasWrappers(); }
|
||||
}
|
||||
|
@ -174,7 +179,13 @@ up to that point if the tree isn't already available.
|
|||
function ensureSyntaxTree(state, upto, timeout = 50) {
|
||||
var _a;
|
||||
let parse = (_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context;
|
||||
return !parse ? null : parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
|
||||
if (!parse)
|
||||
return null;
|
||||
let oldVieport = parse.viewport;
|
||||
parse.updateViewport({ from: 0, to: upto });
|
||||
let result = parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
|
||||
parse.updateViewport(oldVieport);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
Queries whether there is a full syntax tree available up to the
|
||||
|
@ -214,13 +225,13 @@ function syntaxParserRunning(view) {
|
|||
}
|
||||
// Lezer-style Input object for a Text document.
|
||||
class DocInput {
|
||||
constructor(doc, length = doc.length) {
|
||||
constructor(doc) {
|
||||
this.doc = doc;
|
||||
this.length = length;
|
||||
this.cursorPos = 0;
|
||||
this.string = "";
|
||||
this.cursor = doc.iter();
|
||||
}
|
||||
get length() { return this.doc.length; }
|
||||
syncTo(pos) {
|
||||
this.string = this.cursor.next(pos - this.cursorPos).value;
|
||||
this.cursorPos = pos + this.string.length;
|
||||
|
@ -499,14 +510,14 @@ class LanguageState {
|
|||
// state updates with parse work beyond the viewport.
|
||||
let upto = this.context.treeLen == tr.startState.doc.length ? undefined
|
||||
: Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
||||
if (!newCx.work(20 /* Apply */, upto))
|
||||
if (!newCx.work(20 /* Work.Apply */, upto))
|
||||
newCx.takeTree();
|
||||
return new LanguageState(newCx);
|
||||
}
|
||||
static init(state) {
|
||||
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
||||
let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
|
||||
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
||||
if (!parseState.work(20 /* Apply */, vpTo))
|
||||
if (!parseState.work(20 /* Work.Apply */, vpTo))
|
||||
parseState.takeTree();
|
||||
return new LanguageState(parseState);
|
||||
}
|
||||
|
@ -523,14 +534,14 @@ Language.state = /*@__PURE__*/StateField.define({
|
|||
}
|
||||
});
|
||||
let requestIdle = (callback) => {
|
||||
let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
|
||||
let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
|
||||
return () => clearTimeout(timeout);
|
||||
};
|
||||
if (typeof requestIdleCallback != "undefined")
|
||||
requestIdle = (callback) => {
|
||||
let idle = -1, timeout = setTimeout(() => {
|
||||
idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
|
||||
}, 100 /* MinPause */);
|
||||
idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
|
||||
}, 100 /* Work.MinPause */);
|
||||
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
||||
};
|
||||
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
||||
|
@ -553,7 +564,7 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|||
this.scheduleWork();
|
||||
if (update.docChanged) {
|
||||
if (this.view.hasFocus)
|
||||
this.chunkBudget += 50 /* ChangeBonus */;
|
||||
this.chunkBudget += 50 /* Work.ChangeBonus */;
|
||||
this.scheduleWork();
|
||||
}
|
||||
this.checkAsyncSchedule(cx);
|
||||
|
@ -569,19 +580,19 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|||
this.working = null;
|
||||
let now = Date.now();
|
||||
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
|
||||
this.chunkEnd = now + 30000 /* ChunkTime */;
|
||||
this.chunkBudget = 3000 /* ChunkBudget */;
|
||||
this.chunkEnd = now + 30000 /* Work.ChunkTime */;
|
||||
this.chunkBudget = 3000 /* Work.ChunkBudget */;
|
||||
}
|
||||
if (this.chunkBudget <= 0)
|
||||
return; // No more budget
|
||||
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
||||
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
||||
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
|
||||
return;
|
||||
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
||||
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
||||
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
||||
let done = field.context.work(() => {
|
||||
return isInputPending && isInputPending() || Date.now() > endTime;
|
||||
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
||||
}, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
|
||||
this.chunkBudget -= Date.now() - now;
|
||||
if (done || this.chunkBudget <= 0) {
|
||||
field.context.takeTree();
|
||||
|
@ -612,11 +623,21 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|||
eventHandlers: { focus() { this.scheduleWork(); } }
|
||||
});
|
||||
/**
|
||||
The facet used to associate a language with an editor state.
|
||||
The facet used to associate a language with an editor state. Used
|
||||
by `Language` object's `extension` property (so you don't need to
|
||||
manually wrap your languages in this). Can be used to access the
|
||||
current language on a state.
|
||||
*/
|
||||
const language = /*@__PURE__*/Facet.define({
|
||||
combine(languages) { return languages.length ? languages[0] : null; },
|
||||
enables: [Language.state, parseWorker]
|
||||
enables: language => [
|
||||
Language.state,
|
||||
parseWorker,
|
||||
EditorView.contentAttributes.compute([language], state => {
|
||||
let lang = state.facet(language);
|
||||
return lang && lang.name ? { "data-language": lang.name } : {};
|
||||
})
|
||||
]
|
||||
});
|
||||
/**
|
||||
This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an
|
||||
|
@ -746,22 +767,27 @@ class LanguageDescription {
|
|||
|
||||
/**
|
||||
Facet that defines a way to provide a function that computes the
|
||||
appropriate indentation depth at the start of a given line, or
|
||||
`null` to indicate no appropriate indentation could be determined.
|
||||
appropriate indentation depth, as a column number (see
|
||||
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
|
||||
line. A return value of `null` indicates no indentation can be
|
||||
determined, and the line should inherit the indentation of the one
|
||||
above it. A return value of `undefined` defers to the next indent
|
||||
service.
|
||||
*/
|
||||
const indentService = /*@__PURE__*/Facet.define();
|
||||
/**
|
||||
Facet for overriding the unit by which indentation happens.
|
||||
Should be a string consisting either entirely of spaces or
|
||||
entirely of tabs. When not set, this defaults to 2 spaces.
|
||||
Facet for overriding the unit by which indentation happens. Should
|
||||
be a string consisting either entirely of the same whitespace
|
||||
character. When not set, this defaults to 2 spaces.
|
||||
*/
|
||||
const indentUnit = /*@__PURE__*/Facet.define({
|
||||
combine: values => {
|
||||
if (!values.length)
|
||||
return " ";
|
||||
if (!/^(?: +|\t+)$/.test(values[0]))
|
||||
let unit = values[0];
|
||||
if (!unit || /\S/.test(unit) || Array.from(unit).some(e => e != unit[0]))
|
||||
throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));
|
||||
return values[0];
|
||||
return unit;
|
||||
}
|
||||
});
|
||||
/**
|
||||
|
@ -781,36 +807,64 @@ Will use tabs for as much of the columns as possible when the
|
|||
tabs.
|
||||
*/
|
||||
function indentString(state, cols) {
|
||||
let result = "", ts = state.tabSize;
|
||||
if (state.facet(indentUnit).charCodeAt(0) == 9)
|
||||
let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];
|
||||
if (ch == "\t") {
|
||||
while (cols >= ts) {
|
||||
result += "\t";
|
||||
cols -= ts;
|
||||
}
|
||||
ch = " ";
|
||||
}
|
||||
for (let i = 0; i < cols; i++)
|
||||
result += " ";
|
||||
result += ch;
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
Get the indentation at the given position. Will first consult any
|
||||
[indent services](https://codemirror.net/6/docs/ref/#language.indentService) that are registered,
|
||||
and if none of those return an indentation, this will check the
|
||||
syntax tree for the [indent node prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp)
|
||||
and use that if found. Returns a number when an indentation could
|
||||
be determined, and null otherwise.
|
||||
Get the indentation, as a column number, at the given position.
|
||||
Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
||||
that are registered, and if none of those return an indentation,
|
||||
this will check the syntax tree for the [indent node
|
||||
prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
|
||||
number when an indentation could be determined, and null
|
||||
otherwise.
|
||||
*/
|
||||
function getIndentation(context, pos) {
|
||||
if (context instanceof EditorState)
|
||||
context = new IndentContext(context);
|
||||
for (let service of context.state.facet(indentService)) {
|
||||
let result = service(context, pos);
|
||||
if (result != null)
|
||||
if (result !== undefined)
|
||||
return result;
|
||||
}
|
||||
let tree = syntaxTree(context.state);
|
||||
return tree ? syntaxIndentation(context, tree, pos) : null;
|
||||
}
|
||||
/**
|
||||
Create a change set that auto-indents all lines touched by the
|
||||
given document range.
|
||||
*/
|
||||
function indentRange(state, from, to) {
|
||||
let updated = Object.create(null);
|
||||
let context = new IndentContext(state, { overrideIndentation: start => { var _a; return (_a = updated[start]) !== null && _a !== void 0 ? _a : -1; } });
|
||||
let changes = [];
|
||||
for (let pos = from; pos <= to;) {
|
||||
let line = state.doc.lineAt(pos);
|
||||
pos = line.to + 1;
|
||||
let indent = getIndentation(context, line.from);
|
||||
if (indent == null)
|
||||
continue;
|
||||
if (!/\S/.test(line.text))
|
||||
indent = 0;
|
||||
let cur = /^\s*/.exec(line.text)[0];
|
||||
let norm = indentString(state, indent);
|
||||
if (cur != norm) {
|
||||
updated[line.from] = indent;
|
||||
changes.push({ from: line.from, to: line.from + cur.length, insert: norm });
|
||||
}
|
||||
}
|
||||
return state.changes(changes);
|
||||
}
|
||||
/**
|
||||
Indentation contexts are used when calling [indentation
|
||||
services](https://codemirror.net/6/docs/ref/#language.indentService). They provide helper utilities
|
||||
useful in indentation logic, and can selectively override the
|
||||
|
@ -907,8 +961,9 @@ class IndentContext {
|
|||
/**
|
||||
A syntax tree node prop used to associate indentation strategies
|
||||
with node types. Such a strategy is a function from an indentation
|
||||
context to a column number or null, where null indicates that no
|
||||
definitive indentation can be determined.
|
||||
context to a column number (see also
|
||||
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
|
||||
indicates that no definitive indentation can be determined.
|
||||
*/
|
||||
const indentNodeProp = /*@__PURE__*/new NodeProp();
|
||||
// Compute the indentation for a given position from the syntax tree.
|
||||
|
@ -1139,7 +1194,7 @@ function syntaxFolding(state, start, end) {
|
|||
let tree = syntaxTree(state);
|
||||
if (tree.length < end)
|
||||
return null;
|
||||
let inner = tree.resolveInner(end);
|
||||
let inner = tree.resolveInner(end, 1);
|
||||
let found = null;
|
||||
for (let cur = inner; cur; cur = cur.parent) {
|
||||
if (cur.to <= end || cur.from > end)
|
||||
|
@ -1200,6 +1255,13 @@ function selectedLines(view) {
|
|||
}
|
||||
return lines;
|
||||
}
|
||||
/**
|
||||
The state field that stores the folded ranges (as a [decoration
|
||||
set](https://codemirror.net/6/docs/ref/#view.DecorationSet)). Can be passed to
|
||||
[`EditorState.toJSON`](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) and
|
||||
[`fromJSON`](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) to serialize the fold
|
||||
state.
|
||||
*/
|
||||
const foldState = /*@__PURE__*/StateField.define({
|
||||
create() {
|
||||
return Decoration.none;
|
||||
|
@ -1227,7 +1289,24 @@ const foldState = /*@__PURE__*/StateField.define({
|
|||
}
|
||||
return folded;
|
||||
},
|
||||
provide: f => EditorView.decorations.from(f)
|
||||
provide: f => EditorView.decorations.from(f),
|
||||
toJSON(folded, state) {
|
||||
let ranges = [];
|
||||
folded.between(0, state.doc.length, (from, to) => { ranges.push(from, to); });
|
||||
return ranges;
|
||||
},
|
||||
fromJSON(value) {
|
||||
if (!Array.isArray(value) || value.length % 2)
|
||||
throw new RangeError("Invalid JSON for fold state");
|
||||
let ranges = [];
|
||||
for (let i = 0; i < value.length;) {
|
||||
let from = value[i++], to = value[i++];
|
||||
if (typeof from != "number" || typeof to != "number")
|
||||
throw new RangeError("Invalid JSON for fold state");
|
||||
ranges.push(foldWidget.range(from, to));
|
||||
}
|
||||
return Decoration.set(ranges, true);
|
||||
}
|
||||
});
|
||||
/**
|
||||
Get a [range set](https://codemirror.net/6/docs/ref/#state.RangeSet) containing the folded ranges
|
||||
|
@ -1320,6 +1399,41 @@ const unfoldAll = view => {
|
|||
view.dispatch({ effects });
|
||||
return true;
|
||||
};
|
||||
// Find the foldable region containing the given line, if one exists
|
||||
function foldableContainer(view, lineBlock) {
|
||||
// Look backwards through line blocks until we find a foldable region that
|
||||
// intersects with the line
|
||||
for (let line = lineBlock;;) {
|
||||
let foldableRegion = foldable(view.state, line.from, line.to);
|
||||
if (foldableRegion && foldableRegion.to > lineBlock.from)
|
||||
return foldableRegion;
|
||||
if (!line.from)
|
||||
return null;
|
||||
line = view.lineBlockAt(line.from - 1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
Toggle folding at cursors. Unfolds if there is an existing fold
|
||||
starting in that line, tries to find a foldable range around it
|
||||
otherwise.
|
||||
*/
|
||||
const toggleFold = (view) => {
|
||||
let effects = [];
|
||||
for (let line of selectedLines(view)) {
|
||||
let folded = findFold(view.state, line.from, line.to);
|
||||
if (folded) {
|
||||
effects.push(unfoldEffect.of(folded), announceFold(view, folded, false));
|
||||
}
|
||||
else {
|
||||
let foldRange = foldableContainer(view, line);
|
||||
if (foldRange)
|
||||
effects.push(foldEffect.of(foldRange), announceFold(view, foldRange));
|
||||
}
|
||||
}
|
||||
if (effects.length > 0)
|
||||
view.dispatch({ effects: maybeEnable(view.state, effects) });
|
||||
return !!effects.length;
|
||||
};
|
||||
/**
|
||||
Default fold-related key bindings.
|
||||
|
||||
|
@ -1475,7 +1589,12 @@ A highlight style associates CSS styles with higlighting
|
|||
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
||||
*/
|
||||
class HighlightStyle {
|
||||
constructor(spec, options) {
|
||||
constructor(
|
||||
/**
|
||||
The tag styles used to create this highlight style.
|
||||
*/
|
||||
specs, options) {
|
||||
this.specs = specs;
|
||||
let modSpec;
|
||||
function def(spec) {
|
||||
let cls = StyleModule.newName();
|
||||
|
@ -1486,7 +1605,7 @@ class HighlightStyle {
|
|||
const scopeOpt = options.scope;
|
||||
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
|
||||
: scopeOpt ? (type) => type == scopeOpt : undefined;
|
||||
this.style = tagHighlighter(spec.map(style => ({
|
||||
this.style = tagHighlighter(specs.map(style => ({
|
||||
tag: style.tag,
|
||||
class: style.class || def(Object.assign({}, style, { tag: null }))
|
||||
})), {
|
||||
|
@ -1603,7 +1722,7 @@ A default highlight style (works well with light themes).
|
|||
*/
|
||||
const defaultHighlightStyle = /*@__PURE__*/HighlightStyle.define([
|
||||
{ tag: tags.meta,
|
||||
color: "#7a757a" },
|
||||
color: "#404740" },
|
||||
{ tag: tags.link,
|
||||
textDecoration: "underline" },
|
||||
{ tag: tags.heading,
|
||||
|
@ -1702,6 +1821,15 @@ highlighting style is used to indicate this.
|
|||
function bracketMatching(config = {}) {
|
||||
return [bracketMatchingConfig.of(config), bracketMatchingUnique];
|
||||
}
|
||||
/**
|
||||
When larger syntax nodes, such as HTML tags, are marked as
|
||||
opening/closing, it can be a bit messy to treat the whole node as
|
||||
a matchable bracket. This node prop allows you to define, for such
|
||||
a node, a ‘handle’—the part of the node that is highlighted, and
|
||||
that the cursor must be on to activate highlighting in the first
|
||||
place.
|
||||
*/
|
||||
const bracketMatchingHandle = /*@__PURE__*/new NodeProp();
|
||||
function matchingNodes(node, dir, brackets) {
|
||||
let byProp = node.prop(dir < 0 ? NodeProp.openedBy : NodeProp.closedBy);
|
||||
if (byProp)
|
||||
|
@ -1713,6 +1841,10 @@ function matchingNodes(node, dir, brackets) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
function findHandle(node) {
|
||||
let hasHandle = node.type.prop(bracketMatchingHandle);
|
||||
return hasHandle ? hasHandle(node.node) : node;
|
||||
}
|
||||
/**
|
||||
Find the matching bracket for the token at `pos`, scanning
|
||||
direction `dir`. Only the `brackets` and `maxScanDistance`
|
||||
|
@ -1724,31 +1856,37 @@ function matchBrackets(state, pos, dir, config = {}) {
|
|||
let tree = syntaxTree(state), node = tree.resolveInner(pos, dir);
|
||||
for (let cur = node; cur; cur = cur.parent) {
|
||||
let matches = matchingNodes(cur.type, dir, brackets);
|
||||
if (matches && cur.from < cur.to)
|
||||
return matchMarkedBrackets(state, pos, dir, cur, matches, brackets);
|
||||
if (matches && cur.from < cur.to) {
|
||||
let handle = findHandle(cur);
|
||||
if (handle && (dir > 0 ? pos >= handle.from && pos < handle.to : pos > handle.from && pos <= handle.to))
|
||||
return matchMarkedBrackets(state, pos, dir, cur, handle, matches, brackets);
|
||||
}
|
||||
}
|
||||
return matchPlainBrackets(state, pos, dir, tree, node.type, maxScanDistance, brackets);
|
||||
}
|
||||
function matchMarkedBrackets(_state, _pos, dir, token, matching, brackets) {
|
||||
let parent = token.parent, firstToken = { from: token.from, to: token.to };
|
||||
function matchMarkedBrackets(_state, _pos, dir, token, handle, matching, brackets) {
|
||||
let parent = token.parent, firstToken = { from: handle.from, to: handle.to };
|
||||
let depth = 0, cursor = parent === null || parent === void 0 ? void 0 : parent.cursor();
|
||||
if (cursor && (dir < 0 ? cursor.childBefore(token.from) : cursor.childAfter(token.to)))
|
||||
do {
|
||||
if (dir < 0 ? cursor.to <= token.from : cursor.from >= token.to) {
|
||||
if (depth == 0 && matching.indexOf(cursor.type.name) > -1 && cursor.from < cursor.to) {
|
||||
return { start: firstToken, end: { from: cursor.from, to: cursor.to }, matched: true };
|
||||
let endHandle = findHandle(cursor);
|
||||
return { start: firstToken, end: endHandle ? { from: endHandle.from, to: endHandle.to } : undefined, matched: true };
|
||||
}
|
||||
else if (matchingNodes(cursor.type, dir, brackets)) {
|
||||
depth++;
|
||||
}
|
||||
else if (matchingNodes(cursor.type, -dir, brackets)) {
|
||||
depth--;
|
||||
if (depth == 0)
|
||||
if (depth == 0) {
|
||||
let endHandle = findHandle(cursor);
|
||||
return {
|
||||
start: firstToken,
|
||||
end: cursor.from == cursor.to ? undefined : { from: cursor.from, to: cursor.to },
|
||||
end: endHandle && endHandle.from < endHandle.to ? { from: endHandle.from, to: endHandle.to } : undefined,
|
||||
matched: false
|
||||
};
|
||||
}
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
} while (dir < 0 ? cursor.prevSibling() : cursor.nextSibling());
|
||||
|
@ -1768,7 +1906,7 @@ function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, b
|
|||
let basePos = pos + distance * dir;
|
||||
for (let pos = dir > 0 ? 0 : text.length - 1, end = dir > 0 ? text.length : -1; pos != end; pos += dir) {
|
||||
let found = brackets.indexOf(text[pos]);
|
||||
if (found < 0 || tree.resolve(basePos + pos, 1).type != tokenType)
|
||||
if (found < 0 || tree.resolveInner(basePos + pos, 1).type != tokenType)
|
||||
continue;
|
||||
if ((found % 2 == 0) == (dir > 0)) {
|
||||
depth++;
|
||||
|
@ -1819,10 +1957,11 @@ class StringStream {
|
|||
/**
|
||||
The current indent unit size.
|
||||
*/
|
||||
indentUnit) {
|
||||
indentUnit, overrideIndent) {
|
||||
this.string = string;
|
||||
this.tabSize = tabSize;
|
||||
this.indentUnit = indentUnit;
|
||||
this.overrideIndent = overrideIndent;
|
||||
/**
|
||||
The current position on the line.
|
||||
*/
|
||||
|
@ -1923,7 +2062,8 @@ class StringStream {
|
|||
Get the indentation column of the current line.
|
||||
*/
|
||||
indentation() {
|
||||
return countCol(this.string, null, this.tabSize);
|
||||
var _a;
|
||||
return (_a = this.overrideIndent) !== null && _a !== void 0 ? _a : countCol(this.string, null, this.tabSize);
|
||||
}
|
||||
/**
|
||||
Match the input against the given string or regular expression
|
||||
|
@ -1965,6 +2105,7 @@ class StringStream {
|
|||
|
||||
function fullParser(spec) {
|
||||
return {
|
||||
name: spec.name || "",
|
||||
token: spec.token,
|
||||
blankLine: spec.blankLine || (() => { }),
|
||||
startState: spec.startState || (() => true),
|
||||
|
@ -1984,6 +2125,7 @@ function defaultCopyState(state) {
|
|||
}
|
||||
return newState;
|
||||
}
|
||||
const IndentedFrom = /*@__PURE__*/new WeakMap();
|
||||
/**
|
||||
A [language](https://codemirror.net/6/docs/ref/#language.Language) class based on a CodeMirror
|
||||
5-style [streaming parser](https://codemirror.net/6/docs/ref/#language.StreamParser).
|
||||
|
@ -1997,7 +2139,7 @@ class StreamLanguage extends Language {
|
|||
return new Parse(self, input, fragments, ranges);
|
||||
}
|
||||
};
|
||||
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))]);
|
||||
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
|
||||
this.topNode = docID(data);
|
||||
self = this;
|
||||
this.streamParser = p;
|
||||
|
@ -2014,7 +2156,14 @@ class StreamLanguage extends Language {
|
|||
at = at.parent;
|
||||
if (!at)
|
||||
return null;
|
||||
let start = findState(this, tree, 0, at.from, pos), statePos, state;
|
||||
let from = undefined;
|
||||
let { overrideIndentation } = cx.options;
|
||||
if (overrideIndentation) {
|
||||
from = IndentedFrom.get(cx.state);
|
||||
if (from != null && from < pos - 1e4)
|
||||
from = undefined;
|
||||
}
|
||||
let start = findState(this, tree, 0, at.from, from !== null && from !== void 0 ? from : pos), statePos, state;
|
||||
if (start) {
|
||||
state = start.state;
|
||||
statePos = start.pos + 1;
|
||||
|
@ -2023,12 +2172,13 @@ class StreamLanguage extends Language {
|
|||
state = this.streamParser.startState(cx.unit);
|
||||
statePos = 0;
|
||||
}
|
||||
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
||||
if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
|
||||
return null;
|
||||
while (statePos < pos) {
|
||||
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
||||
if (line.length) {
|
||||
let stream = new StringStream(line.text, cx.state.tabSize, cx.unit);
|
||||
let indentation = overrideIndentation ? overrideIndentation(line.from) : -1;
|
||||
let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation);
|
||||
while (stream.pos < end - line.from)
|
||||
readToken(this.streamParser.token, stream, state);
|
||||
}
|
||||
|
@ -2039,8 +2189,10 @@ class StreamLanguage extends Language {
|
|||
break;
|
||||
statePos = line.to + 1;
|
||||
}
|
||||
let { text } = cx.lineAt(pos);
|
||||
return this.streamParser.indent(state, /^\s*(.*)/.exec(text)[1], cx);
|
||||
let line = cx.lineAt(pos);
|
||||
if (overrideIndentation && from == null)
|
||||
IndentedFrom.set(cx.state, line.from);
|
||||
return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
|
||||
}
|
||||
get allowsNesting() { return false; }
|
||||
}
|
||||
|
@ -2102,7 +2254,7 @@ class Parse {
|
|||
this.chunks.push(tree.children[i]);
|
||||
this.chunkPos.push(tree.positions[i]);
|
||||
}
|
||||
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
||||
if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) {
|
||||
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
||||
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
||||
this.parsedPos = context.viewport.from;
|
||||
|
@ -2112,7 +2264,7 @@ class Parse {
|
|||
advance() {
|
||||
let context = ParseContext.get();
|
||||
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
||||
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
||||
let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */);
|
||||
if (context)
|
||||
end = Math.min(end, context.viewport.to);
|
||||
while (this.parsedPos < end)
|
||||
|
@ -2196,7 +2348,7 @@ class Parse {
|
|||
let token = readToken(streamParser.token, stream, this.state);
|
||||
if (token)
|
||||
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
||||
if (stream.start > 10000 /* MaxLineLength */)
|
||||
if (stream.start > 10000 /* C.MaxLineLength */)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2212,7 +2364,7 @@ class Parse {
|
|||
length: this.parsedPos - this.chunkStart,
|
||||
nodeSet,
|
||||
topID: 0,
|
||||
maxBufferLength: 2048 /* ChunkSize */,
|
||||
maxBufferLength: 2048 /* C.ChunkSize */,
|
||||
reused: this.chunkReused
|
||||
});
|
||||
tree = new Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|
||||
|
@ -2245,8 +2397,8 @@ for (let [legacyName, name] of [
|
|||
["variable-2", "variableName.special"],
|
||||
["string-2", "string.special"],
|
||||
["def", "variableName.definition"],
|
||||
["tag", "typeName"],
|
||||
["attribute", "propertyName"],
|
||||
["tag", "tagName"],
|
||||
["attribute", "attributeName"],
|
||||
["type", "typeName"],
|
||||
["builtin", "variableName.standard"],
|
||||
["qualifier", "modifier"],
|
||||
|
@ -2307,4 +2459,4 @@ function docID(data) {
|
|||
return type;
|
||||
}
|
||||
|
||||
export { HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, ParseContext, StreamLanguage, StringStream, TreeIndentContext, bracketMatching, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, unfoldAll, unfoldCode, unfoldEffect };
|
||||
export { HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, ParseContext, StreamLanguage, StringStream, TreeIndentContext, bracketMatching, bracketMatchingHandle, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentRange, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect };
|
||||
|
|
4
node_modules/@codemirror/language/package.json
generated
vendored
4
node_modules/@codemirror/language/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/language",
|
||||
"version": "6.0.0",
|
||||
"version": "6.5.0",
|
||||
"description": "Language support infrastructure for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
@ -12,7 +12,7 @@
|
|||
],
|
||||
"author": {
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijnh@gmail.com",
|
||||
"email": "marijn@haverbeke.berlin",
|
||||
"url": "http://marijnhaverbeke.nl"
|
||||
},
|
||||
"type": "module",
|
||||
|
|
2
node_modules/@codemirror/lint/.github/workflows/dispatch.yml
generated
vendored
2
node_modules/@codemirror/lint/.github/workflows/dispatch.yml
generated
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
with:
|
||||
# You should create a personal access token and store it in your repository
|
||||
token: ${{ secrets.DISPATCH_AUTH }}
|
||||
repo: codemirror.next
|
||||
repo: dev
|
||||
owner: codemirror
|
||||
event_type: push
|
||||
|
|
6
node_modules/@codemirror/lint/CHANGELOG.md
generated
vendored
6
node_modules/@codemirror/lint/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,9 @@
|
|||
## 6.1.0 (2022-11-15)
|
||||
|
||||
### New features
|
||||
|
||||
The new `forEachDiagnostic` function can be used to iterate over the diagnostics in an editor state.
|
||||
|
||||
## 6.0.0 (2022-06-08)
|
||||
|
||||
### Breaking changes
|
||||
|
|
10
node_modules/@codemirror/lint/README.md
generated
vendored
10
node_modules/@codemirror/lint/README.md
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
# @codemirror/lint [](https://www.npmjs.org/package/@codemirror/lint)
|
||||
|
||||
[ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#lint) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lint/blob/main/CHANGELOG.md) ]
|
||||
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#lint) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/lint/blob/main/CHANGELOG.md) ]
|
||||
|
||||
This package implements linting support for the
|
||||
[CodeMirror](https://codemirror.net/6/) code editor.
|
||||
[CodeMirror](https://codemirror.net/) code editor.
|
||||
|
||||
The [project page](https://codemirror.net/6/) has more information, a
|
||||
number of [examples](https://codemirror.net/6/examples/) and the
|
||||
[documentation](https://codemirror.net/6/docs/).
|
||||
The [project page](https://codemirror.net/) has more information, a
|
||||
number of [examples](https://codemirror.net/examples/) and the
|
||||
[documentation](https://codemirror.net/docs/).
|
||||
|
||||
This code is released under an
|
||||
[MIT license](https://github.com/codemirror/lint/tree/main/LICENSE).
|
||||
|
|
24
node_modules/@codemirror/lint/dist/index.cjs
generated
vendored
24
node_modules/@codemirror/lint/dist/index.cjs
generated
vendored
|
@ -197,7 +197,7 @@ A set of default key bindings for the lint functionality.
|
|||
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||
*/
|
||||
const lintKeymap = [
|
||||
{ key: "Mod-Shift-m", run: openLintPanel },
|
||||
{ key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
|
||||
{ key: "F8", run: nextDiagnostic }
|
||||
];
|
||||
const lintPlugin = view.ViewPlugin.fromClass(class {
|
||||
|
@ -611,8 +611,8 @@ class LintGutterMarker extends view.GutterMarker {
|
|||
function trackHoverOn(view, marker) {
|
||||
let mousemove = (event) => {
|
||||
let rect = marker.getBoundingClientRect();
|
||||
if (event.clientX > rect.left - 10 /* Margin */ && event.clientX < rect.right + 10 /* Margin */ &&
|
||||
event.clientY > rect.top - 10 /* Margin */ && event.clientY < rect.bottom + 10 /* Margin */)
|
||||
if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ &&
|
||||
event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */)
|
||||
return;
|
||||
for (let target = event.target; target; target = target.parentNode) {
|
||||
if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))
|
||||
|
@ -715,14 +715,14 @@ const lintGutterTheme = view.EditorView.baseTheme({
|
|||
".cm-lint-marker-warning": {
|
||||
content: svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
|
||||
},
|
||||
".cm-lint-marker-error:before": {
|
||||
".cm-lint-marker-error": {
|
||||
content: svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
|
||||
},
|
||||
});
|
||||
const lintGutterConfig = state.Facet.define({
|
||||
combine(configs) {
|
||||
return state.combineConfig(configs, {
|
||||
hoverTime: 300 /* Time */,
|
||||
hoverTime: 300 /* Hover.Time */,
|
||||
markerFilter: null,
|
||||
tooltipFilter: null
|
||||
});
|
||||
|
@ -736,9 +736,23 @@ the diagnostics.
|
|||
function lintGutter(config = {}) {
|
||||
return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];
|
||||
}
|
||||
/**
|
||||
Iterate over the marked diagnostics for the given editor state,
|
||||
calling `f` for each of them. Note that, if the document changed
|
||||
since the diagnostics werecreated, the `Diagnostic` object will
|
||||
hold the original outdated position, whereas the `to` and `from`
|
||||
arguments hold the diagnostic's current position.
|
||||
*/
|
||||
function forEachDiagnostic(state$1, f) {
|
||||
let lState = state$1.field(lintState, false);
|
||||
if (lState && lState.diagnostics.size)
|
||||
for (let iter = state.RangeSet.iter([lState.diagnostics]); iter.value; iter.next())
|
||||
f(iter.value.spec.diagnostic, iter.from, iter.to);
|
||||
}
|
||||
|
||||
exports.closeLintPanel = closeLintPanel;
|
||||
exports.diagnosticCount = diagnosticCount;
|
||||
exports.forEachDiagnostic = forEachDiagnostic;
|
||||
exports.forceLinting = forceLinting;
|
||||
exports.lintGutter = lintGutter;
|
||||
exports.lintKeymap = lintKeymap;
|
||||
|
|
10
node_modules/@codemirror/lint/dist/index.d.ts
generated
vendored
10
node_modules/@codemirror/lint/dist/index.d.ts
generated
vendored
|
@ -145,5 +145,13 @@ each line that has diagnostics, which can be hovered over to see
|
|||
the diagnostics.
|
||||
*/
|
||||
declare function lintGutter(config?: LintGutterConfig): Extension;
|
||||
/**
|
||||
Iterate over the marked diagnostics for the given editor state,
|
||||
calling `f` for each of them. Note that, if the document changed
|
||||
since the diagnostics werecreated, the `Diagnostic` object will
|
||||
hold the original outdated position, whereas the `to` and `from`
|
||||
arguments hold the diagnostic's current position.
|
||||
*/
|
||||
declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
|
||||
|
||||
export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, setDiagnostics, setDiagnosticsEffect };
|
||||
export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, setDiagnostics, setDiagnosticsEffect };
|
||||
|
|
27
node_modules/@codemirror/lint/dist/index.js
generated
vendored
27
node_modules/@codemirror/lint/dist/index.js
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
import { Decoration, showPanel, EditorView, ViewPlugin, hoverTooltip, logException, gutter, showTooltip, getPanel, WidgetType, GutterMarker } from '@codemirror/view';
|
||||
import { Decoration, showPanel, EditorView, ViewPlugin, logException, gutter, showTooltip, getPanel, WidgetType, hoverTooltip, GutterMarker } from '@codemirror/view';
|
||||
import { StateEffect, StateField, Facet, combineConfig, RangeSet } from '@codemirror/state';
|
||||
import elt from 'crelt';
|
||||
|
||||
|
@ -189,7 +189,7 @@ A set of default key bindings for the lint functionality.
|
|||
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||
*/
|
||||
const lintKeymap = [
|
||||
{ key: "Mod-Shift-m", run: openLintPanel },
|
||||
{ key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
|
||||
{ key: "F8", run: nextDiagnostic }
|
||||
];
|
||||
const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
||||
|
@ -603,8 +603,8 @@ class LintGutterMarker extends GutterMarker {
|
|||
function trackHoverOn(view, marker) {
|
||||
let mousemove = (event) => {
|
||||
let rect = marker.getBoundingClientRect();
|
||||
if (event.clientX > rect.left - 10 /* Margin */ && event.clientX < rect.right + 10 /* Margin */ &&
|
||||
event.clientY > rect.top - 10 /* Margin */ && event.clientY < rect.bottom + 10 /* Margin */)
|
||||
if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ &&
|
||||
event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */)
|
||||
return;
|
||||
for (let target = event.target; target; target = target.parentNode) {
|
||||
if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))
|
||||
|
@ -707,14 +707,14 @@ const lintGutterTheme = /*@__PURE__*/EditorView.baseTheme({
|
|||
".cm-lint-marker-warning": {
|
||||
content: /*@__PURE__*/svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
|
||||
},
|
||||
".cm-lint-marker-error:before": {
|
||||
".cm-lint-marker-error": {
|
||||
content: /*@__PURE__*/svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
|
||||
},
|
||||
});
|
||||
const lintGutterConfig = /*@__PURE__*/Facet.define({
|
||||
combine(configs) {
|
||||
return combineConfig(configs, {
|
||||
hoverTime: 300 /* Time */,
|
||||
hoverTime: 300 /* Hover.Time */,
|
||||
markerFilter: null,
|
||||
tooltipFilter: null
|
||||
});
|
||||
|
@ -728,5 +728,18 @@ the diagnostics.
|
|||
function lintGutter(config = {}) {
|
||||
return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];
|
||||
}
|
||||
/**
|
||||
Iterate over the marked diagnostics for the given editor state,
|
||||
calling `f` for each of them. Note that, if the document changed
|
||||
since the diagnostics werecreated, the `Diagnostic` object will
|
||||
hold the original outdated position, whereas the `to` and `from`
|
||||
arguments hold the diagnostic's current position.
|
||||
*/
|
||||
function forEachDiagnostic(state, f) {
|
||||
let lState = state.field(lintState, false);
|
||||
if (lState && lState.diagnostics.size)
|
||||
for (let iter = RangeSet.iter([lState.diagnostics]); iter.value; iter.next())
|
||||
f(iter.value.spec.diagnostic, iter.from, iter.to);
|
||||
}
|
||||
|
||||
export { closeLintPanel, diagnosticCount, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, setDiagnostics, setDiagnosticsEffect };
|
||||
export { closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, setDiagnostics, setDiagnosticsEffect };
|
||||
|
|
2
node_modules/@codemirror/lint/package.json
generated
vendored
2
node_modules/@codemirror/lint/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/lint",
|
||||
"version": "6.0.0",
|
||||
"version": "6.1.0",
|
||||
"description": "Linting support for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
|
2
node_modules/@codemirror/search/.github/workflows/dispatch.yml
generated
vendored
2
node_modules/@codemirror/search/.github/workflows/dispatch.yml
generated
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
with:
|
||||
# You should create a personal access token and store it in your repository
|
||||
token: ${{ secrets.DISPATCH_AUTH }}
|
||||
repo: codemirror.next
|
||||
repo: dev
|
||||
owner: codemirror
|
||||
event_type: push
|
||||
|
|
48
node_modules/@codemirror/search/CHANGELOG.md
generated
vendored
48
node_modules/@codemirror/search/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,51 @@
|
|||
## 6.2.3 (2022-11-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that hid the search dialog's close button when the editor was read-only.
|
||||
|
||||
## 6.2.2 (2022-10-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
When `literal` is off, \n, \r, and \t escapes are now also supported in replacement text.
|
||||
|
||||
Make sure search dialog inputs don't get treated as form fields when the editor is created inside a form.
|
||||
|
||||
Fix a bug in `RegExpCursor` that would cause it to stop matching in the middle of a line when its current match position was equal to the length of the line.
|
||||
|
||||
## 6.2.1 (2022-09-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
By-word search queries will now skip any result that had word characters both before and after a match boundary.
|
||||
|
||||
## 6.2.0 (2022-08-25)
|
||||
|
||||
### New features
|
||||
|
||||
A new `wholeWord` search query flag can be used to limit matches to whole words.
|
||||
|
||||
`SearchCursor` and `RegExpCursor` now support a `test` parameter that can be used to ignore certain matches.
|
||||
|
||||
## 6.1.0 (2022-08-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an infinite loop when the match position of a `RegExpCursor` ended up in the middle of an UTF16 surrogate pair.
|
||||
|
||||
### New features
|
||||
|
||||
The `literal` search option can now be set to make literal queries the default.
|
||||
|
||||
The new `searchPanelOpen` function can be used to find out whether the search panel is open for a given state.
|
||||
|
||||
## 6.0.1 (2022-07-22)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
`findNext` and `findPrevious` will now return to the current result (and scroll it into view) if no other matches are found.
|
||||
|
||||
## 6.0.0 (2022-06-08)
|
||||
|
||||
### Bug fixes
|
||||
|
|
10
node_modules/@codemirror/search/README.md
generated
vendored
10
node_modules/@codemirror/search/README.md
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
# @codemirror/search [](https://www.npmjs.org/package/@codemirror/search)
|
||||
|
||||
[ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#search) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/search/blob/main/CHANGELOG.md) ]
|
||||
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#search) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/search/blob/main/CHANGELOG.md) ]
|
||||
|
||||
This package implements search functionality for the
|
||||
[CodeMirror](https://codemirror.net/6/) code editor.
|
||||
[CodeMirror](https://codemirror.net/) code editor.
|
||||
|
||||
The [project page](https://codemirror.net/6/) has more information, a
|
||||
number of [examples](https://codemirror.net/6/examples/) and the
|
||||
[documentation](https://codemirror.net/6/docs/).
|
||||
The [project page](https://codemirror.net/) has more information, a
|
||||
number of [examples](https://codemirror.net/examples/) and the
|
||||
[documentation](https://codemirror.net/docs/).
|
||||
|
||||
This code is released under an
|
||||
[MIT license](https://github.com/codemirror/search/tree/main/LICENSE).
|
||||
|
|
260
node_modules/@codemirror/search/dist/index.cjs
generated
vendored
260
node_modules/@codemirror/search/dist/index.cjs
generated
vendored
|
@ -30,7 +30,8 @@ class SearchCursor {
|
|||
[`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
||||
(when supported).
|
||||
*/
|
||||
constructor(text, query, from = 0, to = text.length, normalize) {
|
||||
constructor(text, query, from = 0, to = text.length, normalize, test) {
|
||||
this.test = test;
|
||||
/**
|
||||
The current match (only holds a meaningful value after
|
||||
[`next`](https://codemirror.net/6/docs/ref/#search.SearchCursor.next) has been called and when
|
||||
|
@ -124,6 +125,8 @@ class SearchCursor {
|
|||
else
|
||||
this.matches.push(1, pos);
|
||||
}
|
||||
if (match && this.test && !this.test(match.from, match.to, this.buffer, this.bufferPos))
|
||||
match = null;
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +147,7 @@ class RegExpCursor {
|
|||
`new RegExp`).
|
||||
*/
|
||||
constructor(text, query, options, from = 0, to = text.length) {
|
||||
this.text = text;
|
||||
this.to = to;
|
||||
this.curLine = "";
|
||||
/**
|
||||
|
@ -160,10 +164,11 @@ class RegExpCursor {
|
|||
if (/\\[sWDnr]|\n|\r|\[\^/.test(query))
|
||||
return new MultilineRegExpCursor(text, query, options, from, to);
|
||||
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
||||
this.test = options === null || options === void 0 ? void 0 : options.test;
|
||||
this.iter = text.iter();
|
||||
let startLine = text.lineAt(from);
|
||||
this.curLineStart = startLine.from;
|
||||
this.matchPos = from;
|
||||
this.matchPos = toCharEnd(text, from);
|
||||
this.getLine(this.curLineStart);
|
||||
}
|
||||
getLine(skip) {
|
||||
|
@ -194,10 +199,10 @@ class RegExpCursor {
|
|||
let match = this.matchPos <= this.to && this.re.exec(this.curLine);
|
||||
if (match) {
|
||||
let from = this.curLineStart + match.index, to = from + match[0].length;
|
||||
this.matchPos = to + (from == to ? 1 : 0);
|
||||
if (from == this.curLine.length)
|
||||
this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0));
|
||||
if (from == this.curLineStart + this.curLine.length)
|
||||
this.nextLine();
|
||||
if (from < to || from > this.value.to) {
|
||||
if ((from < to || from > this.value.to) && (!this.test || this.test(from, to, match))) {
|
||||
this.value = { from, to, match };
|
||||
return this;
|
||||
}
|
||||
|
@ -248,9 +253,10 @@ class MultilineRegExpCursor {
|
|||
this.to = to;
|
||||
this.done = false;
|
||||
this.value = empty;
|
||||
this.matchPos = from;
|
||||
this.matchPos = toCharEnd(text, from);
|
||||
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
||||
this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + 5000 /* Base */));
|
||||
this.test = options === null || options === void 0 ? void 0 : options.test;
|
||||
this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + 5000 /* Chunk.Base */));
|
||||
}
|
||||
chunkEnd(pos) {
|
||||
return pos >= this.to ? this.to : this.text.lineAt(pos).to;
|
||||
|
@ -264,24 +270,23 @@ class MultilineRegExpCursor {
|
|||
this.re.lastIndex = off + 1;
|
||||
match = this.re.exec(this.flat.text);
|
||||
}
|
||||
// If a match goes almost to the end of a noncomplete chunk, try
|
||||
// again, since it'll likely be able to match more
|
||||
if (match && this.flat.to < this.to && match.index + match[0].length > this.flat.text.length - 10)
|
||||
match = null;
|
||||
if (match) {
|
||||
let from = this.flat.from + match.index, to = from + match[0].length;
|
||||
this.value = { from, to, match };
|
||||
this.matchPos = to + (from == to ? 1 : 0);
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
if (this.flat.to == this.to) {
|
||||
this.done = true;
|
||||
// If a match goes almost to the end of a noncomplete chunk, try
|
||||
// again, since it'll likely be able to match more
|
||||
if ((this.flat.to >= this.to || match.index + match[0].length <= this.flat.text.length - 10) &&
|
||||
(!this.test || this.test(from, to, match))) {
|
||||
this.value = { from, to, match };
|
||||
this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0));
|
||||
return this;
|
||||
}
|
||||
// Grow the flattened doc
|
||||
this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2));
|
||||
}
|
||||
if (this.flat.to == this.to) {
|
||||
this.done = true;
|
||||
return this;
|
||||
}
|
||||
// Grow the flattened doc
|
||||
this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,6 +303,14 @@ function validRegExp(source) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
function toCharEnd(text, pos) {
|
||||
if (pos >= text.length)
|
||||
return pos;
|
||||
let line = text.lineAt(pos), next;
|
||||
while (pos < line.to && (next = line.text.charCodeAt(pos - line.from)) >= 0xDC00 && next < 0xE000)
|
||||
pos++;
|
||||
return pos;
|
||||
}
|
||||
|
||||
function createLineDialog(view) {
|
||||
let input = elt__default["default"]("input", { class: "cm-textfield", name: "line" });
|
||||
|
@ -549,12 +562,13 @@ const selectNextOccurrence = ({ state: state$1, dispatch }) => {
|
|||
|
||||
const searchConfigFacet = state.Facet.define({
|
||||
combine(configs) {
|
||||
var _a;
|
||||
return {
|
||||
top: configs.reduce((val, conf) => val !== null && val !== void 0 ? val : conf.top, undefined) || false,
|
||||
caseSensitive: configs.reduce((val, conf) => val !== null && val !== void 0 ? val : conf.caseSensitive, undefined) || false,
|
||||
createPanel: ((_a = configs.find(c => c.createPanel)) === null || _a === void 0 ? void 0 : _a.createPanel) || (view => new SearchPanel(view))
|
||||
};
|
||||
return state.combineConfig(configs, {
|
||||
top: false,
|
||||
caseSensitive: false,
|
||||
literal: false,
|
||||
wholeWord: false,
|
||||
createPanel: view => new SearchPanel(view)
|
||||
});
|
||||
}
|
||||
});
|
||||
/**
|
||||
|
@ -576,17 +590,27 @@ class SearchQuery {
|
|||
constructor(config) {
|
||||
this.search = config.search;
|
||||
this.caseSensitive = !!config.caseSensitive;
|
||||
this.literal = !!config.literal;
|
||||
this.regexp = !!config.regexp;
|
||||
this.replace = config.replace || "";
|
||||
this.valid = !!this.search && (!this.regexp || validRegExp(this.search));
|
||||
this.unquoted = config.literal ? this.search : this.search.replace(/\\([nrt\\])/g, (_, ch) => ch == "n" ? "\n" : ch == "r" ? "\r" : ch == "t" ? "\t" : "\\");
|
||||
this.unquoted = this.unquote(this.search);
|
||||
this.wholeWord = !!config.wholeWord;
|
||||
}
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
unquote(text) {
|
||||
return this.literal ? text :
|
||||
text.replace(/\\([nrt\\])/g, (_, ch) => ch == "n" ? "\n" : ch == "r" ? "\r" : ch == "t" ? "\t" : "\\");
|
||||
}
|
||||
/**
|
||||
Compare this query to another query.
|
||||
*/
|
||||
eq(other) {
|
||||
return this.search == other.search && this.replace == other.replace &&
|
||||
this.caseSensitive == other.caseSensitive && this.regexp == other.regexp;
|
||||
this.caseSensitive == other.caseSensitive && this.regexp == other.regexp &&
|
||||
this.wholeWord == other.wholeWord;
|
||||
}
|
||||
/**
|
||||
@internal
|
||||
|
@ -596,10 +620,13 @@ class SearchQuery {
|
|||
}
|
||||
/**
|
||||
Get a search cursor for this query, searching through the given
|
||||
range in the given document.
|
||||
range in the given state.
|
||||
*/
|
||||
getCursor(doc, from = 0, to = doc.length) {
|
||||
return this.regexp ? regexpCursor(this, doc, from, to) : stringCursor(this, doc, from, to);
|
||||
getCursor(state$1, from = 0, to) {
|
||||
let st = state$1.doc ? state$1 : state.EditorState.create({ doc: state$1 });
|
||||
if (to == null)
|
||||
to = st.doc.length;
|
||||
return this.regexp ? regexpCursor(this, st, from, to) : stringCursor(this, st, from, to);
|
||||
}
|
||||
}
|
||||
class QueryType {
|
||||
|
@ -607,41 +634,53 @@ class QueryType {
|
|||
this.spec = spec;
|
||||
}
|
||||
}
|
||||
function stringCursor(spec, doc, from, to) {
|
||||
return new SearchCursor(doc, spec.unquoted, from, to, spec.caseSensitive ? undefined : x => x.toLowerCase());
|
||||
function stringCursor(spec, state, from, to) {
|
||||
return new SearchCursor(state.doc, spec.unquoted, from, to, spec.caseSensitive ? undefined : x => x.toLowerCase(), spec.wholeWord ? stringWordTest(state.doc, state.charCategorizer(state.selection.main.head)) : undefined);
|
||||
}
|
||||
function stringWordTest(doc, categorizer) {
|
||||
return (from, to, buf, bufPos) => {
|
||||
if (bufPos > from || bufPos + buf.length < to) {
|
||||
bufPos = Math.max(0, from - 2);
|
||||
buf = doc.sliceString(bufPos, Math.min(doc.length, to + 2));
|
||||
}
|
||||
return (categorizer(charBefore(buf, from - bufPos)) != state.CharCategory.Word ||
|
||||
categorizer(charAfter(buf, from - bufPos)) != state.CharCategory.Word) &&
|
||||
(categorizer(charAfter(buf, to - bufPos)) != state.CharCategory.Word ||
|
||||
categorizer(charBefore(buf, to - bufPos)) != state.CharCategory.Word);
|
||||
};
|
||||
}
|
||||
class StringQuery extends QueryType {
|
||||
constructor(spec) {
|
||||
super(spec);
|
||||
}
|
||||
nextMatch(doc, curFrom, curTo) {
|
||||
let cursor = stringCursor(this.spec, doc, curTo, doc.length).nextOverlapping();
|
||||
nextMatch(state, curFrom, curTo) {
|
||||
let cursor = stringCursor(this.spec, state, curTo, state.doc.length).nextOverlapping();
|
||||
if (cursor.done)
|
||||
cursor = stringCursor(this.spec, doc, 0, curFrom).nextOverlapping();
|
||||
cursor = stringCursor(this.spec, state, 0, curFrom).nextOverlapping();
|
||||
return cursor.done ? null : cursor.value;
|
||||
}
|
||||
// Searching in reverse is, rather than implementing inverted search
|
||||
// cursor, done by scanning chunk after chunk forward.
|
||||
prevMatchInRange(doc, from, to) {
|
||||
prevMatchInRange(state, from, to) {
|
||||
for (let pos = to;;) {
|
||||
let start = Math.max(from, pos - 10000 /* ChunkSize */ - this.spec.unquoted.length);
|
||||
let cursor = stringCursor(this.spec, doc, start, pos), range = null;
|
||||
let start = Math.max(from, pos - 10000 /* FindPrev.ChunkSize */ - this.spec.unquoted.length);
|
||||
let cursor = stringCursor(this.spec, state, start, pos), range = null;
|
||||
while (!cursor.nextOverlapping().done)
|
||||
range = cursor.value;
|
||||
if (range)
|
||||
return range;
|
||||
if (start == from)
|
||||
return null;
|
||||
pos -= 10000 /* ChunkSize */;
|
||||
pos -= 10000 /* FindPrev.ChunkSize */;
|
||||
}
|
||||
}
|
||||
prevMatch(doc, curFrom, curTo) {
|
||||
return this.prevMatchInRange(doc, 0, curFrom) ||
|
||||
this.prevMatchInRange(doc, curTo, doc.length);
|
||||
prevMatch(state, curFrom, curTo) {
|
||||
return this.prevMatchInRange(state, 0, curFrom) ||
|
||||
this.prevMatchInRange(state, curTo, state.doc.length);
|
||||
}
|
||||
getReplacement(_result) { return this.spec.replace; }
|
||||
matchAll(doc, limit) {
|
||||
let cursor = stringCursor(this.spec, doc, 0, doc.length), ranges = [];
|
||||
getReplacement(_result) { return this.spec.unquote(this.spec.replace); }
|
||||
matchAll(state, limit) {
|
||||
let cursor = stringCursor(this.spec, state, 0, state.doc.length), ranges = [];
|
||||
while (!cursor.next().done) {
|
||||
if (ranges.length >= limit)
|
||||
return null;
|
||||
|
@ -649,26 +688,42 @@ class StringQuery extends QueryType {
|
|||
}
|
||||
return ranges;
|
||||
}
|
||||
highlight(doc, from, to, add) {
|
||||
let cursor = stringCursor(this.spec, doc, Math.max(0, from - this.spec.unquoted.length), Math.min(to + this.spec.unquoted.length, doc.length));
|
||||
highlight(state, from, to, add) {
|
||||
let cursor = stringCursor(this.spec, state, Math.max(0, from - this.spec.unquoted.length), Math.min(to + this.spec.unquoted.length, state.doc.length));
|
||||
while (!cursor.next().done)
|
||||
add(cursor.value.from, cursor.value.to);
|
||||
}
|
||||
}
|
||||
function regexpCursor(spec, doc, from, to) {
|
||||
return new RegExpCursor(doc, spec.search, spec.caseSensitive ? undefined : { ignoreCase: true }, from, to);
|
||||
function regexpCursor(spec, state, from, to) {
|
||||
return new RegExpCursor(state.doc, spec.search, {
|
||||
ignoreCase: !spec.caseSensitive,
|
||||
test: spec.wholeWord ? regexpWordTest(state.charCategorizer(state.selection.main.head)) : undefined
|
||||
}, from, to);
|
||||
}
|
||||
function charBefore(str, index) {
|
||||
return str.slice(state.findClusterBreak(str, index, false), index);
|
||||
}
|
||||
function charAfter(str, index) {
|
||||
return str.slice(index, state.findClusterBreak(str, index));
|
||||
}
|
||||
function regexpWordTest(categorizer) {
|
||||
return (_from, _to, match) => !match[0].length ||
|
||||
(categorizer(charBefore(match.input, match.index)) != state.CharCategory.Word ||
|
||||
categorizer(charAfter(match.input, match.index)) != state.CharCategory.Word) &&
|
||||
(categorizer(charAfter(match.input, match.index + match[0].length)) != state.CharCategory.Word ||
|
||||
categorizer(charBefore(match.input, match.index + match[0].length)) != state.CharCategory.Word);
|
||||
}
|
||||
class RegExpQuery extends QueryType {
|
||||
nextMatch(doc, curFrom, curTo) {
|
||||
let cursor = regexpCursor(this.spec, doc, curTo, doc.length).next();
|
||||
nextMatch(state, curFrom, curTo) {
|
||||
let cursor = regexpCursor(this.spec, state, curTo, state.doc.length).next();
|
||||
if (cursor.done)
|
||||
cursor = regexpCursor(this.spec, doc, 0, curFrom).next();
|
||||
cursor = regexpCursor(this.spec, state, 0, curFrom).next();
|
||||
return cursor.done ? null : cursor.value;
|
||||
}
|
||||
prevMatchInRange(doc, from, to) {
|
||||
prevMatchInRange(state, from, to) {
|
||||
for (let size = 1;; size++) {
|
||||
let start = Math.max(from, to - size * 10000 /* ChunkSize */);
|
||||
let cursor = regexpCursor(this.spec, doc, start, to), range = null;
|
||||
let start = Math.max(from, to - size * 10000 /* FindPrev.ChunkSize */);
|
||||
let cursor = regexpCursor(this.spec, state, start, to), range = null;
|
||||
while (!cursor.next().done)
|
||||
range = cursor.value;
|
||||
if (range && (start == from || range.from > start + 10))
|
||||
|
@ -677,18 +732,18 @@ class RegExpQuery extends QueryType {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
prevMatch(doc, curFrom, curTo) {
|
||||
return this.prevMatchInRange(doc, 0, curFrom) ||
|
||||
this.prevMatchInRange(doc, curTo, doc.length);
|
||||
prevMatch(state, curFrom, curTo) {
|
||||
return this.prevMatchInRange(state, 0, curFrom) ||
|
||||
this.prevMatchInRange(state, curTo, state.doc.length);
|
||||
}
|
||||
getReplacement(result) {
|
||||
return this.spec.replace.replace(/\$([$&\d+])/g, (m, i) => i == "$" ? "$"
|
||||
return this.spec.unquote(this.spec.replace.replace(/\$([$&\d+])/g, (m, i) => i == "$" ? "$"
|
||||
: i == "&" ? result.match[0]
|
||||
: i != "0" && +i < result.match.length ? result.match[i]
|
||||
: m);
|
||||
: m));
|
||||
}
|
||||
matchAll(doc, limit) {
|
||||
let cursor = regexpCursor(this.spec, doc, 0, doc.length), ranges = [];
|
||||
matchAll(state, limit) {
|
||||
let cursor = regexpCursor(this.spec, state, 0, state.doc.length), ranges = [];
|
||||
while (!cursor.next().done) {
|
||||
if (ranges.length >= limit)
|
||||
return null;
|
||||
|
@ -696,8 +751,8 @@ class RegExpQuery extends QueryType {
|
|||
}
|
||||
return ranges;
|
||||
}
|
||||
highlight(doc, from, to, add) {
|
||||
let cursor = regexpCursor(this.spec, doc, Math.max(0, from - 250 /* HighlightMargin */), Math.min(to + 250 /* HighlightMargin */, doc.length));
|
||||
highlight(state, from, to, add) {
|
||||
let cursor = regexpCursor(this.spec, state, Math.max(0, from - 250 /* RegExp.HighlightMargin */), Math.min(to + 250 /* RegExp.HighlightMargin */, state.doc.length));
|
||||
while (!cursor.next().done)
|
||||
add(cursor.value.from, cursor.value.to);
|
||||
}
|
||||
|
@ -733,6 +788,13 @@ function getSearchQuery(state) {
|
|||
let curState = state.field(searchState, false);
|
||||
return curState ? curState.query.spec : defaultQuery(state);
|
||||
}
|
||||
/**
|
||||
Query whether the search panel is open in the given editor state.
|
||||
*/
|
||||
function searchPanelOpen(state) {
|
||||
var _a;
|
||||
return ((_a = state.field(searchState, false)) === null || _a === void 0 ? void 0 : _a.panel) != null;
|
||||
}
|
||||
class SearchState {
|
||||
constructor(query, panel) {
|
||||
this.query = query;
|
||||
|
@ -757,9 +819,9 @@ const searchHighlighter = view.ViewPlugin.fromClass(class {
|
|||
let builder = new state.RangeSetBuilder();
|
||||
for (let i = 0, ranges = view$1.visibleRanges, l = ranges.length; i < l; i++) {
|
||||
let { from, to } = ranges[i];
|
||||
while (i < l - 1 && to > ranges[i + 1].from - 2 * 250 /* HighlightMargin */)
|
||||
while (i < l - 1 && to > ranges[i + 1].from - 2 * 250 /* RegExp.HighlightMargin */)
|
||||
to = ranges[++i].to;
|
||||
query.highlight(view$1.state.doc, from, to, (from, to) => {
|
||||
query.highlight(view$1.state, from, to, (from, to) => {
|
||||
let selected = view$1.state.selection.ranges.some(r => r.from == from && r.to == to);
|
||||
builder.add(from, to, selected ? selectedMatchMark : matchMark);
|
||||
});
|
||||
|
@ -782,9 +844,9 @@ Will wrap around to the start of the document when it reaches the
|
|||
end.
|
||||
*/
|
||||
const findNext = searchCommand((view, { query }) => {
|
||||
let { from, to } = view.state.selection.main;
|
||||
let next = query.nextMatch(view.state.doc, from, to);
|
||||
if (!next || next.from == from && next.to == to)
|
||||
let { to } = view.state.selection.main;
|
||||
let next = query.nextMatch(view.state, to, to);
|
||||
if (!next)
|
||||
return false;
|
||||
view.dispatch({
|
||||
selection: { anchor: next.from, head: next.to },
|
||||
|
@ -800,8 +862,8 @@ before the current main selection. Will wrap past the start
|
|||
of the document to start searching at the end again.
|
||||
*/
|
||||
const findPrevious = searchCommand((view, { query }) => {
|
||||
let { state } = view, { from, to } = state.selection.main;
|
||||
let range = query.prevMatch(state.doc, from, to);
|
||||
let { state } = view, { from } = state.selection.main;
|
||||
let range = query.prevMatch(state, from, from);
|
||||
if (!range)
|
||||
return false;
|
||||
view.dispatch({
|
||||
|
@ -816,7 +878,7 @@ const findPrevious = searchCommand((view, { query }) => {
|
|||
Select all instances of the search query.
|
||||
*/
|
||||
const selectMatches = searchCommand((view, { query }) => {
|
||||
let ranges = query.matchAll(view.state.doc, 1000);
|
||||
let ranges = query.matchAll(view.state, 1000);
|
||||
if (!ranges || !ranges.length)
|
||||
return false;
|
||||
view.dispatch({
|
||||
|
@ -854,7 +916,7 @@ const replaceNext = searchCommand((view$1, { query }) => {
|
|||
let { state } = view$1, { from, to } = state.selection.main;
|
||||
if (state.readOnly)
|
||||
return false;
|
||||
let next = query.nextMatch(state.doc, from, from);
|
||||
let next = query.nextMatch(state, from, from);
|
||||
if (!next)
|
||||
return false;
|
||||
let changes = [], selection, replacement;
|
||||
|
@ -862,7 +924,7 @@ const replaceNext = searchCommand((view$1, { query }) => {
|
|||
if (next.from == from && next.to == to) {
|
||||
replacement = state.toText(query.getReplacement(next));
|
||||
changes.push({ from: next.from, to: next.to, insert: replacement });
|
||||
next = query.nextMatch(state.doc, next.from, next.to);
|
||||
next = query.nextMatch(state, next.from, next.to);
|
||||
announce.push(view.EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
|
||||
}
|
||||
if (next) {
|
||||
|
@ -885,7 +947,7 @@ replacement.
|
|||
const replaceAll = searchCommand((view$1, { query }) => {
|
||||
if (view$1.state.readOnly)
|
||||
return false;
|
||||
let changes = query.matchAll(view$1.state.doc, 1e9).map(match => {
|
||||
let changes = query.matchAll(view$1.state, 1e9).map(match => {
|
||||
let { from, to } = match;
|
||||
return { from, to, insert: query.getReplacement(match) };
|
||||
});
|
||||
|
@ -903,11 +965,18 @@ function createSearchPanel(view) {
|
|||
return view.state.facet(searchConfigFacet).createPanel(view);
|
||||
}
|
||||
function defaultQuery(state, fallback) {
|
||||
var _a;
|
||||
var _a, _b, _c, _d;
|
||||
let sel = state.selection.main;
|
||||
let selText = sel.empty || sel.to > sel.from + 100 ? "" : state.sliceDoc(sel.from, sel.to);
|
||||
let caseSensitive = (_a = fallback === null || fallback === void 0 ? void 0 : fallback.caseSensitive) !== null && _a !== void 0 ? _a : state.facet(searchConfigFacet).caseSensitive;
|
||||
return fallback && !selText ? fallback : new SearchQuery({ search: selText.replace(/\n/g, "\\n"), caseSensitive });
|
||||
if (fallback && !selText)
|
||||
return fallback;
|
||||
let config = state.facet(searchConfigFacet);
|
||||
return new SearchQuery({
|
||||
search: ((_a = fallback === null || fallback === void 0 ? void 0 : fallback.literal) !== null && _a !== void 0 ? _a : config.literal) ? selText : selText.replace(/\n/g, "\\n"),
|
||||
caseSensitive: (_b = fallback === null || fallback === void 0 ? void 0 : fallback.caseSensitive) !== null && _b !== void 0 ? _b : config.caseSensitive,
|
||||
literal: (_c = fallback === null || fallback === void 0 ? void 0 : fallback.literal) !== null && _c !== void 0 ? _c : config.literal,
|
||||
wholeWord: (_d = fallback === null || fallback === void 0 ? void 0 : fallback.wholeWord) !== null && _d !== void 0 ? _d : config.wholeWord
|
||||
});
|
||||
}
|
||||
/**
|
||||
Make sure the search panel is open and focused.
|
||||
|
@ -977,6 +1046,7 @@ class SearchPanel {
|
|||
"aria-label": phrase(view, "Find"),
|
||||
class: "cm-textfield",
|
||||
name: "search",
|
||||
form: "",
|
||||
"main-field": "true",
|
||||
onchange: this.commit,
|
||||
onkeyup: this.commit
|
||||
|
@ -987,21 +1057,31 @@ class SearchPanel {
|
|||
"aria-label": phrase(view, "Replace"),
|
||||
class: "cm-textfield",
|
||||
name: "replace",
|
||||
form: "",
|
||||
onchange: this.commit,
|
||||
onkeyup: this.commit
|
||||
});
|
||||
this.caseField = elt__default["default"]("input", {
|
||||
type: "checkbox",
|
||||
name: "case",
|
||||
form: "",
|
||||
checked: query.caseSensitive,
|
||||
onchange: this.commit
|
||||
});
|
||||
this.reField = elt__default["default"]("input", {
|
||||
type: "checkbox",
|
||||
name: "re",
|
||||
form: "",
|
||||
checked: query.regexp,
|
||||
onchange: this.commit
|
||||
});
|
||||
this.wordField = elt__default["default"]("input", {
|
||||
type: "checkbox",
|
||||
name: "word",
|
||||
form: "",
|
||||
checked: query.wholeWord,
|
||||
onchange: this.commit
|
||||
});
|
||||
function button(name, onclick, content) {
|
||||
return elt__default["default"]("button", { class: "cm-button", name, onclick, type: "button" }, content);
|
||||
}
|
||||
|
@ -1012,18 +1092,19 @@ class SearchPanel {
|
|||
button("select", () => selectMatches(view), [phrase(view, "all")]),
|
||||
elt__default["default"]("label", null, [this.caseField, phrase(view, "match case")]),
|
||||
elt__default["default"]("label", null, [this.reField, phrase(view, "regexp")]),
|
||||
elt__default["default"]("label", null, [this.wordField, phrase(view, "by word")]),
|
||||
...view.state.readOnly ? [] : [
|
||||
elt__default["default"]("br"),
|
||||
this.replaceField,
|
||||
button("replace", () => replaceNext(view), [phrase(view, "replace")]),
|
||||
button("replaceAll", () => replaceAll(view), [phrase(view, "replace all")]),
|
||||
elt__default["default"]("button", {
|
||||
name: "close",
|
||||
onclick: () => closeSearchPanel(view),
|
||||
"aria-label": phrase(view, "close"),
|
||||
type: "button"
|
||||
}, ["×"])
|
||||
]
|
||||
button("replaceAll", () => replaceAll(view), [phrase(view, "replace all")])
|
||||
],
|
||||
elt__default["default"]("button", {
|
||||
name: "close",
|
||||
onclick: () => closeSearchPanel(view),
|
||||
"aria-label": phrase(view, "close"),
|
||||
type: "button"
|
||||
}, ["×"])
|
||||
]);
|
||||
}
|
||||
commit() {
|
||||
|
@ -1031,7 +1112,8 @@ class SearchPanel {
|
|||
search: this.searchField.value,
|
||||
caseSensitive: this.caseField.checked,
|
||||
regexp: this.reField.checked,
|
||||
replace: this.replaceField.value
|
||||
wholeWord: this.wordField.checked,
|
||||
replace: this.replaceField.value,
|
||||
});
|
||||
if (!query.eq(this.query)) {
|
||||
this.query = query;
|
||||
|
@ -1064,6 +1146,7 @@ class SearchPanel {
|
|||
this.replaceField.value = query.replace;
|
||||
this.caseField.checked = query.caseSensitive;
|
||||
this.reField.checked = query.regexp;
|
||||
this.wordField.checked = query.wholeWord;
|
||||
}
|
||||
mount() {
|
||||
this.searchField.select();
|
||||
|
@ -1144,6 +1227,7 @@ exports.replaceAll = replaceAll;
|
|||
exports.replaceNext = replaceNext;
|
||||
exports.search = search;
|
||||
exports.searchKeymap = searchKeymap;
|
||||
exports.searchPanelOpen = searchPanelOpen;
|
||||
exports.selectMatches = selectMatches;
|
||||
exports.selectNextOccurrence = selectNextOccurrence;
|
||||
exports.selectSelectionMatches = selectSelectionMatches;
|
||||
|
|
52
node_modules/@codemirror/search/dist/index.d.ts
generated
vendored
52
node_modules/@codemirror/search/dist/index.d.ts
generated
vendored
|
@ -10,6 +10,7 @@ declare class SearchCursor implements Iterator<{
|
|||
from: number;
|
||||
to: number;
|
||||
}> {
|
||||
private test?;
|
||||
private iter;
|
||||
/**
|
||||
The current match (only holds a meaningful value after
|
||||
|
@ -43,7 +44,7 @@ declare class SearchCursor implements Iterator<{
|
|||
[`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
||||
(when supported).
|
||||
*/
|
||||
constructor(text: Text, query: string, from?: number, to?: number, normalize?: (string: string) => string);
|
||||
constructor(text: Text, query: string, from?: number, to?: number, normalize?: (string: string) => string, test?: ((from: number, to: number, buffer: string, bufferPos: number) => boolean) | undefined);
|
||||
private peek;
|
||||
/**
|
||||
Look for the next match. Updates the iterator's
|
||||
|
@ -65,6 +66,10 @@ declare class SearchCursor implements Iterator<{
|
|||
}>;
|
||||
}
|
||||
|
||||
interface RegExpCursorOptions {
|
||||
ignoreCase?: boolean;
|
||||
test?: (from: number, to: number, match: RegExpExecArray) => boolean;
|
||||
}
|
||||
/**
|
||||
This class is similar to [`SearchCursor`](https://codemirror.net/6/docs/ref/#search.SearchCursor)
|
||||
but searches for a regular expression pattern instead of a plain
|
||||
|
@ -75,9 +80,11 @@ declare class RegExpCursor implements Iterator<{
|
|||
to: number;
|
||||
match: RegExpExecArray;
|
||||
}> {
|
||||
private text;
|
||||
private to;
|
||||
private iter;
|
||||
private re;
|
||||
private test?;
|
||||
private curLine;
|
||||
private curLineStart;
|
||||
private matchPos;
|
||||
|
@ -101,9 +108,7 @@ declare class RegExpCursor implements Iterator<{
|
|||
document. `query` should be the raw pattern (as you'd pass it to
|
||||
`new RegExp`).
|
||||
*/
|
||||
constructor(text: Text, query: string, options?: {
|
||||
ignoreCase?: boolean;
|
||||
}, from?: number, to?: number);
|
||||
constructor(text: Text, query: string, options?: RegExpCursorOptions, from?: number, to?: number);
|
||||
private getLine;
|
||||
private nextLine;
|
||||
/**
|
||||
|
@ -177,6 +182,15 @@ interface SearchConfig {
|
|||
*/
|
||||
caseSensitive?: boolean;
|
||||
/**
|
||||
Whether to treat string searches literally by default (defaults to false).
|
||||
*/
|
||||
literal?: boolean;
|
||||
/**
|
||||
Controls whether the default query has by-word matching enabled.
|
||||
Defaults to false.
|
||||
*/
|
||||
wholeWord?: boolean;
|
||||
/**
|
||||
Can be used to override the way the search panel is implemented.
|
||||
Should create a [Panel](https://codemirror.net/6/docs/ref/#view.Panel) that contains a form
|
||||
which lets the user:
|
||||
|
@ -188,6 +202,9 @@ interface SearchConfig {
|
|||
- Notice external changes to the query by reacting to the
|
||||
appropriate [state effect](https://codemirror.net/6/docs/ref/#search.setSearchQuery).
|
||||
- Run some of the search commands.
|
||||
|
||||
The field that should be focused when opening the panel must be
|
||||
tagged with a `main-field=true` DOM attribute.
|
||||
*/
|
||||
createPanel?: (view: EditorView) => Panel;
|
||||
}
|
||||
|
@ -211,7 +228,13 @@ declare class SearchQuery {
|
|||
*/
|
||||
readonly caseSensitive: boolean;
|
||||
/**
|
||||
Then true, the search string is interpreted as a regular
|
||||
By default, string search will replace `\n`, `\r`, and `\t` in
|
||||
the query with newline, return, and tab characters. When this
|
||||
is set to true, that behavior is disabled.
|
||||
*/
|
||||
readonly literal: boolean;
|
||||
/**
|
||||
When true, the search string is interpreted as a regular
|
||||
expression.
|
||||
*/
|
||||
readonly regexp: boolean;
|
||||
|
@ -226,6 +249,11 @@ declare class SearchQuery {
|
|||
*/
|
||||
readonly valid: boolean;
|
||||
/**
|
||||
When true, matches that contain words are ignored when there are
|
||||
further word characters around them.
|
||||
*/
|
||||
readonly wholeWord: boolean;
|
||||
/**
|
||||
Create a query object.
|
||||
*/
|
||||
constructor(config: {
|
||||
|
@ -251,6 +279,10 @@ declare class SearchQuery {
|
|||
The replace text.
|
||||
*/
|
||||
replace?: string;
|
||||
/**
|
||||
Enable whole-word matching.
|
||||
*/
|
||||
wholeWord?: boolean;
|
||||
});
|
||||
/**
|
||||
Compare this query to another query.
|
||||
|
@ -258,9 +290,9 @@ declare class SearchQuery {
|
|||
eq(other: SearchQuery): boolean;
|
||||
/**
|
||||
Get a search cursor for this query, searching through the given
|
||||
range in the given document.
|
||||
range in the given state.
|
||||
*/
|
||||
getCursor(doc: Text, from?: number, to?: number): Iterator<{
|
||||
getCursor(state: EditorState | Text, from?: number, to?: number): Iterator<{
|
||||
from: number;
|
||||
to: number;
|
||||
}>;
|
||||
|
@ -278,6 +310,10 @@ Get the current search query from an editor state.
|
|||
*/
|
||||
declare function getSearchQuery(state: EditorState): SearchQuery;
|
||||
/**
|
||||
Query whether the search panel is open in the given editor state.
|
||||
*/
|
||||
declare function searchPanelOpen(state: EditorState): boolean;
|
||||
/**
|
||||
Open the search panel if it isn't already open, and move the
|
||||
selection to the first match after the current main selection.
|
||||
Will wrap around to the start of the document when it reaches the
|
||||
|
@ -326,4 +362,4 @@ Default search-related key bindings.
|
|||
*/
|
||||
declare const searchKeymap: readonly KeyBinding[];
|
||||
|
||||
export { RegExpCursor, SearchCursor, SearchQuery, closeSearchPanel, findNext, findPrevious, getSearchQuery, gotoLine, highlightSelectionMatches, openSearchPanel, replaceAll, replaceNext, search, searchKeymap, selectMatches, selectNextOccurrence, selectSelectionMatches, setSearchQuery };
|
||||
export { RegExpCursor, SearchCursor, SearchQuery, closeSearchPanel, findNext, findPrevious, getSearchQuery, gotoLine, highlightSelectionMatches, openSearchPanel, replaceAll, replaceNext, search, searchKeymap, searchPanelOpen, selectMatches, selectNextOccurrence, selectSelectionMatches, setSearchQuery };
|
||||
|
|
263
node_modules/@codemirror/search/dist/index.js
generated
vendored
263
node_modules/@codemirror/search/dist/index.js
generated
vendored
|
@ -1,5 +1,5 @@
|
|||
import { showPanel, EditorView, getPanel, Decoration, ViewPlugin, runScopeHandlers } from '@codemirror/view';
|
||||
import { codePointAt, fromCodePoint, codePointSize, StateEffect, StateField, EditorSelection, Facet, combineConfig, CharCategory, RangeSetBuilder, Prec } from '@codemirror/state';
|
||||
import { codePointAt, fromCodePoint, codePointSize, StateEffect, StateField, EditorSelection, Facet, combineConfig, CharCategory, RangeSetBuilder, Prec, EditorState, findClusterBreak } from '@codemirror/state';
|
||||
import elt from 'crelt';
|
||||
|
||||
const basicNormalize = typeof String.prototype.normalize == "function"
|
||||
|
@ -22,7 +22,8 @@ class SearchCursor {
|
|||
[`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
||||
(when supported).
|
||||
*/
|
||||
constructor(text, query, from = 0, to = text.length, normalize) {
|
||||
constructor(text, query, from = 0, to = text.length, normalize, test) {
|
||||
this.test = test;
|
||||
/**
|
||||
The current match (only holds a meaningful value after
|
||||
[`next`](https://codemirror.net/6/docs/ref/#search.SearchCursor.next) has been called and when
|
||||
|
@ -116,6 +117,8 @@ class SearchCursor {
|
|||
else
|
||||
this.matches.push(1, pos);
|
||||
}
|
||||
if (match && this.test && !this.test(match.from, match.to, this.buffer, this.bufferPos))
|
||||
match = null;
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +139,7 @@ class RegExpCursor {
|
|||
`new RegExp`).
|
||||
*/
|
||||
constructor(text, query, options, from = 0, to = text.length) {
|
||||
this.text = text;
|
||||
this.to = to;
|
||||
this.curLine = "";
|
||||
/**
|
||||
|
@ -152,10 +156,11 @@ class RegExpCursor {
|
|||
if (/\\[sWDnr]|\n|\r|\[\^/.test(query))
|
||||
return new MultilineRegExpCursor(text, query, options, from, to);
|
||||
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
||||
this.test = options === null || options === void 0 ? void 0 : options.test;
|
||||
this.iter = text.iter();
|
||||
let startLine = text.lineAt(from);
|
||||
this.curLineStart = startLine.from;
|
||||
this.matchPos = from;
|
||||
this.matchPos = toCharEnd(text, from);
|
||||
this.getLine(this.curLineStart);
|
||||
}
|
||||
getLine(skip) {
|
||||
|
@ -186,10 +191,10 @@ class RegExpCursor {
|
|||
let match = this.matchPos <= this.to && this.re.exec(this.curLine);
|
||||
if (match) {
|
||||
let from = this.curLineStart + match.index, to = from + match[0].length;
|
||||
this.matchPos = to + (from == to ? 1 : 0);
|
||||
if (from == this.curLine.length)
|
||||
this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0));
|
||||
if (from == this.curLineStart + this.curLine.length)
|
||||
this.nextLine();
|
||||
if (from < to || from > this.value.to) {
|
||||
if ((from < to || from > this.value.to) && (!this.test || this.test(from, to, match))) {
|
||||
this.value = { from, to, match };
|
||||
return this;
|
||||
}
|
||||
|
@ -240,9 +245,10 @@ class MultilineRegExpCursor {
|
|||
this.to = to;
|
||||
this.done = false;
|
||||
this.value = empty;
|
||||
this.matchPos = from;
|
||||
this.matchPos = toCharEnd(text, from);
|
||||
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
||||
this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + 5000 /* Base */));
|
||||
this.test = options === null || options === void 0 ? void 0 : options.test;
|
||||
this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + 5000 /* Chunk.Base */));
|
||||
}
|
||||
chunkEnd(pos) {
|
||||
return pos >= this.to ? this.to : this.text.lineAt(pos).to;
|
||||
|
@ -256,24 +262,23 @@ class MultilineRegExpCursor {
|
|||
this.re.lastIndex = off + 1;
|
||||
match = this.re.exec(this.flat.text);
|
||||
}
|
||||
// If a match goes almost to the end of a noncomplete chunk, try
|
||||
// again, since it'll likely be able to match more
|
||||
if (match && this.flat.to < this.to && match.index + match[0].length > this.flat.text.length - 10)
|
||||
match = null;
|
||||
if (match) {
|
||||
let from = this.flat.from + match.index, to = from + match[0].length;
|
||||
this.value = { from, to, match };
|
||||
this.matchPos = to + (from == to ? 1 : 0);
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
if (this.flat.to == this.to) {
|
||||
this.done = true;
|
||||
// If a match goes almost to the end of a noncomplete chunk, try
|
||||
// again, since it'll likely be able to match more
|
||||
if ((this.flat.to >= this.to || match.index + match[0].length <= this.flat.text.length - 10) &&
|
||||
(!this.test || this.test(from, to, match))) {
|
||||
this.value = { from, to, match };
|
||||
this.matchPos = toCharEnd(this.text, to + (from == to ? 1 : 0));
|
||||
return this;
|
||||
}
|
||||
// Grow the flattened doc
|
||||
this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2));
|
||||
}
|
||||
if (this.flat.to == this.to) {
|
||||
this.done = true;
|
||||
return this;
|
||||
}
|
||||
// Grow the flattened doc
|
||||
this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,6 +295,14 @@ function validRegExp(source) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
function toCharEnd(text, pos) {
|
||||
if (pos >= text.length)
|
||||
return pos;
|
||||
let line = text.lineAt(pos), next;
|
||||
while (pos < line.to && (next = line.text.charCodeAt(pos - line.from)) >= 0xDC00 && next < 0xE000)
|
||||
pos++;
|
||||
return pos;
|
||||
}
|
||||
|
||||
function createLineDialog(view) {
|
||||
let input = elt("input", { class: "cm-textfield", name: "line" });
|
||||
|
@ -541,12 +554,13 @@ const selectNextOccurrence = ({ state, dispatch }) => {
|
|||
|
||||
const searchConfigFacet = /*@__PURE__*/Facet.define({
|
||||
combine(configs) {
|
||||
var _a;
|
||||
return {
|
||||
top: configs.reduce((val, conf) => val !== null && val !== void 0 ? val : conf.top, undefined) || false,
|
||||
caseSensitive: configs.reduce((val, conf) => val !== null && val !== void 0 ? val : conf.caseSensitive, undefined) || false,
|
||||
createPanel: ((_a = configs.find(c => c.createPanel)) === null || _a === void 0 ? void 0 : _a.createPanel) || (view => new SearchPanel(view))
|
||||
};
|
||||
return combineConfig(configs, {
|
||||
top: false,
|
||||
caseSensitive: false,
|
||||
literal: false,
|
||||
wholeWord: false,
|
||||
createPanel: view => new SearchPanel(view)
|
||||
});
|
||||
}
|
||||
});
|
||||
/**
|
||||
|
@ -568,17 +582,27 @@ class SearchQuery {
|
|||
constructor(config) {
|
||||
this.search = config.search;
|
||||
this.caseSensitive = !!config.caseSensitive;
|
||||
this.literal = !!config.literal;
|
||||
this.regexp = !!config.regexp;
|
||||
this.replace = config.replace || "";
|
||||
this.valid = !!this.search && (!this.regexp || validRegExp(this.search));
|
||||
this.unquoted = config.literal ? this.search : this.search.replace(/\\([nrt\\])/g, (_, ch) => ch == "n" ? "\n" : ch == "r" ? "\r" : ch == "t" ? "\t" : "\\");
|
||||
this.unquoted = this.unquote(this.search);
|
||||
this.wholeWord = !!config.wholeWord;
|
||||
}
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
unquote(text) {
|
||||
return this.literal ? text :
|
||||
text.replace(/\\([nrt\\])/g, (_, ch) => ch == "n" ? "\n" : ch == "r" ? "\r" : ch == "t" ? "\t" : "\\");
|
||||
}
|
||||
/**
|
||||
Compare this query to another query.
|
||||
*/
|
||||
eq(other) {
|
||||
return this.search == other.search && this.replace == other.replace &&
|
||||
this.caseSensitive == other.caseSensitive && this.regexp == other.regexp;
|
||||
this.caseSensitive == other.caseSensitive && this.regexp == other.regexp &&
|
||||
this.wholeWord == other.wholeWord;
|
||||
}
|
||||
/**
|
||||
@internal
|
||||
|
@ -588,10 +612,13 @@ class SearchQuery {
|
|||
}
|
||||
/**
|
||||
Get a search cursor for this query, searching through the given
|
||||
range in the given document.
|
||||
range in the given state.
|
||||
*/
|
||||
getCursor(doc, from = 0, to = doc.length) {
|
||||
return this.regexp ? regexpCursor(this, doc, from, to) : stringCursor(this, doc, from, to);
|
||||
getCursor(state, from = 0, to) {
|
||||
let st = state.doc ? state : EditorState.create({ doc: state });
|
||||
if (to == null)
|
||||
to = st.doc.length;
|
||||
return this.regexp ? regexpCursor(this, st, from, to) : stringCursor(this, st, from, to);
|
||||
}
|
||||
}
|
||||
class QueryType {
|
||||
|
@ -599,41 +626,53 @@ class QueryType {
|
|||
this.spec = spec;
|
||||
}
|
||||
}
|
||||
function stringCursor(spec, doc, from, to) {
|
||||
return new SearchCursor(doc, spec.unquoted, from, to, spec.caseSensitive ? undefined : x => x.toLowerCase());
|
||||
function stringCursor(spec, state, from, to) {
|
||||
return new SearchCursor(state.doc, spec.unquoted, from, to, spec.caseSensitive ? undefined : x => x.toLowerCase(), spec.wholeWord ? stringWordTest(state.doc, state.charCategorizer(state.selection.main.head)) : undefined);
|
||||
}
|
||||
function stringWordTest(doc, categorizer) {
|
||||
return (from, to, buf, bufPos) => {
|
||||
if (bufPos > from || bufPos + buf.length < to) {
|
||||
bufPos = Math.max(0, from - 2);
|
||||
buf = doc.sliceString(bufPos, Math.min(doc.length, to + 2));
|
||||
}
|
||||
return (categorizer(charBefore(buf, from - bufPos)) != CharCategory.Word ||
|
||||
categorizer(charAfter(buf, from - bufPos)) != CharCategory.Word) &&
|
||||
(categorizer(charAfter(buf, to - bufPos)) != CharCategory.Word ||
|
||||
categorizer(charBefore(buf, to - bufPos)) != CharCategory.Word);
|
||||
};
|
||||
}
|
||||
class StringQuery extends QueryType {
|
||||
constructor(spec) {
|
||||
super(spec);
|
||||
}
|
||||
nextMatch(doc, curFrom, curTo) {
|
||||
let cursor = stringCursor(this.spec, doc, curTo, doc.length).nextOverlapping();
|
||||
nextMatch(state, curFrom, curTo) {
|
||||
let cursor = stringCursor(this.spec, state, curTo, state.doc.length).nextOverlapping();
|
||||
if (cursor.done)
|
||||
cursor = stringCursor(this.spec, doc, 0, curFrom).nextOverlapping();
|
||||
cursor = stringCursor(this.spec, state, 0, curFrom).nextOverlapping();
|
||||
return cursor.done ? null : cursor.value;
|
||||
}
|
||||
// Searching in reverse is, rather than implementing inverted search
|
||||
// cursor, done by scanning chunk after chunk forward.
|
||||
prevMatchInRange(doc, from, to) {
|
||||
prevMatchInRange(state, from, to) {
|
||||
for (let pos = to;;) {
|
||||
let start = Math.max(from, pos - 10000 /* ChunkSize */ - this.spec.unquoted.length);
|
||||
let cursor = stringCursor(this.spec, doc, start, pos), range = null;
|
||||
let start = Math.max(from, pos - 10000 /* FindPrev.ChunkSize */ - this.spec.unquoted.length);
|
||||
let cursor = stringCursor(this.spec, state, start, pos), range = null;
|
||||
while (!cursor.nextOverlapping().done)
|
||||
range = cursor.value;
|
||||
if (range)
|
||||
return range;
|
||||
if (start == from)
|
||||
return null;
|
||||
pos -= 10000 /* ChunkSize */;
|
||||
pos -= 10000 /* FindPrev.ChunkSize */;
|
||||
}
|
||||
}
|
||||
prevMatch(doc, curFrom, curTo) {
|
||||
return this.prevMatchInRange(doc, 0, curFrom) ||
|
||||
this.prevMatchInRange(doc, curTo, doc.length);
|
||||
prevMatch(state, curFrom, curTo) {
|
||||
return this.prevMatchInRange(state, 0, curFrom) ||
|
||||
this.prevMatchInRange(state, curTo, state.doc.length);
|
||||
}
|
||||
getReplacement(_result) { return this.spec.replace; }
|
||||
matchAll(doc, limit) {
|
||||
let cursor = stringCursor(this.spec, doc, 0, doc.length), ranges = [];
|
||||
getReplacement(_result) { return this.spec.unquote(this.spec.replace); }
|
||||
matchAll(state, limit) {
|
||||
let cursor = stringCursor(this.spec, state, 0, state.doc.length), ranges = [];
|
||||
while (!cursor.next().done) {
|
||||
if (ranges.length >= limit)
|
||||
return null;
|
||||
|
@ -641,26 +680,42 @@ class StringQuery extends QueryType {
|
|||
}
|
||||
return ranges;
|
||||
}
|
||||
highlight(doc, from, to, add) {
|
||||
let cursor = stringCursor(this.spec, doc, Math.max(0, from - this.spec.unquoted.length), Math.min(to + this.spec.unquoted.length, doc.length));
|
||||
highlight(state, from, to, add) {
|
||||
let cursor = stringCursor(this.spec, state, Math.max(0, from - this.spec.unquoted.length), Math.min(to + this.spec.unquoted.length, state.doc.length));
|
||||
while (!cursor.next().done)
|
||||
add(cursor.value.from, cursor.value.to);
|
||||
}
|
||||
}
|
||||
function regexpCursor(spec, doc, from, to) {
|
||||
return new RegExpCursor(doc, spec.search, spec.caseSensitive ? undefined : { ignoreCase: true }, from, to);
|
||||
function regexpCursor(spec, state, from, to) {
|
||||
return new RegExpCursor(state.doc, spec.search, {
|
||||
ignoreCase: !spec.caseSensitive,
|
||||
test: spec.wholeWord ? regexpWordTest(state.charCategorizer(state.selection.main.head)) : undefined
|
||||
}, from, to);
|
||||
}
|
||||
function charBefore(str, index) {
|
||||
return str.slice(findClusterBreak(str, index, false), index);
|
||||
}
|
||||
function charAfter(str, index) {
|
||||
return str.slice(index, findClusterBreak(str, index));
|
||||
}
|
||||
function regexpWordTest(categorizer) {
|
||||
return (_from, _to, match) => !match[0].length ||
|
||||
(categorizer(charBefore(match.input, match.index)) != CharCategory.Word ||
|
||||
categorizer(charAfter(match.input, match.index)) != CharCategory.Word) &&
|
||||
(categorizer(charAfter(match.input, match.index + match[0].length)) != CharCategory.Word ||
|
||||
categorizer(charBefore(match.input, match.index + match[0].length)) != CharCategory.Word);
|
||||
}
|
||||
class RegExpQuery extends QueryType {
|
||||
nextMatch(doc, curFrom, curTo) {
|
||||
let cursor = regexpCursor(this.spec, doc, curTo, doc.length).next();
|
||||
nextMatch(state, curFrom, curTo) {
|
||||
let cursor = regexpCursor(this.spec, state, curTo, state.doc.length).next();
|
||||
if (cursor.done)
|
||||
cursor = regexpCursor(this.spec, doc, 0, curFrom).next();
|
||||
cursor = regexpCursor(this.spec, state, 0, curFrom).next();
|
||||
return cursor.done ? null : cursor.value;
|
||||
}
|
||||
prevMatchInRange(doc, from, to) {
|
||||
prevMatchInRange(state, from, to) {
|
||||
for (let size = 1;; size++) {
|
||||
let start = Math.max(from, to - size * 10000 /* ChunkSize */);
|
||||
let cursor = regexpCursor(this.spec, doc, start, to), range = null;
|
||||
let start = Math.max(from, to - size * 10000 /* FindPrev.ChunkSize */);
|
||||
let cursor = regexpCursor(this.spec, state, start, to), range = null;
|
||||
while (!cursor.next().done)
|
||||
range = cursor.value;
|
||||
if (range && (start == from || range.from > start + 10))
|
||||
|
@ -669,18 +724,18 @@ class RegExpQuery extends QueryType {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
prevMatch(doc, curFrom, curTo) {
|
||||
return this.prevMatchInRange(doc, 0, curFrom) ||
|
||||
this.prevMatchInRange(doc, curTo, doc.length);
|
||||
prevMatch(state, curFrom, curTo) {
|
||||
return this.prevMatchInRange(state, 0, curFrom) ||
|
||||
this.prevMatchInRange(state, curTo, state.doc.length);
|
||||
}
|
||||
getReplacement(result) {
|
||||
return this.spec.replace.replace(/\$([$&\d+])/g, (m, i) => i == "$" ? "$"
|
||||
return this.spec.unquote(this.spec.replace.replace(/\$([$&\d+])/g, (m, i) => i == "$" ? "$"
|
||||
: i == "&" ? result.match[0]
|
||||
: i != "0" && +i < result.match.length ? result.match[i]
|
||||
: m);
|
||||
: m));
|
||||
}
|
||||
matchAll(doc, limit) {
|
||||
let cursor = regexpCursor(this.spec, doc, 0, doc.length), ranges = [];
|
||||
matchAll(state, limit) {
|
||||
let cursor = regexpCursor(this.spec, state, 0, state.doc.length), ranges = [];
|
||||
while (!cursor.next().done) {
|
||||
if (ranges.length >= limit)
|
||||
return null;
|
||||
|
@ -688,8 +743,8 @@ class RegExpQuery extends QueryType {
|
|||
}
|
||||
return ranges;
|
||||
}
|
||||
highlight(doc, from, to, add) {
|
||||
let cursor = regexpCursor(this.spec, doc, Math.max(0, from - 250 /* HighlightMargin */), Math.min(to + 250 /* HighlightMargin */, doc.length));
|
||||
highlight(state, from, to, add) {
|
||||
let cursor = regexpCursor(this.spec, state, Math.max(0, from - 250 /* RegExp.HighlightMargin */), Math.min(to + 250 /* RegExp.HighlightMargin */, state.doc.length));
|
||||
while (!cursor.next().done)
|
||||
add(cursor.value.from, cursor.value.to);
|
||||
}
|
||||
|
@ -725,6 +780,13 @@ function getSearchQuery(state) {
|
|||
let curState = state.field(searchState, false);
|
||||
return curState ? curState.query.spec : defaultQuery(state);
|
||||
}
|
||||
/**
|
||||
Query whether the search panel is open in the given editor state.
|
||||
*/
|
||||
function searchPanelOpen(state) {
|
||||
var _a;
|
||||
return ((_a = state.field(searchState, false)) === null || _a === void 0 ? void 0 : _a.panel) != null;
|
||||
}
|
||||
class SearchState {
|
||||
constructor(query, panel) {
|
||||
this.query = query;
|
||||
|
@ -749,9 +811,9 @@ const searchHighlighter = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|||
let builder = new RangeSetBuilder();
|
||||
for (let i = 0, ranges = view.visibleRanges, l = ranges.length; i < l; i++) {
|
||||
let { from, to } = ranges[i];
|
||||
while (i < l - 1 && to > ranges[i + 1].from - 2 * 250 /* HighlightMargin */)
|
||||
while (i < l - 1 && to > ranges[i + 1].from - 2 * 250 /* RegExp.HighlightMargin */)
|
||||
to = ranges[++i].to;
|
||||
query.highlight(view.state.doc, from, to, (from, to) => {
|
||||
query.highlight(view.state, from, to, (from, to) => {
|
||||
let selected = view.state.selection.ranges.some(r => r.from == from && r.to == to);
|
||||
builder.add(from, to, selected ? selectedMatchMark : matchMark);
|
||||
});
|
||||
|
@ -774,9 +836,9 @@ Will wrap around to the start of the document when it reaches the
|
|||
end.
|
||||
*/
|
||||
const findNext = /*@__PURE__*/searchCommand((view, { query }) => {
|
||||
let { from, to } = view.state.selection.main;
|
||||
let next = query.nextMatch(view.state.doc, from, to);
|
||||
if (!next || next.from == from && next.to == to)
|
||||
let { to } = view.state.selection.main;
|
||||
let next = query.nextMatch(view.state, to, to);
|
||||
if (!next)
|
||||
return false;
|
||||
view.dispatch({
|
||||
selection: { anchor: next.from, head: next.to },
|
||||
|
@ -792,8 +854,8 @@ before the current main selection. Will wrap past the start
|
|||
of the document to start searching at the end again.
|
||||
*/
|
||||
const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
|
||||
let { state } = view, { from, to } = state.selection.main;
|
||||
let range = query.prevMatch(state.doc, from, to);
|
||||
let { state } = view, { from } = state.selection.main;
|
||||
let range = query.prevMatch(state, from, from);
|
||||
if (!range)
|
||||
return false;
|
||||
view.dispatch({
|
||||
|
@ -808,7 +870,7 @@ const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
|
|||
Select all instances of the search query.
|
||||
*/
|
||||
const selectMatches = /*@__PURE__*/searchCommand((view, { query }) => {
|
||||
let ranges = query.matchAll(view.state.doc, 1000);
|
||||
let ranges = query.matchAll(view.state, 1000);
|
||||
if (!ranges || !ranges.length)
|
||||
return false;
|
||||
view.dispatch({
|
||||
|
@ -846,7 +908,7 @@ const replaceNext = /*@__PURE__*/searchCommand((view, { query }) => {
|
|||
let { state } = view, { from, to } = state.selection.main;
|
||||
if (state.readOnly)
|
||||
return false;
|
||||
let next = query.nextMatch(state.doc, from, from);
|
||||
let next = query.nextMatch(state, from, from);
|
||||
if (!next)
|
||||
return false;
|
||||
let changes = [], selection, replacement;
|
||||
|
@ -854,7 +916,7 @@ const replaceNext = /*@__PURE__*/searchCommand((view, { query }) => {
|
|||
if (next.from == from && next.to == to) {
|
||||
replacement = state.toText(query.getReplacement(next));
|
||||
changes.push({ from: next.from, to: next.to, insert: replacement });
|
||||
next = query.nextMatch(state.doc, next.from, next.to);
|
||||
next = query.nextMatch(state, next.from, next.to);
|
||||
announce.push(EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
|
||||
}
|
||||
if (next) {
|
||||
|
@ -877,7 +939,7 @@ replacement.
|
|||
const replaceAll = /*@__PURE__*/searchCommand((view, { query }) => {
|
||||
if (view.state.readOnly)
|
||||
return false;
|
||||
let changes = query.matchAll(view.state.doc, 1e9).map(match => {
|
||||
let changes = query.matchAll(view.state, 1e9).map(match => {
|
||||
let { from, to } = match;
|
||||
return { from, to, insert: query.getReplacement(match) };
|
||||
});
|
||||
|
@ -895,11 +957,18 @@ function createSearchPanel(view) {
|
|||
return view.state.facet(searchConfigFacet).createPanel(view);
|
||||
}
|
||||
function defaultQuery(state, fallback) {
|
||||
var _a;
|
||||
var _a, _b, _c, _d;
|
||||
let sel = state.selection.main;
|
||||
let selText = sel.empty || sel.to > sel.from + 100 ? "" : state.sliceDoc(sel.from, sel.to);
|
||||
let caseSensitive = (_a = fallback === null || fallback === void 0 ? void 0 : fallback.caseSensitive) !== null && _a !== void 0 ? _a : state.facet(searchConfigFacet).caseSensitive;
|
||||
return fallback && !selText ? fallback : new SearchQuery({ search: selText.replace(/\n/g, "\\n"), caseSensitive });
|
||||
if (fallback && !selText)
|
||||
return fallback;
|
||||
let config = state.facet(searchConfigFacet);
|
||||
return new SearchQuery({
|
||||
search: ((_a = fallback === null || fallback === void 0 ? void 0 : fallback.literal) !== null && _a !== void 0 ? _a : config.literal) ? selText : selText.replace(/\n/g, "\\n"),
|
||||
caseSensitive: (_b = fallback === null || fallback === void 0 ? void 0 : fallback.caseSensitive) !== null && _b !== void 0 ? _b : config.caseSensitive,
|
||||
literal: (_c = fallback === null || fallback === void 0 ? void 0 : fallback.literal) !== null && _c !== void 0 ? _c : config.literal,
|
||||
wholeWord: (_d = fallback === null || fallback === void 0 ? void 0 : fallback.wholeWord) !== null && _d !== void 0 ? _d : config.wholeWord
|
||||
});
|
||||
}
|
||||
/**
|
||||
Make sure the search panel is open and focused.
|
||||
|
@ -969,6 +1038,7 @@ class SearchPanel {
|
|||
"aria-label": phrase(view, "Find"),
|
||||
class: "cm-textfield",
|
||||
name: "search",
|
||||
form: "",
|
||||
"main-field": "true",
|
||||
onchange: this.commit,
|
||||
onkeyup: this.commit
|
||||
|
@ -979,21 +1049,31 @@ class SearchPanel {
|
|||
"aria-label": phrase(view, "Replace"),
|
||||
class: "cm-textfield",
|
||||
name: "replace",
|
||||
form: "",
|
||||
onchange: this.commit,
|
||||
onkeyup: this.commit
|
||||
});
|
||||
this.caseField = elt("input", {
|
||||
type: "checkbox",
|
||||
name: "case",
|
||||
form: "",
|
||||
checked: query.caseSensitive,
|
||||
onchange: this.commit
|
||||
});
|
||||
this.reField = elt("input", {
|
||||
type: "checkbox",
|
||||
name: "re",
|
||||
form: "",
|
||||
checked: query.regexp,
|
||||
onchange: this.commit
|
||||
});
|
||||
this.wordField = elt("input", {
|
||||
type: "checkbox",
|
||||
name: "word",
|
||||
form: "",
|
||||
checked: query.wholeWord,
|
||||
onchange: this.commit
|
||||
});
|
||||
function button(name, onclick, content) {
|
||||
return elt("button", { class: "cm-button", name, onclick, type: "button" }, content);
|
||||
}
|
||||
|
@ -1004,18 +1084,19 @@ class SearchPanel {
|
|||
button("select", () => selectMatches(view), [phrase(view, "all")]),
|
||||
elt("label", null, [this.caseField, phrase(view, "match case")]),
|
||||
elt("label", null, [this.reField, phrase(view, "regexp")]),
|
||||
elt("label", null, [this.wordField, phrase(view, "by word")]),
|
||||
...view.state.readOnly ? [] : [
|
||||
elt("br"),
|
||||
this.replaceField,
|
||||
button("replace", () => replaceNext(view), [phrase(view, "replace")]),
|
||||
button("replaceAll", () => replaceAll(view), [phrase(view, "replace all")]),
|
||||
elt("button", {
|
||||
name: "close",
|
||||
onclick: () => closeSearchPanel(view),
|
||||
"aria-label": phrase(view, "close"),
|
||||
type: "button"
|
||||
}, ["×"])
|
||||
]
|
||||
button("replaceAll", () => replaceAll(view), [phrase(view, "replace all")])
|
||||
],
|
||||
elt("button", {
|
||||
name: "close",
|
||||
onclick: () => closeSearchPanel(view),
|
||||
"aria-label": phrase(view, "close"),
|
||||
type: "button"
|
||||
}, ["×"])
|
||||
]);
|
||||
}
|
||||
commit() {
|
||||
|
@ -1023,7 +1104,8 @@ class SearchPanel {
|
|||
search: this.searchField.value,
|
||||
caseSensitive: this.caseField.checked,
|
||||
regexp: this.reField.checked,
|
||||
replace: this.replaceField.value
|
||||
wholeWord: this.wordField.checked,
|
||||
replace: this.replaceField.value,
|
||||
});
|
||||
if (!query.eq(this.query)) {
|
||||
this.query = query;
|
||||
|
@ -1056,6 +1138,7 @@ class SearchPanel {
|
|||
this.replaceField.value = query.replace;
|
||||
this.caseField.checked = query.caseSensitive;
|
||||
this.reField.checked = query.regexp;
|
||||
this.wordField.checked = query.wholeWord;
|
||||
}
|
||||
mount() {
|
||||
this.searchField.select();
|
||||
|
@ -1122,4 +1205,4 @@ const searchExtensions = [
|
|||
baseTheme
|
||||
];
|
||||
|
||||
export { RegExpCursor, SearchCursor, SearchQuery, closeSearchPanel, findNext, findPrevious, getSearchQuery, gotoLine, highlightSelectionMatches, openSearchPanel, replaceAll, replaceNext, search, searchKeymap, selectMatches, selectNextOccurrence, selectSelectionMatches, setSearchQuery };
|
||||
export { RegExpCursor, SearchCursor, SearchQuery, closeSearchPanel, findNext, findPrevious, getSearchQuery, gotoLine, highlightSelectionMatches, openSearchPanel, replaceAll, replaceNext, search, searchKeymap, searchPanelOpen, selectMatches, selectNextOccurrence, selectSelectionMatches, setSearchQuery };
|
||||
|
|
2
node_modules/@codemirror/search/package.json
generated
vendored
2
node_modules/@codemirror/search/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/search",
|
||||
"version": "6.0.0",
|
||||
"version": "6.2.3",
|
||||
"description": "Search functionality for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
|
2
node_modules/@codemirror/state/.github/workflows/dispatch.yml
generated
vendored
2
node_modules/@codemirror/state/.github/workflows/dispatch.yml
generated
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
with:
|
||||
# You should create a personal access token and store it in your repository
|
||||
token: ${{ secrets.DISPATCH_AUTH }}
|
||||
repo: codemirror.next
|
||||
repo: dev
|
||||
owner: codemirror
|
||||
event_type: push
|
||||
|
|
48
node_modules/@codemirror/state/CHANGELOG.md
generated
vendored
48
node_modules/@codemirror/state/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,51 @@
|
|||
## 6.2.0 (2022-12-26)
|
||||
|
||||
### New features
|
||||
|
||||
`EditorSelection.range` now accepts an optional 4th argument to specify the bidi level of the range's head position.
|
||||
|
||||
## 6.1.4 (2022-11-15)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused the `openStart` value passed to span iterators to be incorrect around widgets in some circumstances.
|
||||
|
||||
## 6.1.3 (2022-11-10)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Avoid unnecessary calls to computed facet getters when a state is reconfigured but no dependencies of the computed facet change.
|
||||
|
||||
Fix an infinite loop in `RangeSet.eq` when the `to` parameter isn't given.
|
||||
|
||||
## 6.1.2 (2022-09-21)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where, when multiple transaction extenders took effect, only the highest-precedence one was actually included in the transaction.
|
||||
|
||||
## 6.1.1 (2022-08-03)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug in range set span iteration that would cause decorations to be inappropriately split in some situations.
|
||||
|
||||
## 6.1.0 (2022-06-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Refine change mapping to preserve insertions made by concurrent changes.
|
||||
|
||||
### New features
|
||||
|
||||
The `enables` option to `Facet.define` may now take a function, which will be called with the facet value to create the extensions.
|
||||
|
||||
## 6.0.1 (2022-06-17)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a problem that caused effects' `map` methods to be called with an incorrect change set when filtering changes.
|
||||
|
||||
## 6.0.0 (2022-06-08)
|
||||
|
||||
### Breaking changes
|
||||
|
|
10
node_modules/@codemirror/state/README.md
generated
vendored
10
node_modules/@codemirror/state/README.md
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
# @codemirror/state [](https://www.npmjs.org/package/@codemirror/state)
|
||||
|
||||
[ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#state) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/state/blob/main/CHANGELOG.md) ]
|
||||
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#state) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/state/blob/main/CHANGELOG.md) ]
|
||||
|
||||
This package implements the editor state data structures for the
|
||||
[CodeMirror](https://codemirror.net/6/) code editor.
|
||||
[CodeMirror](https://codemirror.net/) code editor.
|
||||
|
||||
The [project page](https://codemirror.net/6/) has more information, a
|
||||
number of [examples](https://codemirror.net/6/examples/) and the
|
||||
[documentation](https://codemirror.net/6/docs/).
|
||||
The [project page](https://codemirror.net/) has more information, a
|
||||
number of [examples](https://codemirror.net/examples/) and the
|
||||
[documentation](https://codemirror.net/docs/).
|
||||
|
||||
This code is released under an
|
||||
[MIT license](https://github.com/codemirror/state/tree/main/LICENSE).
|
||||
|
|
271
node_modules/@codemirror/state/dist/index.cjs
generated
vendored
271
node_modules/@codemirror/state/dist/index.cjs
generated
vendored
|
@ -31,10 +31,10 @@ class Text {
|
|||
*/
|
||||
replace(from, to, text) {
|
||||
let parts = [];
|
||||
this.decompose(0, from, parts, 2 /* To */);
|
||||
this.decompose(0, from, parts, 2 /* Open.To */);
|
||||
if (text.length)
|
||||
text.decompose(0, text.length, parts, 1 /* From */ | 2 /* To */);
|
||||
this.decompose(to, this.length, parts, 1 /* From */);
|
||||
text.decompose(0, text.length, parts, 1 /* Open.From */ | 2 /* Open.To */);
|
||||
this.decompose(to, this.length, parts, 1 /* Open.From */);
|
||||
return TextNode.from(parts, this.length - (to - from) + text.length);
|
||||
}
|
||||
/**
|
||||
|
@ -124,7 +124,7 @@ class Text {
|
|||
throw new RangeError("A document must have at least one line");
|
||||
if (text.length == 1 && !text[0])
|
||||
return Text.empty;
|
||||
return text.length <= 32 /* Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
||||
return text.length <= 32 /* Tree.Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
||||
}
|
||||
}
|
||||
// Leaves store an array of line strings. There are always line breaks
|
||||
|
@ -150,10 +150,10 @@ class TextLeaf extends Text {
|
|||
decompose(from, to, target, open) {
|
||||
let text = from <= 0 && to >= this.length ? this
|
||||
: new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from));
|
||||
if (open & 1 /* From */) {
|
||||
if (open & 1 /* Open.From */) {
|
||||
let prev = target.pop();
|
||||
let joined = appendText(text.text, prev.text.slice(), 0, text.length);
|
||||
if (joined.length <= 32 /* Branch */) {
|
||||
if (joined.length <= 32 /* Tree.Branch */) {
|
||||
target.push(new TextLeaf(joined, prev.length + text.length));
|
||||
}
|
||||
else {
|
||||
|
@ -170,7 +170,7 @@ class TextLeaf extends Text {
|
|||
return super.replace(from, to, text);
|
||||
let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to);
|
||||
let newLen = this.length + text.length - (to - from);
|
||||
if (lines.length <= 32 /* Branch */)
|
||||
if (lines.length <= 32 /* Tree.Branch */)
|
||||
return new TextLeaf(lines, newLen);
|
||||
return TextNode.from(TextLeaf.split(lines, []), newLen);
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ class TextLeaf extends Text {
|
|||
for (let line of text) {
|
||||
part.push(line);
|
||||
len += line.length + 1;
|
||||
if (part.length == 32 /* Branch */) {
|
||||
if (part.length == 32 /* Tree.Branch */) {
|
||||
target.push(new TextLeaf(part, len));
|
||||
part = [];
|
||||
len = -1;
|
||||
|
@ -233,7 +233,7 @@ class TextNode extends Text {
|
|||
for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) {
|
||||
let child = this.children[i], end = pos + child.length;
|
||||
if (from <= end && to >= pos) {
|
||||
let childOpen = open & ((pos <= from ? 1 /* From */ : 0) | (end >= to ? 2 /* To */ : 0));
|
||||
let childOpen = open & ((pos <= from ? 1 /* Open.From */ : 0) | (end >= to ? 2 /* Open.To */ : 0));
|
||||
if (pos >= from && end <= to && !childOpen)
|
||||
target.push(child);
|
||||
else
|
||||
|
@ -252,8 +252,8 @@ class TextNode extends Text {
|
|||
if (from >= pos && to <= end) {
|
||||
let updated = child.replace(from - pos, to - pos, text);
|
||||
let totalLines = this.lines - child.lines + updated.lines;
|
||||
if (updated.lines < (totalLines >> (5 /* BranchShift */ - 1)) &&
|
||||
updated.lines > (totalLines >> (5 /* BranchShift */ + 1))) {
|
||||
if (updated.lines < (totalLines >> (5 /* Tree.BranchShift */ - 1)) &&
|
||||
updated.lines > (totalLines >> (5 /* Tree.BranchShift */ + 1))) {
|
||||
let copy = this.children.slice();
|
||||
copy[i] = updated;
|
||||
return new TextNode(copy, this.length - (to - from) + text.length);
|
||||
|
@ -299,13 +299,13 @@ class TextNode extends Text {
|
|||
let lines = 0;
|
||||
for (let ch of children)
|
||||
lines += ch.lines;
|
||||
if (lines < 32 /* Branch */) {
|
||||
if (lines < 32 /* Tree.Branch */) {
|
||||
let flat = [];
|
||||
for (let ch of children)
|
||||
ch.flatten(flat);
|
||||
return new TextLeaf(flat, length);
|
||||
}
|
||||
let chunk = Math.max(32 /* Branch */, lines >> 5 /* BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
||||
let chunk = Math.max(32 /* Tree.Branch */, lines >> 5 /* Tree.BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
||||
let chunked = [], currentLines = 0, currentLen = -1, currentChunk = [];
|
||||
function add(child) {
|
||||
let last;
|
||||
|
@ -319,7 +319,7 @@ class TextNode extends Text {
|
|||
}
|
||||
else if (child instanceof TextLeaf && currentLines &&
|
||||
(last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf &&
|
||||
child.lines + last.lines <= 32 /* Branch */) {
|
||||
child.lines + last.lines <= 32 /* Tree.Branch */) {
|
||||
currentLines += child.lines;
|
||||
currentLen += child.length + 1;
|
||||
currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length);
|
||||
|
@ -1130,51 +1130,65 @@ function iterChanges(desc, f, individual) {
|
|||
}
|
||||
}
|
||||
function mapSet(setA, setB, before, mkSet = false) {
|
||||
// Produce a copy of setA that applies to the document after setB
|
||||
// has been applied (assuming both start at the same document).
|
||||
let sections = [], insert = mkSet ? [] : null;
|
||||
let a = new SectionIter(setA), b = new SectionIter(setB);
|
||||
for (let posA = 0, posB = 0;;) {
|
||||
if (a.ins == -1) {
|
||||
posA += a.len;
|
||||
a.next();
|
||||
// Iterate over both sets in parallel. inserted tracks, for changes
|
||||
// in A that have to be processed piece-by-piece, whether their
|
||||
// content has been inserted already, and refers to the section
|
||||
// index.
|
||||
for (let inserted = -1;;) {
|
||||
if (a.ins == -1 && b.ins == -1) {
|
||||
// Move across ranges skipped by both sets.
|
||||
let len = Math.min(a.len, b.len);
|
||||
addSection(sections, len, -1);
|
||||
a.forward(len);
|
||||
b.forward(len);
|
||||
}
|
||||
else if (b.ins == -1 && posB < posA) {
|
||||
let skip = Math.min(b.len, posA - posB);
|
||||
b.forward(skip);
|
||||
addSection(sections, skip, -1);
|
||||
posB += skip;
|
||||
}
|
||||
else if (b.ins >= 0 && (a.done || posB < posA || posB == posA && (b.len < a.len || b.len == a.len && !before))) {
|
||||
else if (b.ins >= 0 && (a.ins < 0 || inserted == a.i || a.off == 0 && (b.len < a.len || b.len == a.len && !before))) {
|
||||
// If there's a change in B that comes before the next change in
|
||||
// A (ordered by start pos, then len, then before flag), skip
|
||||
// that (and process any changes in A it covers).
|
||||
let len = b.len;
|
||||
addSection(sections, b.ins, -1);
|
||||
while (posA > posB && !a.done && posA + a.len < posB + b.len) {
|
||||
posA += a.len;
|
||||
a.next();
|
||||
while (len) {
|
||||
let piece = Math.min(a.len, len);
|
||||
if (a.ins >= 0 && inserted < a.i && a.len <= piece) {
|
||||
addSection(sections, 0, a.ins);
|
||||
if (insert)
|
||||
addInsert(insert, sections, a.text);
|
||||
inserted = a.i;
|
||||
}
|
||||
a.forward(piece);
|
||||
len -= piece;
|
||||
}
|
||||
posB += b.len;
|
||||
b.next();
|
||||
}
|
||||
else if (a.ins >= 0) {
|
||||
let len = 0, end = posA + a.len;
|
||||
for (;;) {
|
||||
if (b.ins >= 0 && posB > posA && posB + b.len < end) {
|
||||
len += b.ins;
|
||||
posB += b.len;
|
||||
b.next();
|
||||
// Process the part of a change in A up to the start of the next
|
||||
// non-deletion change in B (if overlapping).
|
||||
let len = 0, left = a.len;
|
||||
while (left) {
|
||||
if (b.ins == -1) {
|
||||
let piece = Math.min(left, b.len);
|
||||
len += piece;
|
||||
left -= piece;
|
||||
b.forward(piece);
|
||||
}
|
||||
else if (b.ins == -1 && posB < end) {
|
||||
let skip = Math.min(b.len, end - posB);
|
||||
len += skip;
|
||||
b.forward(skip);
|
||||
posB += skip;
|
||||
else if (b.ins == 0 && b.len < left) {
|
||||
left -= b.len;
|
||||
b.next();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
addSection(sections, len, a.ins);
|
||||
if (insert)
|
||||
addSection(sections, len, inserted < a.i ? a.ins : 0);
|
||||
if (insert && inserted < a.i)
|
||||
addInsert(insert, sections, a.text);
|
||||
posA = end;
|
||||
a.next();
|
||||
inserted = a.i;
|
||||
a.forward(a.len - left);
|
||||
}
|
||||
else if (a.done && b.done) {
|
||||
return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(sections);
|
||||
|
@ -1302,12 +1316,12 @@ class SelectionRange {
|
|||
The anchor of the range—the side that doesn't move when you
|
||||
extend it.
|
||||
*/
|
||||
get anchor() { return this.flags & 16 /* Inverted */ ? this.to : this.from; }
|
||||
get anchor() { return this.flags & 16 /* RangeFlag.Inverted */ ? this.to : this.from; }
|
||||
/**
|
||||
The head of the range, which is moved when the range is
|
||||
[extended](https://codemirror.net/6/docs/ref/#state.SelectionRange.extend).
|
||||
*/
|
||||
get head() { return this.flags & 16 /* Inverted */ ? this.from : this.to; }
|
||||
get head() { return this.flags & 16 /* RangeFlag.Inverted */ ? this.from : this.to; }
|
||||
/**
|
||||
True when `anchor` and `head` are at the same position.
|
||||
*/
|
||||
|
@ -1318,13 +1332,13 @@ class SelectionRange {
|
|||
the character before its position, 1 the character after, and 0
|
||||
means no association.
|
||||
*/
|
||||
get assoc() { return this.flags & 4 /* AssocBefore */ ? -1 : this.flags & 8 /* AssocAfter */ ? 1 : 0; }
|
||||
get assoc() { return this.flags & 4 /* RangeFlag.AssocBefore */ ? -1 : this.flags & 8 /* RangeFlag.AssocAfter */ ? 1 : 0; }
|
||||
/**
|
||||
The bidirectional text level associated with this cursor, if
|
||||
any.
|
||||
*/
|
||||
get bidiLevel() {
|
||||
let level = this.flags & 3 /* BidiLevelMask */;
|
||||
let level = this.flags & 3 /* RangeFlag.BidiLevelMask */;
|
||||
return level == 3 ? null : level;
|
||||
}
|
||||
/**
|
||||
|
@ -1334,8 +1348,8 @@ class SelectionRange {
|
|||
lines of different length.
|
||||
*/
|
||||
get goalColumn() {
|
||||
let value = this.flags >> 5 /* GoalColumnOffset */;
|
||||
return value == 33554431 /* NoGoalColumn */ ? undefined : value;
|
||||
let value = this.flags >> 5 /* RangeFlag.GoalColumnOffset */;
|
||||
return value == 33554431 /* RangeFlag.NoGoalColumn */ ? undefined : value;
|
||||
}
|
||||
/**
|
||||
Map this range through a change, producing a valid range in the
|
||||
|
@ -1495,17 +1509,18 @@ class EditorSelection {
|
|||
safely ignore the optional arguments in most situations.
|
||||
*/
|
||||
static cursor(pos, assoc = 0, bidiLevel, goalColumn) {
|
||||
return SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* AssocBefore */ : 8 /* AssocAfter */) |
|
||||
return SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* RangeFlag.AssocBefore */ : 8 /* RangeFlag.AssocAfter */) |
|
||||
(bidiLevel == null ? 3 : Math.min(2, bidiLevel)) |
|
||||
((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */));
|
||||
((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* RangeFlag.NoGoalColumn */) << 5 /* RangeFlag.GoalColumnOffset */));
|
||||
}
|
||||
/**
|
||||
Create a selection range.
|
||||
*/
|
||||
static range(anchor, head, goalColumn) {
|
||||
let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */;
|
||||
return head < anchor ? SelectionRange.create(head, anchor, 16 /* Inverted */ | goal | 8 /* AssocAfter */)
|
||||
: SelectionRange.create(anchor, head, goal | (head > anchor ? 4 /* AssocBefore */ : 0));
|
||||
static range(anchor, head, goalColumn, bidiLevel) {
|
||||
let flags = ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* RangeFlag.NoGoalColumn */) << 5 /* RangeFlag.GoalColumnOffset */) |
|
||||
(bidiLevel == null ? 3 : Math.min(2, bidiLevel));
|
||||
return head < anchor ? SelectionRange.create(head, anchor, 16 /* RangeFlag.Inverted */ | 8 /* RangeFlag.AssocAfter */ | flags)
|
||||
: SelectionRange.create(anchor, head, (head > anchor ? 4 /* RangeFlag.AssocBefore */ : 0) | flags);
|
||||
}
|
||||
/**
|
||||
@internal
|
||||
|
@ -1556,21 +1571,17 @@ class Facet {
|
|||
/**
|
||||
@internal
|
||||
*/
|
||||
compare, isStatic,
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
extensions) {
|
||||
compare, isStatic, enables) {
|
||||
this.combine = combine;
|
||||
this.compareInput = compareInput;
|
||||
this.compare = compare;
|
||||
this.isStatic = isStatic;
|
||||
this.extensions = extensions;
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
this.id = nextID++;
|
||||
this.default = combine([]);
|
||||
this.extensions = typeof enables == "function" ? enables(this) : enables;
|
||||
}
|
||||
/**
|
||||
Define a new facet.
|
||||
|
@ -1582,7 +1593,7 @@ class Facet {
|
|||
Returns an extension that adds the given value to this facet.
|
||||
*/
|
||||
of(value) {
|
||||
return new FacetProvider([], this, 0 /* Static */, value);
|
||||
return new FacetProvider([], this, 0 /* Provider.Static */, value);
|
||||
}
|
||||
/**
|
||||
Create an extension that computes a value for the facet from a
|
||||
|
@ -1596,7 +1607,7 @@ class Facet {
|
|||
compute(deps, get) {
|
||||
if (this.isStatic)
|
||||
throw new Error("Can't compute a static facet");
|
||||
return new FacetProvider(deps, this, 1 /* Single */, get);
|
||||
return new FacetProvider(deps, this, 1 /* Provider.Single */, get);
|
||||
}
|
||||
/**
|
||||
Create an extension that computes zero or more values for this
|
||||
|
@ -1605,7 +1616,7 @@ class Facet {
|
|||
computeN(deps, get) {
|
||||
if (this.isStatic)
|
||||
throw new Error("Can't compute a static facet");
|
||||
return new FacetProvider(deps, this, 2 /* Multi */, get);
|
||||
return new FacetProvider(deps, this, 2 /* Provider.Multi */, get);
|
||||
}
|
||||
from(field, get) {
|
||||
if (!get)
|
||||
|
@ -1628,7 +1639,7 @@ class FacetProvider {
|
|||
var _a;
|
||||
let getter = this.value;
|
||||
let compare = this.facet.compareInput;
|
||||
let id = this.id, idx = addresses[id] >> 1, multi = this.type == 2 /* Multi */;
|
||||
let id = this.id, idx = addresses[id] >> 1, multi = this.type == 2 /* Provider.Multi */;
|
||||
let depDoc = false, depSel = false, depAddrs = [];
|
||||
for (let dep of this.dependencies) {
|
||||
if (dep == "doc")
|
||||
|
@ -1641,33 +1652,35 @@ class FacetProvider {
|
|||
return {
|
||||
create(state) {
|
||||
state.values[idx] = getter(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
update(state, tr) {
|
||||
if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || ensureAll(state, depAddrs)) {
|
||||
let newVal = getter(state);
|
||||
if (multi ? !compareArray(newVal, state.values[idx], compare) : !compare(newVal, state.values[idx])) {
|
||||
state.values[idx] = newVal;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
reconfigure: (state, oldState) => {
|
||||
let newVal = getter(state);
|
||||
let oldAddr = oldState.config.address[id];
|
||||
let newVal, oldAddr = oldState.config.address[id];
|
||||
if (oldAddr != null) {
|
||||
let oldVal = getAddr(oldState, oldAddr);
|
||||
if (this.dependencies.every(dep => {
|
||||
return dep instanceof Facet ? oldState.facet(dep) === state.facet(dep) :
|
||||
dep instanceof StateField ? oldState.field(dep, false) == state.field(dep, false) : true;
|
||||
}) || (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))) {
|
||||
}) || (multi ? compareArray(newVal = getter(state), oldVal, compare) : compare(newVal = getter(state), oldVal))) {
|
||||
state.values[idx] = oldVal;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
newVal = getter(state);
|
||||
}
|
||||
state.values[idx] = newVal;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1683,7 +1696,7 @@ function compareArray(a, b, compare) {
|
|||
function ensureAll(state, addrs) {
|
||||
let changed = false;
|
||||
for (let addr of addrs)
|
||||
if (ensureAddr(state, addr) & 1 /* Changed */)
|
||||
if (ensureAddr(state, addr) & 1 /* SlotStatus.Changed */)
|
||||
changed = true;
|
||||
return changed;
|
||||
}
|
||||
|
@ -1696,7 +1709,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
let values = [];
|
||||
for (let i = 0; i < providerAddrs.length; i++) {
|
||||
let value = getAddr(state, providerAddrs[i]);
|
||||
if (providerTypes[i] == 2 /* Multi */)
|
||||
if (providerTypes[i] == 2 /* Provider.Multi */)
|
||||
for (let val of value)
|
||||
values.push(val);
|
||||
else
|
||||
|
@ -1709,7 +1722,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
for (let addr of providerAddrs)
|
||||
ensureAddr(state, addr);
|
||||
state.values[idx] = get(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
update(state, tr) {
|
||||
if (!ensureAll(state, dynamic))
|
||||
|
@ -1718,7 +1731,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
if (facet.compare(value, state.values[idx]))
|
||||
return 0;
|
||||
state.values[idx] = value;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
reconfigure(state, oldState) {
|
||||
let depChanged = ensureAll(state, providerAddrs);
|
||||
|
@ -1733,7 +1746,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
return 0;
|
||||
}
|
||||
state.values[idx] = value;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1783,7 +1796,7 @@ class StateField {
|
|||
return {
|
||||
create: (state) => {
|
||||
state.values[idx] = this.create(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
update: (state, tr) => {
|
||||
let oldVal = state.values[idx];
|
||||
|
@ -1791,7 +1804,7 @@ class StateField {
|
|||
if (this.compareF(oldVal, value))
|
||||
return 0;
|
||||
state.values[idx] = value;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
reconfigure: (state, oldState) => {
|
||||
if (oldState.config.address[this.id] != null) {
|
||||
|
@ -1799,7 +1812,7 @@ class StateField {
|
|||
return 0;
|
||||
}
|
||||
state.values[idx] = this.create(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1908,7 +1921,7 @@ class Configuration {
|
|||
this.facets = facets;
|
||||
this.statusTemplate = [];
|
||||
while (this.statusTemplate.length < dynamicSlots.length)
|
||||
this.statusTemplate.push(0 /* Unresolved */);
|
||||
this.statusTemplate.push(0 /* SlotStatus.Unresolved */);
|
||||
}
|
||||
staticFacet(facet) {
|
||||
let addr = this.address[facet.id];
|
||||
|
@ -1935,7 +1948,7 @@ class Configuration {
|
|||
for (let id in facets) {
|
||||
let providers = facets[id], facet = providers[0].facet;
|
||||
let oldProviders = oldFacets && oldFacets[id] || [];
|
||||
if (providers.every(p => p.type == 0 /* Static */)) {
|
||||
if (providers.every(p => p.type == 0 /* Provider.Static */)) {
|
||||
address[facet.id] = (staticValues.length << 1) | 1;
|
||||
if (sameArray(oldProviders, providers)) {
|
||||
staticValues.push(oldState.facet(facet));
|
||||
|
@ -1947,7 +1960,7 @@ class Configuration {
|
|||
}
|
||||
else {
|
||||
for (let p of providers) {
|
||||
if (p.type == 0 /* Static */) {
|
||||
if (p.type == 0 /* Provider.Static */) {
|
||||
address[p.id] = (staticValues.length << 1) | 1;
|
||||
staticValues.push(p.value);
|
||||
}
|
||||
|
@ -2001,7 +2014,7 @@ function flatten(extension, compartments, newCompartments) {
|
|||
else if (ext instanceof FacetProvider) {
|
||||
result[prec].push(ext);
|
||||
if (ext.facet.extensions)
|
||||
inner(ext.facet.extensions, prec);
|
||||
inner(ext.facet.extensions, Prec_.default);
|
||||
}
|
||||
else {
|
||||
let content = ext.extension;
|
||||
|
@ -2015,16 +2028,16 @@ function flatten(extension, compartments, newCompartments) {
|
|||
}
|
||||
function ensureAddr(state, addr) {
|
||||
if (addr & 1)
|
||||
return 2 /* Computed */;
|
||||
return 2 /* SlotStatus.Computed */;
|
||||
let idx = addr >> 1;
|
||||
let status = state.status[idx];
|
||||
if (status == 4 /* Computing */)
|
||||
if (status == 4 /* SlotStatus.Computing */)
|
||||
throw new Error("Cyclic dependency between fields and/or facets");
|
||||
if (status & 2 /* Computed */)
|
||||
if (status & 2 /* SlotStatus.Computed */)
|
||||
return status;
|
||||
state.status[idx] = 4 /* Computing */;
|
||||
state.status[idx] = 4 /* SlotStatus.Computing */;
|
||||
let changed = state.computeSlot(state, state.config.dynamicSlots[idx]);
|
||||
return state.status[idx] = 2 /* Computed */ | changed;
|
||||
return state.status[idx] = 2 /* SlotStatus.Computed */ | changed;
|
||||
}
|
||||
function getAddr(state, addr) {
|
||||
return addr & 1 ? state.config.staticValues[addr >> 1] : state.values[addr >> 1];
|
||||
|
@ -2439,7 +2452,7 @@ function filterTransaction(tr) {
|
|||
else {
|
||||
let filtered = tr.changes.filter(result);
|
||||
changes = filtered.changes;
|
||||
back = filtered.filtered.invertedDesc;
|
||||
back = filtered.filtered.mapDesc(filtered.changes).invertedDesc;
|
||||
}
|
||||
tr = Transaction.create(state, changes, tr.selection && tr.selection.map(back), StateEffect.mapEffects(tr.effects, back), tr.annotations, tr.scrollIntoView);
|
||||
}
|
||||
|
@ -2461,7 +2474,7 @@ function extendTransaction(tr) {
|
|||
for (let i = extenders.length - 1; i >= 0; i--) {
|
||||
let extension = extenders[i](tr);
|
||||
if (extension && Object.keys(extension).length)
|
||||
spec = mergeTransaction(tr, resolveTransactionInner(state, extension, tr.changes.newLength), true);
|
||||
spec = mergeTransaction(spec, resolveTransactionInner(state, extension, tr.changes.newLength), true);
|
||||
}
|
||||
return spec == tr ? tr : Transaction.create(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.scrollIntoView);
|
||||
}
|
||||
|
@ -2712,7 +2725,7 @@ class EditorState {
|
|||
if (fields)
|
||||
for (let prop in fields) {
|
||||
let value = fields[prop];
|
||||
if (value instanceof StateField)
|
||||
if (value instanceof StateField && this.config.address[value.id] != null)
|
||||
result[prop] = value.spec.toJSON(this.field(fields[prop]), this);
|
||||
}
|
||||
return result;
|
||||
|
@ -2729,8 +2742,10 @@ class EditorState {
|
|||
let fieldInit = [];
|
||||
if (fields)
|
||||
for (let prop in fields) {
|
||||
let field = fields[prop], value = json[prop];
|
||||
fieldInit.push(field.init(state => field.spec.fromJSON(value, state)));
|
||||
if (Object.prototype.hasOwnProperty.call(json, prop)) {
|
||||
let field = fields[prop], value = json[prop];
|
||||
fieldInit.push(field.init(state => field.spec.fromJSON(value, state)));
|
||||
}
|
||||
}
|
||||
return EditorState.create({
|
||||
doc: json.doc,
|
||||
|
@ -2791,13 +2806,25 @@ class EditorState {
|
|||
if (i == "$")
|
||||
return "$";
|
||||
let n = +(i || 1);
|
||||
return n > insert.length ? m : insert[n - 1];
|
||||
return !n || n > insert.length ? m : insert[n - 1];
|
||||
});
|
||||
return phrase;
|
||||
}
|
||||
/**
|
||||
Find the values for a given language data field, provided by the
|
||||
the [`languageData`](https://codemirror.net/6/docs/ref/#state.EditorState^languageData) facet.
|
||||
|
||||
Examples of language data fields are...
|
||||
|
||||
- [`"commentTokens"`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) for specifying
|
||||
comment syntax.
|
||||
- [`"autocomplete"`](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion^config.override)
|
||||
for providing language-specific completion sources.
|
||||
- [`"wordChars"`](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer) for adding
|
||||
characters that should be considered part of words in this
|
||||
language.
|
||||
- [`"closeBrackets"`](https://codemirror.net/6/docs/ref/#autocomplete.CloseBracketConfig) controls
|
||||
bracket closing behavior.
|
||||
*/
|
||||
languageDataAt(name, pos, side = -1) {
|
||||
let values = [];
|
||||
|
@ -3069,7 +3096,7 @@ class Chunk {
|
|||
}
|
||||
}
|
||||
between(offset, from, to, f) {
|
||||
for (let i = this.findIndex(from, -1000000000 /* Far */, true), e = this.findIndex(to, 1000000000 /* Far */, false, i); i < e; i++)
|
||||
for (let i = this.findIndex(from, -1000000000 /* C.Far */, true), e = this.findIndex(to, 1000000000 /* C.Far */, false, i); i < e; i++)
|
||||
if (f(this.from[i] + offset, this.to[i] + offset, this.value[i]) === false)
|
||||
return false;
|
||||
}
|
||||
|
@ -3302,7 +3329,7 @@ class RangeSet {
|
|||
*/
|
||||
static eq(oldSets, newSets, from = 0, to) {
|
||||
if (to == null)
|
||||
to = 1000000000 /* Far */;
|
||||
to = 1000000000 /* C.Far */ - 1;
|
||||
let a = oldSets.filter(set => !set.isEmpty && newSets.indexOf(set) < 0);
|
||||
let b = newSets.filter(set => !set.isEmpty && oldSets.indexOf(set) < 0);
|
||||
if (a.length != b.length)
|
||||
|
@ -3336,23 +3363,24 @@ class RangeSet {
|
|||
*/
|
||||
minPointSize = -1) {
|
||||
let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from;
|
||||
let open = cursor.openStart;
|
||||
let openRanges = cursor.openStart;
|
||||
for (;;) {
|
||||
let curTo = Math.min(cursor.to, to);
|
||||
if (cursor.point) {
|
||||
iterator.point(pos, curTo, cursor.point, cursor.activeForPoint(cursor.to), open, cursor.pointRank);
|
||||
open = cursor.openEnd(curTo) + (cursor.to > curTo ? 1 : 0);
|
||||
let active = cursor.activeForPoint(cursor.to);
|
||||
let openCount = cursor.pointFrom < from ? active.length + 1 : Math.min(active.length, openRanges);
|
||||
iterator.point(pos, curTo, cursor.point, active, openCount, cursor.pointRank);
|
||||
openRanges = Math.min(cursor.openEnd(curTo), active.length);
|
||||
}
|
||||
else if (curTo > pos) {
|
||||
iterator.span(pos, curTo, cursor.active, open);
|
||||
open = cursor.openEnd(curTo);
|
||||
iterator.span(pos, curTo, cursor.active, openRanges);
|
||||
openRanges = cursor.openEnd(curTo);
|
||||
}
|
||||
if (cursor.to > to)
|
||||
break;
|
||||
return openRanges + (cursor.point && cursor.to > to ? 1 : 0);
|
||||
pos = cursor.to;
|
||||
cursor.next();
|
||||
}
|
||||
return open;
|
||||
}
|
||||
/**
|
||||
Create a range set for the given range or array of ranges. By
|
||||
|
@ -3397,8 +3425,8 @@ class RangeSetBuilder {
|
|||
this.chunkPos = [];
|
||||
this.chunkStart = -1;
|
||||
this.last = null;
|
||||
this.lastFrom = -1000000000 /* Far */;
|
||||
this.lastTo = -1000000000 /* Far */;
|
||||
this.lastFrom = -1000000000 /* C.Far */;
|
||||
this.lastTo = -1000000000 /* C.Far */;
|
||||
this.from = [];
|
||||
this.to = [];
|
||||
this.value = [];
|
||||
|
@ -3435,7 +3463,7 @@ class RangeSetBuilder {
|
|||
throw new Error("Ranges must be added sorted by `from` position and `startSide`");
|
||||
if (diff < 0)
|
||||
return false;
|
||||
if (this.from.length == 250 /* ChunkSize */)
|
||||
if (this.from.length == 250 /* C.ChunkSize */)
|
||||
this.finishChunk(true);
|
||||
if (this.chunkStart < 0)
|
||||
this.chunkStart = from;
|
||||
|
@ -3509,7 +3537,7 @@ class LayerCursor {
|
|||
}
|
||||
get startSide() { return this.value ? this.value.startSide : 0; }
|
||||
get endSide() { return this.value ? this.value.endSide : 0; }
|
||||
goto(pos, side = -1000000000 /* Far */) {
|
||||
goto(pos, side = -1000000000 /* C.Far */) {
|
||||
this.chunkIndex = this.rangeIndex = 0;
|
||||
this.gotoInner(pos, side, false);
|
||||
return this;
|
||||
|
@ -3538,7 +3566,7 @@ class LayerCursor {
|
|||
next() {
|
||||
for (;;) {
|
||||
if (this.chunkIndex == this.layer.chunk.length) {
|
||||
this.from = this.to = 1000000000 /* Far */;
|
||||
this.from = this.to = 1000000000 /* C.Far */;
|
||||
this.value = null;
|
||||
break;
|
||||
}
|
||||
|
@ -3592,7 +3620,7 @@ class HeapCursor {
|
|||
return heap.length == 1 ? heap[0] : new HeapCursor(heap);
|
||||
}
|
||||
get startSide() { return this.value ? this.value.startSide : 0; }
|
||||
goto(pos, side = -1000000000 /* Far */) {
|
||||
goto(pos, side = -1000000000 /* C.Far */) {
|
||||
for (let cur of this.heap)
|
||||
cur.goto(pos, side);
|
||||
for (let i = this.heap.length >> 1; i >= 0; i--)
|
||||
|
@ -3610,7 +3638,7 @@ class HeapCursor {
|
|||
}
|
||||
next() {
|
||||
if (this.heap.length == 0) {
|
||||
this.from = this.to = 1000000000 /* Far */;
|
||||
this.from = this.to = 1000000000 /* C.Far */;
|
||||
this.value = null;
|
||||
this.rank = -1;
|
||||
}
|
||||
|
@ -3654,12 +3682,14 @@ class SpanCursor {
|
|||
this.point = null;
|
||||
this.pointFrom = 0;
|
||||
this.pointRank = 0;
|
||||
this.to = -1000000000 /* Far */;
|
||||
this.to = -1000000000 /* C.Far */;
|
||||
this.endSide = 0;
|
||||
// The amount of open active ranges at the start of the iterator.
|
||||
// Not including points.
|
||||
this.openStart = -1;
|
||||
this.cursor = HeapCursor.from(sets, skip, minPoint);
|
||||
}
|
||||
goto(pos, side = -1000000000 /* Far */) {
|
||||
goto(pos, side = -1000000000 /* C.Far */) {
|
||||
this.cursor.goto(pos, side);
|
||||
this.active.length = this.activeTo.length = this.activeRank.length = 0;
|
||||
this.minActive = -1;
|
||||
|
@ -3696,7 +3726,7 @@ class SpanCursor {
|
|||
next() {
|
||||
let from = this.to, wasPoint = this.point;
|
||||
this.point = null;
|
||||
let trackOpen = this.openStart < 0 ? [] : null, trackExtra = 0;
|
||||
let trackOpen = this.openStart < 0 ? [] : null;
|
||||
for (;;) {
|
||||
let a = this.minActive;
|
||||
if (a > -1 && (this.activeTo[a] - this.cursor.from || this.active[a].endSide - this.cursor.startSide) < 0) {
|
||||
|
@ -3710,7 +3740,7 @@ class SpanCursor {
|
|||
remove(trackOpen, a);
|
||||
}
|
||||
else if (!this.cursor.value) {
|
||||
this.to = this.endSide = 1000000000 /* Far */;
|
||||
this.to = this.endSide = 1000000000 /* C.Far */;
|
||||
break;
|
||||
}
|
||||
else if (this.cursor.from > from) {
|
||||
|
@ -3734,8 +3764,6 @@ class SpanCursor {
|
|||
this.pointRank = this.cursor.rank;
|
||||
this.to = this.cursor.to;
|
||||
this.endSide = nextVal.endSide;
|
||||
if (this.cursor.from < from)
|
||||
trackExtra = 1;
|
||||
this.cursor.next();
|
||||
this.forward(this.to, this.endSide);
|
||||
break;
|
||||
|
@ -3743,10 +3771,9 @@ class SpanCursor {
|
|||
}
|
||||
}
|
||||
if (trackOpen) {
|
||||
let openStart = 0;
|
||||
while (openStart < trackOpen.length && trackOpen[openStart] < from)
|
||||
openStart++;
|
||||
this.openStart = openStart + trackExtra;
|
||||
this.openStart = 0;
|
||||
for (let i = trackOpen.length - 1; i >= 0 && trackOpen[i] < from; i--)
|
||||
this.openStart++;
|
||||
}
|
||||
}
|
||||
activeForPoint(to) {
|
||||
|
@ -3813,7 +3840,7 @@ function insert(array, index, value) {
|
|||
array[index] = value;
|
||||
}
|
||||
function findMinIndex(value, array) {
|
||||
let found = -1, foundPos = 1000000000 /* Far */;
|
||||
let found = -1, foundPos = 1000000000 /* C.Far */;
|
||||
for (let i = 0; i < array.length; i++)
|
||||
if ((array[i] - foundPos || value[i].endSide - value[found].endSide) < 0) {
|
||||
found = i;
|
||||
|
|
25
node_modules/@codemirror/state/dist/index.d.ts
generated
vendored
25
node_modules/@codemirror/state/dist/index.d.ts
generated
vendored
|
@ -476,7 +476,7 @@ declare class EditorSelection {
|
|||
/**
|
||||
Create a selection range.
|
||||
*/
|
||||
static range(anchor: number, head: number, goalColumn?: number): SelectionRange;
|
||||
static range(anchor: number, head: number, goalColumn?: number, bidiLevel?: number): SelectionRange;
|
||||
}
|
||||
|
||||
declare type FacetConfig<Input, Output> = {
|
||||
|
@ -505,13 +505,14 @@ declare type FacetConfig<Input, Output> = {
|
|||
*/
|
||||
static?: boolean;
|
||||
/**
|
||||
If given, these extension(s) will be added to any state where
|
||||
this facet is provided. (Note that, while a facet's default
|
||||
value can be read from a state even if the facet wasn't present
|
||||
in the state at all, these extensions won't be added in that
|
||||
If given, these extension(s) (or the result of calling the given
|
||||
function with the facet) will be added to any state where this
|
||||
facet is provided. (Note that, while a facet's default value can
|
||||
be read from a state even if the facet wasn't present in the
|
||||
state at all, these extensions won't be added in that
|
||||
situation.)
|
||||
*/
|
||||
enables?: Extension;
|
||||
enables?: Extension | ((self: Facet<Input, Output>) => Extension);
|
||||
};
|
||||
/**
|
||||
A facet is a labeled value that is associated with an editor
|
||||
|
@ -1227,6 +1228,18 @@ declare class EditorState {
|
|||
/**
|
||||
Find the values for a given language data field, provided by the
|
||||
the [`languageData`](https://codemirror.net/6/docs/ref/#state.EditorState^languageData) facet.
|
||||
|
||||
Examples of language data fields are...
|
||||
|
||||
- [`"commentTokens"`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) for specifying
|
||||
comment syntax.
|
||||
- [`"autocomplete"`](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion^config.override)
|
||||
for providing language-specific completion sources.
|
||||
- [`"wordChars"`](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer) for adding
|
||||
characters that should be considered part of words in this
|
||||
language.
|
||||
- [`"closeBrackets"`](https://codemirror.net/6/docs/ref/#autocomplete.CloseBracketConfig) controls
|
||||
bracket closing behavior.
|
||||
*/
|
||||
languageDataAt<T>(name: string, pos: number, side?: -1 | 0 | 1): readonly T[];
|
||||
/**
|
||||
|
|
271
node_modules/@codemirror/state/dist/index.js
generated
vendored
271
node_modules/@codemirror/state/dist/index.js
generated
vendored
|
@ -27,10 +27,10 @@ class Text {
|
|||
*/
|
||||
replace(from, to, text) {
|
||||
let parts = [];
|
||||
this.decompose(0, from, parts, 2 /* To */);
|
||||
this.decompose(0, from, parts, 2 /* Open.To */);
|
||||
if (text.length)
|
||||
text.decompose(0, text.length, parts, 1 /* From */ | 2 /* To */);
|
||||
this.decompose(to, this.length, parts, 1 /* From */);
|
||||
text.decompose(0, text.length, parts, 1 /* Open.From */ | 2 /* Open.To */);
|
||||
this.decompose(to, this.length, parts, 1 /* Open.From */);
|
||||
return TextNode.from(parts, this.length - (to - from) + text.length);
|
||||
}
|
||||
/**
|
||||
|
@ -120,7 +120,7 @@ class Text {
|
|||
throw new RangeError("A document must have at least one line");
|
||||
if (text.length == 1 && !text[0])
|
||||
return Text.empty;
|
||||
return text.length <= 32 /* Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
||||
return text.length <= 32 /* Tree.Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
||||
}
|
||||
}
|
||||
// Leaves store an array of line strings. There are always line breaks
|
||||
|
@ -146,10 +146,10 @@ class TextLeaf extends Text {
|
|||
decompose(from, to, target, open) {
|
||||
let text = from <= 0 && to >= this.length ? this
|
||||
: new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from));
|
||||
if (open & 1 /* From */) {
|
||||
if (open & 1 /* Open.From */) {
|
||||
let prev = target.pop();
|
||||
let joined = appendText(text.text, prev.text.slice(), 0, text.length);
|
||||
if (joined.length <= 32 /* Branch */) {
|
||||
if (joined.length <= 32 /* Tree.Branch */) {
|
||||
target.push(new TextLeaf(joined, prev.length + text.length));
|
||||
}
|
||||
else {
|
||||
|
@ -166,7 +166,7 @@ class TextLeaf extends Text {
|
|||
return super.replace(from, to, text);
|
||||
let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to);
|
||||
let newLen = this.length + text.length - (to - from);
|
||||
if (lines.length <= 32 /* Branch */)
|
||||
if (lines.length <= 32 /* Tree.Branch */)
|
||||
return new TextLeaf(lines, newLen);
|
||||
return TextNode.from(TextLeaf.split(lines, []), newLen);
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ class TextLeaf extends Text {
|
|||
for (let line of text) {
|
||||
part.push(line);
|
||||
len += line.length + 1;
|
||||
if (part.length == 32 /* Branch */) {
|
||||
if (part.length == 32 /* Tree.Branch */) {
|
||||
target.push(new TextLeaf(part, len));
|
||||
part = [];
|
||||
len = -1;
|
||||
|
@ -229,7 +229,7 @@ class TextNode extends Text {
|
|||
for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) {
|
||||
let child = this.children[i], end = pos + child.length;
|
||||
if (from <= end && to >= pos) {
|
||||
let childOpen = open & ((pos <= from ? 1 /* From */ : 0) | (end >= to ? 2 /* To */ : 0));
|
||||
let childOpen = open & ((pos <= from ? 1 /* Open.From */ : 0) | (end >= to ? 2 /* Open.To */ : 0));
|
||||
if (pos >= from && end <= to && !childOpen)
|
||||
target.push(child);
|
||||
else
|
||||
|
@ -248,8 +248,8 @@ class TextNode extends Text {
|
|||
if (from >= pos && to <= end) {
|
||||
let updated = child.replace(from - pos, to - pos, text);
|
||||
let totalLines = this.lines - child.lines + updated.lines;
|
||||
if (updated.lines < (totalLines >> (5 /* BranchShift */ - 1)) &&
|
||||
updated.lines > (totalLines >> (5 /* BranchShift */ + 1))) {
|
||||
if (updated.lines < (totalLines >> (5 /* Tree.BranchShift */ - 1)) &&
|
||||
updated.lines > (totalLines >> (5 /* Tree.BranchShift */ + 1))) {
|
||||
let copy = this.children.slice();
|
||||
copy[i] = updated;
|
||||
return new TextNode(copy, this.length - (to - from) + text.length);
|
||||
|
@ -295,13 +295,13 @@ class TextNode extends Text {
|
|||
let lines = 0;
|
||||
for (let ch of children)
|
||||
lines += ch.lines;
|
||||
if (lines < 32 /* Branch */) {
|
||||
if (lines < 32 /* Tree.Branch */) {
|
||||
let flat = [];
|
||||
for (let ch of children)
|
||||
ch.flatten(flat);
|
||||
return new TextLeaf(flat, length);
|
||||
}
|
||||
let chunk = Math.max(32 /* Branch */, lines >> 5 /* BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
||||
let chunk = Math.max(32 /* Tree.Branch */, lines >> 5 /* Tree.BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
||||
let chunked = [], currentLines = 0, currentLen = -1, currentChunk = [];
|
||||
function add(child) {
|
||||
let last;
|
||||
|
@ -315,7 +315,7 @@ class TextNode extends Text {
|
|||
}
|
||||
else if (child instanceof TextLeaf && currentLines &&
|
||||
(last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf &&
|
||||
child.lines + last.lines <= 32 /* Branch */) {
|
||||
child.lines + last.lines <= 32 /* Tree.Branch */) {
|
||||
currentLines += child.lines;
|
||||
currentLen += child.length + 1;
|
||||
currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length);
|
||||
|
@ -1125,51 +1125,65 @@ function iterChanges(desc, f, individual) {
|
|||
}
|
||||
}
|
||||
function mapSet(setA, setB, before, mkSet = false) {
|
||||
// Produce a copy of setA that applies to the document after setB
|
||||
// has been applied (assuming both start at the same document).
|
||||
let sections = [], insert = mkSet ? [] : null;
|
||||
let a = new SectionIter(setA), b = new SectionIter(setB);
|
||||
for (let posA = 0, posB = 0;;) {
|
||||
if (a.ins == -1) {
|
||||
posA += a.len;
|
||||
a.next();
|
||||
// Iterate over both sets in parallel. inserted tracks, for changes
|
||||
// in A that have to be processed piece-by-piece, whether their
|
||||
// content has been inserted already, and refers to the section
|
||||
// index.
|
||||
for (let inserted = -1;;) {
|
||||
if (a.ins == -1 && b.ins == -1) {
|
||||
// Move across ranges skipped by both sets.
|
||||
let len = Math.min(a.len, b.len);
|
||||
addSection(sections, len, -1);
|
||||
a.forward(len);
|
||||
b.forward(len);
|
||||
}
|
||||
else if (b.ins == -1 && posB < posA) {
|
||||
let skip = Math.min(b.len, posA - posB);
|
||||
b.forward(skip);
|
||||
addSection(sections, skip, -1);
|
||||
posB += skip;
|
||||
}
|
||||
else if (b.ins >= 0 && (a.done || posB < posA || posB == posA && (b.len < a.len || b.len == a.len && !before))) {
|
||||
else if (b.ins >= 0 && (a.ins < 0 || inserted == a.i || a.off == 0 && (b.len < a.len || b.len == a.len && !before))) {
|
||||
// If there's a change in B that comes before the next change in
|
||||
// A (ordered by start pos, then len, then before flag), skip
|
||||
// that (and process any changes in A it covers).
|
||||
let len = b.len;
|
||||
addSection(sections, b.ins, -1);
|
||||
while (posA > posB && !a.done && posA + a.len < posB + b.len) {
|
||||
posA += a.len;
|
||||
a.next();
|
||||
while (len) {
|
||||
let piece = Math.min(a.len, len);
|
||||
if (a.ins >= 0 && inserted < a.i && a.len <= piece) {
|
||||
addSection(sections, 0, a.ins);
|
||||
if (insert)
|
||||
addInsert(insert, sections, a.text);
|
||||
inserted = a.i;
|
||||
}
|
||||
a.forward(piece);
|
||||
len -= piece;
|
||||
}
|
||||
posB += b.len;
|
||||
b.next();
|
||||
}
|
||||
else if (a.ins >= 0) {
|
||||
let len = 0, end = posA + a.len;
|
||||
for (;;) {
|
||||
if (b.ins >= 0 && posB > posA && posB + b.len < end) {
|
||||
len += b.ins;
|
||||
posB += b.len;
|
||||
b.next();
|
||||
// Process the part of a change in A up to the start of the next
|
||||
// non-deletion change in B (if overlapping).
|
||||
let len = 0, left = a.len;
|
||||
while (left) {
|
||||
if (b.ins == -1) {
|
||||
let piece = Math.min(left, b.len);
|
||||
len += piece;
|
||||
left -= piece;
|
||||
b.forward(piece);
|
||||
}
|
||||
else if (b.ins == -1 && posB < end) {
|
||||
let skip = Math.min(b.len, end - posB);
|
||||
len += skip;
|
||||
b.forward(skip);
|
||||
posB += skip;
|
||||
else if (b.ins == 0 && b.len < left) {
|
||||
left -= b.len;
|
||||
b.next();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
addSection(sections, len, a.ins);
|
||||
if (insert)
|
||||
addSection(sections, len, inserted < a.i ? a.ins : 0);
|
||||
if (insert && inserted < a.i)
|
||||
addInsert(insert, sections, a.text);
|
||||
posA = end;
|
||||
a.next();
|
||||
inserted = a.i;
|
||||
a.forward(a.len - left);
|
||||
}
|
||||
else if (a.done && b.done) {
|
||||
return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(sections);
|
||||
|
@ -1297,12 +1311,12 @@ class SelectionRange {
|
|||
The anchor of the range—the side that doesn't move when you
|
||||
extend it.
|
||||
*/
|
||||
get anchor() { return this.flags & 16 /* Inverted */ ? this.to : this.from; }
|
||||
get anchor() { return this.flags & 16 /* RangeFlag.Inverted */ ? this.to : this.from; }
|
||||
/**
|
||||
The head of the range, which is moved when the range is
|
||||
[extended](https://codemirror.net/6/docs/ref/#state.SelectionRange.extend).
|
||||
*/
|
||||
get head() { return this.flags & 16 /* Inverted */ ? this.from : this.to; }
|
||||
get head() { return this.flags & 16 /* RangeFlag.Inverted */ ? this.from : this.to; }
|
||||
/**
|
||||
True when `anchor` and `head` are at the same position.
|
||||
*/
|
||||
|
@ -1313,13 +1327,13 @@ class SelectionRange {
|
|||
the character before its position, 1 the character after, and 0
|
||||
means no association.
|
||||
*/
|
||||
get assoc() { return this.flags & 4 /* AssocBefore */ ? -1 : this.flags & 8 /* AssocAfter */ ? 1 : 0; }
|
||||
get assoc() { return this.flags & 4 /* RangeFlag.AssocBefore */ ? -1 : this.flags & 8 /* RangeFlag.AssocAfter */ ? 1 : 0; }
|
||||
/**
|
||||
The bidirectional text level associated with this cursor, if
|
||||
any.
|
||||
*/
|
||||
get bidiLevel() {
|
||||
let level = this.flags & 3 /* BidiLevelMask */;
|
||||
let level = this.flags & 3 /* RangeFlag.BidiLevelMask */;
|
||||
return level == 3 ? null : level;
|
||||
}
|
||||
/**
|
||||
|
@ -1329,8 +1343,8 @@ class SelectionRange {
|
|||
lines of different length.
|
||||
*/
|
||||
get goalColumn() {
|
||||
let value = this.flags >> 5 /* GoalColumnOffset */;
|
||||
return value == 33554431 /* NoGoalColumn */ ? undefined : value;
|
||||
let value = this.flags >> 5 /* RangeFlag.GoalColumnOffset */;
|
||||
return value == 33554431 /* RangeFlag.NoGoalColumn */ ? undefined : value;
|
||||
}
|
||||
/**
|
||||
Map this range through a change, producing a valid range in the
|
||||
|
@ -1490,17 +1504,18 @@ class EditorSelection {
|
|||
safely ignore the optional arguments in most situations.
|
||||
*/
|
||||
static cursor(pos, assoc = 0, bidiLevel, goalColumn) {
|
||||
return SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* AssocBefore */ : 8 /* AssocAfter */) |
|
||||
return SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* RangeFlag.AssocBefore */ : 8 /* RangeFlag.AssocAfter */) |
|
||||
(bidiLevel == null ? 3 : Math.min(2, bidiLevel)) |
|
||||
((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */));
|
||||
((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* RangeFlag.NoGoalColumn */) << 5 /* RangeFlag.GoalColumnOffset */));
|
||||
}
|
||||
/**
|
||||
Create a selection range.
|
||||
*/
|
||||
static range(anchor, head, goalColumn) {
|
||||
let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */;
|
||||
return head < anchor ? SelectionRange.create(head, anchor, 16 /* Inverted */ | goal | 8 /* AssocAfter */)
|
||||
: SelectionRange.create(anchor, head, goal | (head > anchor ? 4 /* AssocBefore */ : 0));
|
||||
static range(anchor, head, goalColumn, bidiLevel) {
|
||||
let flags = ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* RangeFlag.NoGoalColumn */) << 5 /* RangeFlag.GoalColumnOffset */) |
|
||||
(bidiLevel == null ? 3 : Math.min(2, bidiLevel));
|
||||
return head < anchor ? SelectionRange.create(head, anchor, 16 /* RangeFlag.Inverted */ | 8 /* RangeFlag.AssocAfter */ | flags)
|
||||
: SelectionRange.create(anchor, head, (head > anchor ? 4 /* RangeFlag.AssocBefore */ : 0) | flags);
|
||||
}
|
||||
/**
|
||||
@internal
|
||||
|
@ -1551,21 +1566,17 @@ class Facet {
|
|||
/**
|
||||
@internal
|
||||
*/
|
||||
compare, isStatic,
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
extensions) {
|
||||
compare, isStatic, enables) {
|
||||
this.combine = combine;
|
||||
this.compareInput = compareInput;
|
||||
this.compare = compare;
|
||||
this.isStatic = isStatic;
|
||||
this.extensions = extensions;
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
this.id = nextID++;
|
||||
this.default = combine([]);
|
||||
this.extensions = typeof enables == "function" ? enables(this) : enables;
|
||||
}
|
||||
/**
|
||||
Define a new facet.
|
||||
|
@ -1577,7 +1588,7 @@ class Facet {
|
|||
Returns an extension that adds the given value to this facet.
|
||||
*/
|
||||
of(value) {
|
||||
return new FacetProvider([], this, 0 /* Static */, value);
|
||||
return new FacetProvider([], this, 0 /* Provider.Static */, value);
|
||||
}
|
||||
/**
|
||||
Create an extension that computes a value for the facet from a
|
||||
|
@ -1591,7 +1602,7 @@ class Facet {
|
|||
compute(deps, get) {
|
||||
if (this.isStatic)
|
||||
throw new Error("Can't compute a static facet");
|
||||
return new FacetProvider(deps, this, 1 /* Single */, get);
|
||||
return new FacetProvider(deps, this, 1 /* Provider.Single */, get);
|
||||
}
|
||||
/**
|
||||
Create an extension that computes zero or more values for this
|
||||
|
@ -1600,7 +1611,7 @@ class Facet {
|
|||
computeN(deps, get) {
|
||||
if (this.isStatic)
|
||||
throw new Error("Can't compute a static facet");
|
||||
return new FacetProvider(deps, this, 2 /* Multi */, get);
|
||||
return new FacetProvider(deps, this, 2 /* Provider.Multi */, get);
|
||||
}
|
||||
from(field, get) {
|
||||
if (!get)
|
||||
|
@ -1623,7 +1634,7 @@ class FacetProvider {
|
|||
var _a;
|
||||
let getter = this.value;
|
||||
let compare = this.facet.compareInput;
|
||||
let id = this.id, idx = addresses[id] >> 1, multi = this.type == 2 /* Multi */;
|
||||
let id = this.id, idx = addresses[id] >> 1, multi = this.type == 2 /* Provider.Multi */;
|
||||
let depDoc = false, depSel = false, depAddrs = [];
|
||||
for (let dep of this.dependencies) {
|
||||
if (dep == "doc")
|
||||
|
@ -1636,33 +1647,35 @@ class FacetProvider {
|
|||
return {
|
||||
create(state) {
|
||||
state.values[idx] = getter(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
update(state, tr) {
|
||||
if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || ensureAll(state, depAddrs)) {
|
||||
let newVal = getter(state);
|
||||
if (multi ? !compareArray(newVal, state.values[idx], compare) : !compare(newVal, state.values[idx])) {
|
||||
state.values[idx] = newVal;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
reconfigure: (state, oldState) => {
|
||||
let newVal = getter(state);
|
||||
let oldAddr = oldState.config.address[id];
|
||||
let newVal, oldAddr = oldState.config.address[id];
|
||||
if (oldAddr != null) {
|
||||
let oldVal = getAddr(oldState, oldAddr);
|
||||
if (this.dependencies.every(dep => {
|
||||
return dep instanceof Facet ? oldState.facet(dep) === state.facet(dep) :
|
||||
dep instanceof StateField ? oldState.field(dep, false) == state.field(dep, false) : true;
|
||||
}) || (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))) {
|
||||
}) || (multi ? compareArray(newVal = getter(state), oldVal, compare) : compare(newVal = getter(state), oldVal))) {
|
||||
state.values[idx] = oldVal;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
newVal = getter(state);
|
||||
}
|
||||
state.values[idx] = newVal;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1678,7 +1691,7 @@ function compareArray(a, b, compare) {
|
|||
function ensureAll(state, addrs) {
|
||||
let changed = false;
|
||||
for (let addr of addrs)
|
||||
if (ensureAddr(state, addr) & 1 /* Changed */)
|
||||
if (ensureAddr(state, addr) & 1 /* SlotStatus.Changed */)
|
||||
changed = true;
|
||||
return changed;
|
||||
}
|
||||
|
@ -1691,7 +1704,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
let values = [];
|
||||
for (let i = 0; i < providerAddrs.length; i++) {
|
||||
let value = getAddr(state, providerAddrs[i]);
|
||||
if (providerTypes[i] == 2 /* Multi */)
|
||||
if (providerTypes[i] == 2 /* Provider.Multi */)
|
||||
for (let val of value)
|
||||
values.push(val);
|
||||
else
|
||||
|
@ -1704,7 +1717,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
for (let addr of providerAddrs)
|
||||
ensureAddr(state, addr);
|
||||
state.values[idx] = get(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
update(state, tr) {
|
||||
if (!ensureAll(state, dynamic))
|
||||
|
@ -1713,7 +1726,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
if (facet.compare(value, state.values[idx]))
|
||||
return 0;
|
||||
state.values[idx] = value;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
reconfigure(state, oldState) {
|
||||
let depChanged = ensureAll(state, providerAddrs);
|
||||
|
@ -1728,7 +1741,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|||
return 0;
|
||||
}
|
||||
state.values[idx] = value;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1778,7 +1791,7 @@ class StateField {
|
|||
return {
|
||||
create: (state) => {
|
||||
state.values[idx] = this.create(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
update: (state, tr) => {
|
||||
let oldVal = state.values[idx];
|
||||
|
@ -1786,7 +1799,7 @@ class StateField {
|
|||
if (this.compareF(oldVal, value))
|
||||
return 0;
|
||||
state.values[idx] = value;
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
},
|
||||
reconfigure: (state, oldState) => {
|
||||
if (oldState.config.address[this.id] != null) {
|
||||
|
@ -1794,7 +1807,7 @@ class StateField {
|
|||
return 0;
|
||||
}
|
||||
state.values[idx] = this.create(state);
|
||||
return 1 /* Changed */;
|
||||
return 1 /* SlotStatus.Changed */;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1903,7 +1916,7 @@ class Configuration {
|
|||
this.facets = facets;
|
||||
this.statusTemplate = [];
|
||||
while (this.statusTemplate.length < dynamicSlots.length)
|
||||
this.statusTemplate.push(0 /* Unresolved */);
|
||||
this.statusTemplate.push(0 /* SlotStatus.Unresolved */);
|
||||
}
|
||||
staticFacet(facet) {
|
||||
let addr = this.address[facet.id];
|
||||
|
@ -1930,7 +1943,7 @@ class Configuration {
|
|||
for (let id in facets) {
|
||||
let providers = facets[id], facet = providers[0].facet;
|
||||
let oldProviders = oldFacets && oldFacets[id] || [];
|
||||
if (providers.every(p => p.type == 0 /* Static */)) {
|
||||
if (providers.every(p => p.type == 0 /* Provider.Static */)) {
|
||||
address[facet.id] = (staticValues.length << 1) | 1;
|
||||
if (sameArray(oldProviders, providers)) {
|
||||
staticValues.push(oldState.facet(facet));
|
||||
|
@ -1942,7 +1955,7 @@ class Configuration {
|
|||
}
|
||||
else {
|
||||
for (let p of providers) {
|
||||
if (p.type == 0 /* Static */) {
|
||||
if (p.type == 0 /* Provider.Static */) {
|
||||
address[p.id] = (staticValues.length << 1) | 1;
|
||||
staticValues.push(p.value);
|
||||
}
|
||||
|
@ -1996,7 +2009,7 @@ function flatten(extension, compartments, newCompartments) {
|
|||
else if (ext instanceof FacetProvider) {
|
||||
result[prec].push(ext);
|
||||
if (ext.facet.extensions)
|
||||
inner(ext.facet.extensions, prec);
|
||||
inner(ext.facet.extensions, Prec_.default);
|
||||
}
|
||||
else {
|
||||
let content = ext.extension;
|
||||
|
@ -2010,16 +2023,16 @@ function flatten(extension, compartments, newCompartments) {
|
|||
}
|
||||
function ensureAddr(state, addr) {
|
||||
if (addr & 1)
|
||||
return 2 /* Computed */;
|
||||
return 2 /* SlotStatus.Computed */;
|
||||
let idx = addr >> 1;
|
||||
let status = state.status[idx];
|
||||
if (status == 4 /* Computing */)
|
||||
if (status == 4 /* SlotStatus.Computing */)
|
||||
throw new Error("Cyclic dependency between fields and/or facets");
|
||||
if (status & 2 /* Computed */)
|
||||
if (status & 2 /* SlotStatus.Computed */)
|
||||
return status;
|
||||
state.status[idx] = 4 /* Computing */;
|
||||
state.status[idx] = 4 /* SlotStatus.Computing */;
|
||||
let changed = state.computeSlot(state, state.config.dynamicSlots[idx]);
|
||||
return state.status[idx] = 2 /* Computed */ | changed;
|
||||
return state.status[idx] = 2 /* SlotStatus.Computed */ | changed;
|
||||
}
|
||||
function getAddr(state, addr) {
|
||||
return addr & 1 ? state.config.staticValues[addr >> 1] : state.values[addr >> 1];
|
||||
|
@ -2434,7 +2447,7 @@ function filterTransaction(tr) {
|
|||
else {
|
||||
let filtered = tr.changes.filter(result);
|
||||
changes = filtered.changes;
|
||||
back = filtered.filtered.invertedDesc;
|
||||
back = filtered.filtered.mapDesc(filtered.changes).invertedDesc;
|
||||
}
|
||||
tr = Transaction.create(state, changes, tr.selection && tr.selection.map(back), StateEffect.mapEffects(tr.effects, back), tr.annotations, tr.scrollIntoView);
|
||||
}
|
||||
|
@ -2456,7 +2469,7 @@ function extendTransaction(tr) {
|
|||
for (let i = extenders.length - 1; i >= 0; i--) {
|
||||
let extension = extenders[i](tr);
|
||||
if (extension && Object.keys(extension).length)
|
||||
spec = mergeTransaction(tr, resolveTransactionInner(state, extension, tr.changes.newLength), true);
|
||||
spec = mergeTransaction(spec, resolveTransactionInner(state, extension, tr.changes.newLength), true);
|
||||
}
|
||||
return spec == tr ? tr : Transaction.create(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.scrollIntoView);
|
||||
}
|
||||
|
@ -2706,7 +2719,7 @@ class EditorState {
|
|||
if (fields)
|
||||
for (let prop in fields) {
|
||||
let value = fields[prop];
|
||||
if (value instanceof StateField)
|
||||
if (value instanceof StateField && this.config.address[value.id] != null)
|
||||
result[prop] = value.spec.toJSON(this.field(fields[prop]), this);
|
||||
}
|
||||
return result;
|
||||
|
@ -2723,8 +2736,10 @@ class EditorState {
|
|||
let fieldInit = [];
|
||||
if (fields)
|
||||
for (let prop in fields) {
|
||||
let field = fields[prop], value = json[prop];
|
||||
fieldInit.push(field.init(state => field.spec.fromJSON(value, state)));
|
||||
if (Object.prototype.hasOwnProperty.call(json, prop)) {
|
||||
let field = fields[prop], value = json[prop];
|
||||
fieldInit.push(field.init(state => field.spec.fromJSON(value, state)));
|
||||
}
|
||||
}
|
||||
return EditorState.create({
|
||||
doc: json.doc,
|
||||
|
@ -2785,13 +2800,25 @@ class EditorState {
|
|||
if (i == "$")
|
||||
return "$";
|
||||
let n = +(i || 1);
|
||||
return n > insert.length ? m : insert[n - 1];
|
||||
return !n || n > insert.length ? m : insert[n - 1];
|
||||
});
|
||||
return phrase;
|
||||
}
|
||||
/**
|
||||
Find the values for a given language data field, provided by the
|
||||
the [`languageData`](https://codemirror.net/6/docs/ref/#state.EditorState^languageData) facet.
|
||||
|
||||
Examples of language data fields are...
|
||||
|
||||
- [`"commentTokens"`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) for specifying
|
||||
comment syntax.
|
||||
- [`"autocomplete"`](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion^config.override)
|
||||
for providing language-specific completion sources.
|
||||
- [`"wordChars"`](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer) for adding
|
||||
characters that should be considered part of words in this
|
||||
language.
|
||||
- [`"closeBrackets"`](https://codemirror.net/6/docs/ref/#autocomplete.CloseBracketConfig) controls
|
||||
bracket closing behavior.
|
||||
*/
|
||||
languageDataAt(name, pos, side = -1) {
|
||||
let values = [];
|
||||
|
@ -3063,7 +3090,7 @@ class Chunk {
|
|||
}
|
||||
}
|
||||
between(offset, from, to, f) {
|
||||
for (let i = this.findIndex(from, -1000000000 /* Far */, true), e = this.findIndex(to, 1000000000 /* Far */, false, i); i < e; i++)
|
||||
for (let i = this.findIndex(from, -1000000000 /* C.Far */, true), e = this.findIndex(to, 1000000000 /* C.Far */, false, i); i < e; i++)
|
||||
if (f(this.from[i] + offset, this.to[i] + offset, this.value[i]) === false)
|
||||
return false;
|
||||
}
|
||||
|
@ -3296,7 +3323,7 @@ class RangeSet {
|
|||
*/
|
||||
static eq(oldSets, newSets, from = 0, to) {
|
||||
if (to == null)
|
||||
to = 1000000000 /* Far */;
|
||||
to = 1000000000 /* C.Far */ - 1;
|
||||
let a = oldSets.filter(set => !set.isEmpty && newSets.indexOf(set) < 0);
|
||||
let b = newSets.filter(set => !set.isEmpty && oldSets.indexOf(set) < 0);
|
||||
if (a.length != b.length)
|
||||
|
@ -3330,23 +3357,24 @@ class RangeSet {
|
|||
*/
|
||||
minPointSize = -1) {
|
||||
let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from;
|
||||
let open = cursor.openStart;
|
||||
let openRanges = cursor.openStart;
|
||||
for (;;) {
|
||||
let curTo = Math.min(cursor.to, to);
|
||||
if (cursor.point) {
|
||||
iterator.point(pos, curTo, cursor.point, cursor.activeForPoint(cursor.to), open, cursor.pointRank);
|
||||
open = cursor.openEnd(curTo) + (cursor.to > curTo ? 1 : 0);
|
||||
let active = cursor.activeForPoint(cursor.to);
|
||||
let openCount = cursor.pointFrom < from ? active.length + 1 : Math.min(active.length, openRanges);
|
||||
iterator.point(pos, curTo, cursor.point, active, openCount, cursor.pointRank);
|
||||
openRanges = Math.min(cursor.openEnd(curTo), active.length);
|
||||
}
|
||||
else if (curTo > pos) {
|
||||
iterator.span(pos, curTo, cursor.active, open);
|
||||
open = cursor.openEnd(curTo);
|
||||
iterator.span(pos, curTo, cursor.active, openRanges);
|
||||
openRanges = cursor.openEnd(curTo);
|
||||
}
|
||||
if (cursor.to > to)
|
||||
break;
|
||||
return openRanges + (cursor.point && cursor.to > to ? 1 : 0);
|
||||
pos = cursor.to;
|
||||
cursor.next();
|
||||
}
|
||||
return open;
|
||||
}
|
||||
/**
|
||||
Create a range set for the given range or array of ranges. By
|
||||
|
@ -3391,8 +3419,8 @@ class RangeSetBuilder {
|
|||
this.chunkPos = [];
|
||||
this.chunkStart = -1;
|
||||
this.last = null;
|
||||
this.lastFrom = -1000000000 /* Far */;
|
||||
this.lastTo = -1000000000 /* Far */;
|
||||
this.lastFrom = -1000000000 /* C.Far */;
|
||||
this.lastTo = -1000000000 /* C.Far */;
|
||||
this.from = [];
|
||||
this.to = [];
|
||||
this.value = [];
|
||||
|
@ -3429,7 +3457,7 @@ class RangeSetBuilder {
|
|||
throw new Error("Ranges must be added sorted by `from` position and `startSide`");
|
||||
if (diff < 0)
|
||||
return false;
|
||||
if (this.from.length == 250 /* ChunkSize */)
|
||||
if (this.from.length == 250 /* C.ChunkSize */)
|
||||
this.finishChunk(true);
|
||||
if (this.chunkStart < 0)
|
||||
this.chunkStart = from;
|
||||
|
@ -3503,7 +3531,7 @@ class LayerCursor {
|
|||
}
|
||||
get startSide() { return this.value ? this.value.startSide : 0; }
|
||||
get endSide() { return this.value ? this.value.endSide : 0; }
|
||||
goto(pos, side = -1000000000 /* Far */) {
|
||||
goto(pos, side = -1000000000 /* C.Far */) {
|
||||
this.chunkIndex = this.rangeIndex = 0;
|
||||
this.gotoInner(pos, side, false);
|
||||
return this;
|
||||
|
@ -3532,7 +3560,7 @@ class LayerCursor {
|
|||
next() {
|
||||
for (;;) {
|
||||
if (this.chunkIndex == this.layer.chunk.length) {
|
||||
this.from = this.to = 1000000000 /* Far */;
|
||||
this.from = this.to = 1000000000 /* C.Far */;
|
||||
this.value = null;
|
||||
break;
|
||||
}
|
||||
|
@ -3586,7 +3614,7 @@ class HeapCursor {
|
|||
return heap.length == 1 ? heap[0] : new HeapCursor(heap);
|
||||
}
|
||||
get startSide() { return this.value ? this.value.startSide : 0; }
|
||||
goto(pos, side = -1000000000 /* Far */) {
|
||||
goto(pos, side = -1000000000 /* C.Far */) {
|
||||
for (let cur of this.heap)
|
||||
cur.goto(pos, side);
|
||||
for (let i = this.heap.length >> 1; i >= 0; i--)
|
||||
|
@ -3604,7 +3632,7 @@ class HeapCursor {
|
|||
}
|
||||
next() {
|
||||
if (this.heap.length == 0) {
|
||||
this.from = this.to = 1000000000 /* Far */;
|
||||
this.from = this.to = 1000000000 /* C.Far */;
|
||||
this.value = null;
|
||||
this.rank = -1;
|
||||
}
|
||||
|
@ -3648,12 +3676,14 @@ class SpanCursor {
|
|||
this.point = null;
|
||||
this.pointFrom = 0;
|
||||
this.pointRank = 0;
|
||||
this.to = -1000000000 /* Far */;
|
||||
this.to = -1000000000 /* C.Far */;
|
||||
this.endSide = 0;
|
||||
// The amount of open active ranges at the start of the iterator.
|
||||
// Not including points.
|
||||
this.openStart = -1;
|
||||
this.cursor = HeapCursor.from(sets, skip, minPoint);
|
||||
}
|
||||
goto(pos, side = -1000000000 /* Far */) {
|
||||
goto(pos, side = -1000000000 /* C.Far */) {
|
||||
this.cursor.goto(pos, side);
|
||||
this.active.length = this.activeTo.length = this.activeRank.length = 0;
|
||||
this.minActive = -1;
|
||||
|
@ -3690,7 +3720,7 @@ class SpanCursor {
|
|||
next() {
|
||||
let from = this.to, wasPoint = this.point;
|
||||
this.point = null;
|
||||
let trackOpen = this.openStart < 0 ? [] : null, trackExtra = 0;
|
||||
let trackOpen = this.openStart < 0 ? [] : null;
|
||||
for (;;) {
|
||||
let a = this.minActive;
|
||||
if (a > -1 && (this.activeTo[a] - this.cursor.from || this.active[a].endSide - this.cursor.startSide) < 0) {
|
||||
|
@ -3704,7 +3734,7 @@ class SpanCursor {
|
|||
remove(trackOpen, a);
|
||||
}
|
||||
else if (!this.cursor.value) {
|
||||
this.to = this.endSide = 1000000000 /* Far */;
|
||||
this.to = this.endSide = 1000000000 /* C.Far */;
|
||||
break;
|
||||
}
|
||||
else if (this.cursor.from > from) {
|
||||
|
@ -3728,8 +3758,6 @@ class SpanCursor {
|
|||
this.pointRank = this.cursor.rank;
|
||||
this.to = this.cursor.to;
|
||||
this.endSide = nextVal.endSide;
|
||||
if (this.cursor.from < from)
|
||||
trackExtra = 1;
|
||||
this.cursor.next();
|
||||
this.forward(this.to, this.endSide);
|
||||
break;
|
||||
|
@ -3737,10 +3765,9 @@ class SpanCursor {
|
|||
}
|
||||
}
|
||||
if (trackOpen) {
|
||||
let openStart = 0;
|
||||
while (openStart < trackOpen.length && trackOpen[openStart] < from)
|
||||
openStart++;
|
||||
this.openStart = openStart + trackExtra;
|
||||
this.openStart = 0;
|
||||
for (let i = trackOpen.length - 1; i >= 0 && trackOpen[i] < from; i--)
|
||||
this.openStart++;
|
||||
}
|
||||
}
|
||||
activeForPoint(to) {
|
||||
|
@ -3807,7 +3834,7 @@ function insert(array, index, value) {
|
|||
array[index] = value;
|
||||
}
|
||||
function findMinIndex(value, array) {
|
||||
let found = -1, foundPos = 1000000000 /* Far */;
|
||||
let found = -1, foundPos = 1000000000 /* C.Far */;
|
||||
for (let i = 0; i < array.length; i++)
|
||||
if ((array[i] - foundPos || value[i].endSide - value[found].endSide) < 0) {
|
||||
found = i;
|
||||
|
|
2
node_modules/@codemirror/state/package.json
generated
vendored
2
node_modules/@codemirror/state/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/state",
|
||||
"version": "6.0.0",
|
||||
"version": "6.2.0",
|
||||
"description": "Editor state data structures for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
|
2
node_modules/@codemirror/view/.github/workflows/dispatch.yml
generated
vendored
2
node_modules/@codemirror/view/.github/workflows/dispatch.yml
generated
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
with:
|
||||
# You should create a personal access token and store it in your repository
|
||||
token: ${{ secrets.DISPATCH_AUTH }}
|
||||
repo: codemirror.next
|
||||
repo: dev
|
||||
owner: codemirror
|
||||
event_type: push
|
||||
|
|
282
node_modules/@codemirror/view/CHANGELOG.md
generated
vendored
282
node_modules/@codemirror/view/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,285 @@
|
|||
## 6.8.1 (2023-02-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where tooltips that have their height reduced have their height flicker when scrolling or otherwise interacting with the editor.
|
||||
|
||||
## 6.8.0 (2023-02-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a regression that caused clicking on the scrollbar to move the selection.
|
||||
|
||||
Fix an issue where focus or blur event handlers that dispatched editor transactions could corrupt the mouse selection state.
|
||||
|
||||
Fix a CSS regression that prevented the drop cursor from being positioned properly.
|
||||
|
||||
### New features
|
||||
|
||||
`WidgetType.updateDOM` is now passed the editor view object.
|
||||
|
||||
## 6.7.3 (2023-01-12)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug in `posAtCoords` that could cause incorrect results for positions to the left of a wrapped line.
|
||||
|
||||
## 6.7.2 (2023-01-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a regression where the cursor didn't restart its blink cycle when moving it with the pointer.
|
||||
|
||||
Even without a `key` property, measure request objects that are already scheduled will not be scheduled again by `requestMeasure`.
|
||||
|
||||
Fix an issue where keymaps incorrectly interpreted key events that used Ctrl+Alt modifiers to simulate AltGr on Windows.
|
||||
|
||||
Fix a bug where line decorations with a different `class` property would be treated as equal.
|
||||
|
||||
Fix a bug that caused `drawSelection` to not notice when it was reconfigured.
|
||||
|
||||
Fix a crash in the gutter extension caused by sharing of mutable arrays.
|
||||
|
||||
Fix a regression that caused touch selection on mobile platforms to not work in an uneditable editor.
|
||||
|
||||
Fix a bug where DOM events on the boundary between lines could get assigned to the wrong line.
|
||||
|
||||
## 6.7.1 (2022-12-12)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make the editor properly scroll when moving the pointer out of it during drag selection.
|
||||
|
||||
Fix a regression where clicking below the content element in an editor with its own height didn't focus the editor.
|
||||
|
||||
## 6.7.0 (2022-12-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make the editor notice widget height changes to automatically adjust its height information.
|
||||
|
||||
Fix an issue where widget buffers could be incorrectly omitted after empty lines.
|
||||
|
||||
Fix an issue in content redrawing that could cause `coordsAtPos` to return incorrect results.
|
||||
|
||||
### New features
|
||||
|
||||
The static `RectangleMarker.forRange` method exposes the logic used by the editor to draw rectangles covering a selection range.
|
||||
|
||||
Layers can now provide a `destroy` function to be called when the layer is removed.
|
||||
|
||||
The new `highlightWhitespace` extension makes spaces and tabs in the editor visible.
|
||||
|
||||
The `highlightTrailingWhitespace` extension can be used to make trailing whitespace stand out.
|
||||
|
||||
## 6.6.0 (2022-11-24)
|
||||
|
||||
### New features
|
||||
|
||||
The `layer` function can now be used to define extensions that draw DOM elements over or below the document text.
|
||||
|
||||
Tooltips that are bigger than the available vertical space for them will now have their height set so that they don't stick out of the window. The new `resize` property on `TooltipView` can be used to opt out of this behavior.
|
||||
|
||||
## 6.5.1 (2022-11-15)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused marked unnecessary splitting of mark decoration DOM elements in some cases.
|
||||
|
||||
## 6.5.0 (2022-11-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where key bindings were activated for the wrong key in some situations with non-US keyboards.
|
||||
|
||||
### New features
|
||||
|
||||
A tooltip's `positioned` callback is now passed the available space for tooltips.
|
||||
|
||||
## 6.4.2 (2022-11-10)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Typing into a read-only editor no longer moves the cursor.
|
||||
|
||||
Fix an issue where hover tooltips were closed when the mouse was moved over them if they had a custom parent element.
|
||||
|
||||
Fix an issue where the editor could end up displaying incorrect height measurements (typically after initializing).
|
||||
|
||||
## 6.4.1 (2022-11-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where coordinates next to replaced widgets were returned incorrectly, causing the cursor to be drawn in the wrong place.
|
||||
|
||||
Update the `crosshairCursor` state on every mousemove event.
|
||||
|
||||
Avoid an issue in the way that the editor enforces cursor associativity that could cause the cursor to get stuck on single-character wrapped lines.
|
||||
|
||||
## 6.4.0 (2022-10-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Avoid an issue where `scrollPastEnd` makes a single-line editor have a vertical scrollbar.
|
||||
|
||||
Work around a Chrome bug where it inserts a newline when you press space at the start of a wrapped line.
|
||||
|
||||
Align `rectangularSelection`'s behavior with other popular editors by making it create cursors at the end of lines that are too short to touch the rectangle.
|
||||
|
||||
Fix an issue where coordinates on mark decoration boundaries were sometimes taken from the wrong side of the position.
|
||||
|
||||
Prevent scrolling artifacts caused by attempts to scroll stuff into view when the editor isn't being displayed.
|
||||
|
||||
### New features
|
||||
|
||||
`TooltipView` objects can now provide a `destroy` method to be called when the tooltip is removed.
|
||||
|
||||
## 6.3.1 (2022-10-10)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a crash when trying to scroll something into view in an editor that wasn't in the visible DOM.
|
||||
|
||||
Fix an issue where `coordsAtPos` returned the coordinates on the wrong side of a widget decoration wrapped in a mark decoration.
|
||||
|
||||
Fix an issue where content on long wrapped lines could fail to properly scroll into view.
|
||||
|
||||
Fix an issue where DOM change reading on Chrome Android could get confused when a transaction came in right after a beforeinput event for backspace, enter, or delete.
|
||||
|
||||
## 6.3.0 (2022-09-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Reduce the amount of wrap-point jittering when scrolling through a very long wrapped line.
|
||||
|
||||
Fix an issue where scrolling to content that wasn't currently drawn due to being on a very long line would often fail to scroll to the right position.
|
||||
|
||||
Suppress double-space-adds-period behavior on Chrome Mac when it behaves weirdly next to widget.
|
||||
|
||||
### New features
|
||||
|
||||
Key binding objects with an `any` property will now add handlers that are called for any key, within the ordering of the keybindings.
|
||||
|
||||
## 6.2.5 (2022-09-24)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't override double/triple tap behavior on touch screen devices, so that the mobile selection menu pops up properly.
|
||||
|
||||
Fix an issue where updating the selection could crash on Safari when the editor was hidden.
|
||||
|
||||
## 6.2.4 (2022-09-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Highlight the active line even when there is a selection. Prevent the active line background from obscuring the selection backdrop.
|
||||
|
||||
Fix an issue where elements with negative margins would confuse the editor's scrolling-into-view logic.
|
||||
|
||||
Fix scrolling to a specific position in an editor that has not been in view yet.
|
||||
|
||||
## 6.2.3 (2022-09-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug where cursor motion, when starting from a non-empty selection range, could get stuck on atomic ranges in some circumstances.
|
||||
|
||||
Avoid triggering Chrome Android's text-duplication issue when a period is typed in the middle of a word.
|
||||
|
||||
## 6.2.2 (2022-08-31)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't reset the selection for selection change events that were suppressed by a node view.
|
||||
|
||||
## 6.2.1 (2022-08-25)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't use the global `document` variable to track focus, since that doesn't work in another window/frame.
|
||||
|
||||
Fix an issue where key handlers that didn't return true were sometimes called twice for the same keypress.
|
||||
|
||||
Avoid editing glitches when using deletion keys like ctrl-d on iOS.
|
||||
|
||||
Properly treat characters from the 'Arabic Presentation Forms-A' Unicode block as right-to-left.
|
||||
|
||||
Work around a Firefox bug that inserts text at the wrong point for specific cross-line selections.
|
||||
|
||||
## 6.2.0 (2022-08-05)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug where `posAtCoords` would return the wrong results for positions to the right of wrapped lines.
|
||||
|
||||
### New features
|
||||
|
||||
The new `EditorView.setRoot` method can be used when an editor view is moved to a new document or shadow root.
|
||||
|
||||
## 6.1.4 (2022-08-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make selection-restoration on focus more reliable.
|
||||
|
||||
## 6.1.3 (2022-08-03)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug where a document that contains only non-printing characters would lead to bogus text measurements (and, from those, to crashing).
|
||||
|
||||
Make sure differences between estimated and actual block heights don't cause visible scroll glitches.
|
||||
|
||||
## 6.1.2 (2022-07-27)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue where double tapping enter to confirm IME input and insert a newline on iOS would sometimes insert two newlines.
|
||||
|
||||
Fix an issue on iOS where a composition could get aborted if the editor scrolled on backspace.
|
||||
|
||||
## 6.1.1 (2022-07-25)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make `highlightSpecialChars` replace directional isolate characters by default.
|
||||
|
||||
The editor will now try to suppress browsers' native behavior of resetting the selection in the editable content when the editable element is focused (programmatically, with tab, etc).
|
||||
|
||||
Fix a CSS issue that made it possible, when the gutters were wide enough, for them to overlap with the content.
|
||||
|
||||
## 6.1.0 (2022-07-19)
|
||||
|
||||
### New features
|
||||
|
||||
`MatchDecorator` now supports a `decorate` option that can be used to customize the way decorations are added for each match.
|
||||
|
||||
## 6.0.3 (2022-07-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a problem where `posAtCoords` could incorrectly return the start of the next line when querying positions between lines.
|
||||
|
||||
Fix an issue where registering a high-precedence keymap made keymap handling take precedence over other keydown event handlers.
|
||||
|
||||
Ctrl/Cmd-clicking can now remove ranges from a multi-range selection.
|
||||
|
||||
## 6.0.2 (2022-06-23)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a CSS issue that broke horizontal scroll width stabilization.
|
||||
|
||||
Fix a bug where `defaultLineHeight` could get an incorrect value in very narrow editors.
|
||||
|
||||
## 6.0.1 (2022-06-17)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Avoid DOM selection corruption when the editor doesn't have focus but has selection and updates its content.
|
||||
|
||||
Fall back to dispatching by key code when a key event produces a non-ASCII character (so that Cyrillic and Arabic keyboards can still use bindings specified with Latin characters).
|
||||
|
||||
## 6.0.0 (2022-06-08)
|
||||
|
||||
### New features
|
||||
|
|
2
node_modules/@codemirror/view/LICENSE
generated
vendored
2
node_modules/@codemirror/view/LICENSE
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (C) 2018-2021 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||
Copyright (C) 2018-2021 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
10
node_modules/@codemirror/view/README.md
generated
vendored
10
node_modules/@codemirror/view/README.md
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
# @codemirror/view [](https://www.npmjs.org/package/@codemirror/view)
|
||||
|
||||
[ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/view/blob/main/CHANGELOG.md) ]
|
||||
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/view/blob/main/CHANGELOG.md) ]
|
||||
|
||||
This package implements the DOM view component for the
|
||||
[CodeMirror](https://codemirror.net/6/) code editor.
|
||||
[CodeMirror](https://codemirror.net/) code editor.
|
||||
|
||||
The [project page](https://codemirror.net/6/) has more information, a
|
||||
number of [examples](https://codemirror.net/6/examples/) and the
|
||||
[documentation](https://codemirror.net/6/docs/).
|
||||
The [project page](https://codemirror.net/) has more information, a
|
||||
number of [examples](https://codemirror.net/examples/) and the
|
||||
[documentation](https://codemirror.net/docs/).
|
||||
|
||||
This code is released under an
|
||||
[MIT license](https://github.com/codemirror/view/tree/main/LICENSE).
|
||||
|
|
2504
node_modules/@codemirror/view/dist/index.cjs
generated
vendored
2504
node_modules/@codemirror/view/dist/index.cjs
generated
vendored
File diff suppressed because it is too large
Load diff
171
node_modules/@codemirror/view/dist/index.d.ts
generated
vendored
171
node_modules/@codemirror/view/dist/index.d.ts
generated
vendored
|
@ -154,7 +154,7 @@ declare abstract class WidgetType {
|
|||
couldn't (in which case the widget will be redrawn). The default
|
||||
implementation just returns false.
|
||||
*/
|
||||
updateDOM(dom: HTMLElement): boolean;
|
||||
updateDOM(dom: HTMLElement, view: EditorView): boolean;
|
||||
/**
|
||||
The estimated height this widget will have, to be used when
|
||||
estimating the height of content that hasn't been drawn. May
|
||||
|
@ -647,10 +647,11 @@ declare class EditorView {
|
|||
*/
|
||||
get compositionStarted(): boolean;
|
||||
private _dispatch;
|
||||
private _root;
|
||||
/**
|
||||
The document or shadow root that the view lives in.
|
||||
*/
|
||||
readonly root: DocumentOrShadowRoot;
|
||||
get root(): DocumentOrShadowRoot;
|
||||
/**
|
||||
The DOM element that wraps the entire editor view.
|
||||
*/
|
||||
|
@ -735,7 +736,7 @@ declare class EditorView {
|
|||
know you registered a given plugin, it is recommended to check
|
||||
the return value of this method.
|
||||
*/
|
||||
plugin<T>(plugin: ViewPlugin<T>): T | null;
|
||||
plugin<T extends PluginValue>(plugin: ViewPlugin<T>): T | null;
|
||||
/**
|
||||
The top position of the document, in screen coordinates. This
|
||||
may be negative when the editor is scrolled down. Points
|
||||
|
@ -752,13 +753,14 @@ declare class EditorView {
|
|||
/**
|
||||
Find the text line or block widget at the given vertical
|
||||
position (which is interpreted as relative to the [top of the
|
||||
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
||||
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
||||
*/
|
||||
elementAtHeight(height: number): BlockInfo;
|
||||
/**
|
||||
Find the line block (see
|
||||
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
||||
height.
|
||||
height, again interpreted relative to the [top of the
|
||||
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop).
|
||||
*/
|
||||
lineBlockAtHeight(height: number): BlockInfo;
|
||||
/**
|
||||
|
@ -921,6 +923,11 @@ declare class EditorView {
|
|||
*/
|
||||
focus(): void;
|
||||
/**
|
||||
Update the [root](https://codemirror.net/6/docs/ref/##view.EditorViewConfig.root) in which the editor lives. This is only
|
||||
necessary when moving the editor's existing DOM to a new window or shadow root.
|
||||
*/
|
||||
setRoot(root: Document | ShadowRoot): void;
|
||||
/**
|
||||
Clean up this editor view, removing its element from the
|
||||
document, unregistering event handlers, and notifying
|
||||
plugins. The view instance can no longer be used after
|
||||
|
@ -1047,6 +1054,11 @@ declare class EditorView {
|
|||
functions are called _after_ the new viewport has been computed,
|
||||
and thus **must not** introduce block widgets or replacing
|
||||
decorations that cover line breaks.
|
||||
|
||||
If you want decorated ranges to behave like atomic units for
|
||||
cursor motion and deletion purposes, also provide the range set
|
||||
containing the decorations to
|
||||
[`EditorView.atomicRanges`](https://codemirror.net/6/docs/ref/#view.EditorView^atomicRanges).
|
||||
*/
|
||||
static decorations: Facet<DecorationSet | ((view: EditorView) => DecorationSet), readonly (DecorationSet | ((view: EditorView) => DecorationSet))[]>;
|
||||
/**
|
||||
|
@ -1207,7 +1219,7 @@ interface KeyBinding {
|
|||
command function returns `false`, further bindings will be tried
|
||||
for the key.
|
||||
*/
|
||||
run: Command;
|
||||
run?: Command;
|
||||
/**
|
||||
When given, this defines a second binding, using the (possibly
|
||||
platform-specific) key name prefixed with `Shift-` to activate
|
||||
|
@ -1215,6 +1227,11 @@ interface KeyBinding {
|
|||
*/
|
||||
shift?: Command;
|
||||
/**
|
||||
When this property is present, the function is called for every
|
||||
key that is not a multi-stroke prefix.
|
||||
*/
|
||||
any?: (view: EditorView, event: KeyboardEvent) => boolean;
|
||||
/**
|
||||
By default, key bindings apply when focus is on the editor
|
||||
content (the `"editor"` scope). Some extensions, mostly those
|
||||
that define their own panels, might want to allow you to
|
||||
|
@ -1349,6 +1366,94 @@ to show when the editor is empty.
|
|||
*/
|
||||
declare function placeholder(content: string | HTMLElement): Extension;
|
||||
|
||||
/**
|
||||
Markers shown in a [layer](https://codemirror.net/6/docs/ref/#view.layer) must conform to this
|
||||
interface. They are created in a measuring phase, and have to
|
||||
contain all their positioning information, so that they can be
|
||||
drawn without further DOM layout reading.
|
||||
|
||||
Markers are automatically absolutely positioned. Their parent
|
||||
element has the same top-left corner as the document, so they
|
||||
should be positioned relative to the document.
|
||||
*/
|
||||
interface LayerMarker {
|
||||
/**
|
||||
Compare this marker to a marker of the same type. Used to avoid
|
||||
unnecessary redraws.
|
||||
*/
|
||||
eq(other: LayerMarker): boolean;
|
||||
/**
|
||||
Draw the marker to the DOM.
|
||||
*/
|
||||
draw(): HTMLElement;
|
||||
/**
|
||||
Update an existing marker of this type to this marker.
|
||||
*/
|
||||
update?(dom: HTMLElement, oldMarker: LayerMarker): boolean;
|
||||
}
|
||||
/**
|
||||
Implementation of [`LayerMarker`](https://codemirror.net/6/docs/ref/#view.LayerMarker) that creates
|
||||
a rectangle at a given set of coordinates.
|
||||
*/
|
||||
declare class RectangleMarker implements LayerMarker {
|
||||
private className;
|
||||
private left;
|
||||
private top;
|
||||
private width;
|
||||
private height;
|
||||
/**
|
||||
Create a marker with the given class and dimensions. If `width`
|
||||
is null, the DOM element will get no width style.
|
||||
*/
|
||||
constructor(className: string, left: number, top: number, width: number | null, height: number);
|
||||
draw(): HTMLDivElement;
|
||||
update(elt: HTMLElement, prev: RectangleMarker): boolean;
|
||||
private adjust;
|
||||
eq(p: RectangleMarker): boolean;
|
||||
/**
|
||||
Create a set of rectangles for the given selection range,
|
||||
assigning them theclass`className`. Will create a single
|
||||
rectangle for empty ranges, and a set of selection-style
|
||||
rectangles covering the range's content (in a bidi-aware
|
||||
way) for non-empty ones.
|
||||
*/
|
||||
static forRange(view: EditorView, className: string, range: SelectionRange): readonly RectangleMarker[];
|
||||
}
|
||||
interface LayerConfig {
|
||||
/**
|
||||
Determines whether this layer is shown above or below the text.
|
||||
*/
|
||||
above: boolean;
|
||||
/**
|
||||
When given, this class is added to the DOM element that will
|
||||
wrap the markers.
|
||||
*/
|
||||
class?: string;
|
||||
/**
|
||||
Called on every view update. Returning true triggers a marker
|
||||
update (a call to `markers` and drawing of those markers).
|
||||
*/
|
||||
update(update: ViewUpdate, layer: HTMLElement): boolean;
|
||||
/**
|
||||
Build a set of markers for this layer, and measure their
|
||||
dimensions.
|
||||
*/
|
||||
markers(view: EditorView): readonly LayerMarker[];
|
||||
/**
|
||||
If given, this is called when the layer is created.
|
||||
*/
|
||||
mount?(layer: HTMLElement, view: EditorView): void;
|
||||
/**
|
||||
If given, called when the layer is removed from the editor or
|
||||
the entire editor is destroyed.
|
||||
*/
|
||||
destroy?(layer: HTMLElement, view: EditorView): void;
|
||||
}
|
||||
/**
|
||||
Define a layer.
|
||||
*/
|
||||
declare function layer(config: LayerConfig): Extension;
|
||||
|
||||
/**
|
||||
Helper class used to make it easier to maintain decorations on
|
||||
visible code that matches a given regular expression. To be used
|
||||
|
@ -1357,7 +1462,7 @@ represent a matching configuration.
|
|||
*/
|
||||
declare class MatchDecorator {
|
||||
private regexp;
|
||||
private getDeco;
|
||||
private addMatch;
|
||||
private boundary;
|
||||
private maxLength;
|
||||
/**
|
||||
|
@ -1374,7 +1479,18 @@ declare class MatchDecorator {
|
|||
The decoration to apply to matches, either directly or as a
|
||||
function of the match.
|
||||
*/
|
||||
decoration: Decoration | ((match: RegExpExecArray, view: EditorView, pos: number) => Decoration);
|
||||
decoration?: Decoration | ((match: RegExpExecArray, view: EditorView, pos: number) => Decoration | null);
|
||||
/**
|
||||
Customize the way decorations are added for matches. This
|
||||
function, when given, will be called for matches and should
|
||||
call `add` to create decorations for them. Note that the
|
||||
decorations should appear *in* the given range, and the
|
||||
function should have no side effects beyond calling `add`.
|
||||
|
||||
The `decoration` option is ignored when `decorate` is
|
||||
provided.
|
||||
*/
|
||||
decorate?: (add: (from: number, to: number, decoration: Decoration) => void, from: number, to: number, match: RegExpExecArray, view: EditorView) => void;
|
||||
/**
|
||||
By default, changed lines are re-matched entirely. You can
|
||||
provide a boundary expression, which should match single
|
||||
|
@ -1463,12 +1579,7 @@ declare function tooltips(config?: {
|
|||
for showing tooltips. You can provide a function here that
|
||||
returns an alternative rectangle.
|
||||
*/
|
||||
tooltipSpace?: (view: EditorView) => {
|
||||
top: number;
|
||||
left: number;
|
||||
bottom: number;
|
||||
right: number;
|
||||
};
|
||||
tooltipSpace?: (view: EditorView) => Rect;
|
||||
}): Extension;
|
||||
/**
|
||||
Describes a tooltip. Values of this type, when provided through
|
||||
|
@ -1551,9 +1662,22 @@ interface TooltipView {
|
|||
*/
|
||||
update?(update: ViewUpdate): void;
|
||||
/**
|
||||
Called when the tooltip has been (re)positioned.
|
||||
Called when the tooltip is removed from the editor or the editor
|
||||
is destroyed.
|
||||
*/
|
||||
positioned?(): void;
|
||||
destroy?(): void;
|
||||
/**
|
||||
Called when the tooltip has been (re)positioned. The argument is
|
||||
the [space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace) available to the
|
||||
tooltip.
|
||||
*/
|
||||
positioned?(space: Rect): void;
|
||||
/**
|
||||
By default, the library will restrict the size of tooltips so
|
||||
that they don't stick out of the available space. Set this to
|
||||
false to disable that.
|
||||
*/
|
||||
resize?: boolean;
|
||||
}
|
||||
/**
|
||||
Facet to which an extension can add a value to show a tooltip.
|
||||
|
@ -1790,4 +1914,17 @@ line](https://codemirror.net/6/docs/ref/#view.highlightActiveLine).
|
|||
*/
|
||||
declare function highlightActiveLineGutter(): Extension;
|
||||
|
||||
export { BidiSpan, BlockInfo, BlockType, Command, DOMEventHandlers, DOMEventMap, Decoration, DecorationSet, Direction, EditorView, EditorViewConfig, GutterMarker, KeyBinding, MatchDecorator, MouseSelectionStyle, Panel, PanelConstructor, PluginSpec, PluginValue, Rect, Tooltip, TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, hoverTooltip, keymap, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
||||
/**
|
||||
Returns an extension that highlights whitespace, adding a
|
||||
`cm-highlightSpace` class to stretches of spaces, and a
|
||||
`cm-highlightTab` class to individual tab characters. By default,
|
||||
the former are shown as faint dots, and the latter as arrows.
|
||||
*/
|
||||
declare function highlightWhitespace(): Extension;
|
||||
/**
|
||||
Returns an extension that adds a `cm-trailingSpace` class to all
|
||||
trailing whitespace.
|
||||
*/
|
||||
declare function highlightTrailingWhitespace(): Extension;
|
||||
|
||||
export { BidiSpan, BlockInfo, BlockType, Command, DOMEventHandlers, DOMEventMap, Decoration, DecorationSet, Direction, EditorView, EditorViewConfig, GutterMarker, KeyBinding, LayerMarker, MatchDecorator, MouseSelectionStyle, Panel, PanelConstructor, PluginSpec, PluginValue, Rect, RectangleMarker, Tooltip, TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
||||
|
|
2506
node_modules/@codemirror/view/dist/index.js
generated
vendored
2506
node_modules/@codemirror/view/dist/index.js
generated
vendored
File diff suppressed because it is too large
Load diff
6
node_modules/@codemirror/view/package.json
generated
vendored
6
node_modules/@codemirror/view/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@codemirror/view",
|
||||
"version": "6.0.0",
|
||||
"version": "6.8.1",
|
||||
"description": "DOM view component for the CodeMirror code editor",
|
||||
"scripts": {
|
||||
"test": "cm-runtests",
|
||||
|
@ -12,7 +12,7 @@
|
|||
],
|
||||
"author": {
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijnh@gmail.com",
|
||||
"email": "marijn@haverbeke.berlin",
|
||||
"url": "http://marijnhaverbeke.nl"
|
||||
},
|
||||
"type": "module",
|
||||
|
@ -26,7 +26,7 @@
|
|||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/state": "^6.1.4",
|
||||
"style-mod": "^4.0.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue