1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-05 02:39:46 +02:00

npm update

This commit is contained in:
Daniel Neto 2023-08-12 10:32:47 -03:00
parent 0cdd3e9fee
commit 4696ba952f
1437 changed files with 32727 additions and 1248226 deletions

View file

@ -1,5 +1,5 @@
import { Annotation, EditorSelection, codePointAt, codePointSize, fromCodePoint, Facet, combineConfig, StateEffect, StateField, Prec, Text, MapMode, RangeValue, RangeSet, CharCategory } from '@codemirror/state';
import { logException, Direction, showTooltip, EditorView, ViewPlugin, getTooltip, Decoration, WidgetType, keymap } from '@codemirror/view';
import { Annotation, StateEffect, EditorSelection, codePointAt, codePointSize, fromCodePoint, Facet, combineConfig, StateField, Prec, Text, MapMode, RangeValue, RangeSet, CharCategory } from '@codemirror/state';
import { Direction, logException, showTooltip, EditorView, ViewPlugin, getTooltip, Decoration, WidgetType, keymap } from '@codemirror/view';
import { syntaxTree, indentUnit } from '@codemirror/language';
/**
@ -108,9 +108,12 @@ cursor is in a syntax node with one of the given names.
*/
function ifIn(nodes, source) {
return (context) => {
for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) {
if (nodes.indexOf(pos.name) > -1)
return source(context);
if (pos.type.isTop)
break;
}
return null;
};
}
@ -120,20 +123,24 @@ cursor is in a syntax node with one of the given names.
*/
function ifNotIn(nodes, source) {
return (context) => {
for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) {
if (nodes.indexOf(pos.name) > -1)
return null;
if (pos.type.isTop)
break;
}
return source(context);
};
}
class Option {
constructor(completion, source, match) {
constructor(completion, source, match, score) {
this.completion = completion;
this.source = source;
this.match = match;
this.score = score;
}
}
function cur(state) { return state.selection.main.head; }
function cur(state) { return state.selection.main.from; }
// Make sure the given regexp has a $ at its end and, if `start` is
// true, a ^ at its start.
function ensureAnchor(expr, start) {
@ -155,30 +162,17 @@ completion's text in the main selection range, and any other
selection range that has the same text in front of it.
*/
function insertCompletionText(state, text, from, to) {
let { main } = state.selection, fromOff = from - main.from, toOff = to - main.from;
return Object.assign(Object.assign({}, state.changeByRange(range => {
if (range == state.selection.main)
return {
changes: { from: from, to: to, insert: text },
range: EditorSelection.cursor(from + text.length)
};
let len = to - from;
if (!range.empty ||
len && state.sliceDoc(range.from - len, range.from) != state.sliceDoc(from, to))
if (range != main && from != to &&
state.sliceDoc(range.from + fromOff, range.from + toOff) != state.sliceDoc(from, to))
return { range };
return {
changes: { from: range.from - len, to: range.from, insert: text },
range: EditorSelection.cursor(range.from - len + text.length)
changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
range: EditorSelection.cursor(range.from + fromOff + text.length)
};
})), { userEvent: "input.complete" });
}
function applyCompletion(view, option) {
const apply = option.completion.apply || option.completion.label;
let result = option.source;
if (typeof apply == "string")
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);
}
const SourceCache = /*@__PURE__*/new WeakMap();
function asSource(source) {
if (!Array.isArray(source))
@ -188,6 +182,8 @@ function asSource(source) {
SourceCache.set(source, known = completeFromList(source));
return known;
}
const startCompletionEffect = /*@__PURE__*/StateEffect.define();
const closeCompletionEffect = /*@__PURE__*/StateEffect.define();
// A pattern matcher for fuzzy completion matching. Create an instance
// once for a pattern, and then use that to match any number of
@ -202,6 +198,8 @@ class FuzzyMatcher {
this.any = [];
this.precise = [];
this.byWord = [];
this.score = 0;
this.matched = [];
for (let p = 0; p < pattern.length;) {
let char = codePointAt(pattern, p), size = codePointSize(char);
this.chars.push(char);
@ -211,29 +209,39 @@ class FuzzyMatcher {
}
this.astral = pattern.length != this.chars.length;
}
ret(score, matched) {
this.score = score;
this.matched = matched;
return true;
}
// Matches a given word (completion) against the pattern (input).
// Will return null for no match, and otherwise an array that starts
// with the match score, followed by any number of `from, to` pairs
// indicating the matched parts of `word`.
// Will return a boolean indicating whether there was a match and,
// on success, set `this.score` to the score, `this.matched` to an
// array of `from, to` pairs indicating the matched parts of `word`.
//
// The score is a number that is more negative the worse the match
// is. See `Penalty` above.
match(word) {
if (this.pattern.length == 0)
return [0];
return this.ret(-100 /* NotFull */, []);
if (word.length < this.pattern.length)
return null;
return false;
let { chars, folded, any, precise, byWord } = this;
// For single-character queries, only match when they occur right
// at the start
if (chars.length == 1) {
let first = codePointAt(word, 0);
return first == chars[0] ? [0, 0, codePointSize(first)]
: first == folded[0] ? [-200 /* Penalty.CaseFold */, 0, codePointSize(first)] : null;
let first = codePointAt(word, 0), firstSize = codePointSize(first);
let score = firstSize == word.length ? 0 : -100 /* NotFull */;
if (first == chars[0]) ;
else if (first == folded[0])
score += -200 /* CaseFold */;
else
return false;
return this.ret(score, [0, firstSize]);
}
let direct = word.indexOf(this.pattern);
if (direct == 0)
return [0, 0, this.pattern.length];
return this.ret(word.length == this.pattern.length ? 0 : -100 /* NotFull */, [0, this.pattern.length]);
let len = chars.length, anyTo = 0;
if (direct < 0) {
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
@ -244,7 +252,7 @@ class FuzzyMatcher {
}
// No match, exit immediately
if (anyTo < len)
return null;
return false;
}
// This tracks the extent of the precise (non-folded, not
// necessarily adjacent) match
@ -257,7 +265,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 /* Tp.NonWord */; i < e && byWordTo < len;) {
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
let next = codePointAt(word, i);
if (direct < 0) {
if (preciseTo < len && next == chars[preciseTo])
@ -275,9 +283,9 @@ class FuzzyMatcher {
}
}
let ch, type = next < 0xff
? (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 */) {
? (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 */) {
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
byWord[byWordTo++] = i;
else if (byWord.length)
@ -287,30 +295,31 @@ class FuzzyMatcher {
i += codePointSize(next);
}
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
if (adjacentTo == len && adjacentStart == 0)
return [-200 /* Penalty.CaseFold */ - word.length, 0, adjacentEnd];
return this.ret(-200 /* CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* NotFull */), [0, adjacentEnd]);
if (direct > -1)
return [-700 /* Penalty.NotStart */ - word.length, direct, direct + this.pattern.length];
return this.ret(-700 /* NotStart */ - word.length, [direct, direct + this.pattern.length]);
if (adjacentTo == len)
return [-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, adjacentStart, adjacentEnd];
return this.ret(-200 /* CaseFold */ + -700 /* NotStart */ - word.length, [adjacentStart, adjacentEnd]);
if (byWordTo == len)
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);
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
return chars.length == 2 ? false
: this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
}
result(score, positions, word) {
let result = [score - word.length], i = 1;
let result = [], i = 0;
for (let pos of positions) {
let to = pos + (this.astral ? codePointSize(codePointAt(word, pos)) : 1);
if (i > 1 && result[i - 1] == pos)
if (i && result[i - 1] == pos)
result[i - 1] = to;
else {
result[i++] = pos;
result[i++] = to;
}
}
return result;
return this.ret(score - word.length, result);
}
}
@ -328,6 +337,7 @@ const completionConfig = /*@__PURE__*/Facet.define({
aboveCursor: false,
icons: true,
addToOptions: [],
positionInfo: defaultPositionInfo,
compareCompletions: (a, b) => a.label.localeCompare(b.label),
interactionDelay: 75
}, {
@ -343,6 +353,36 @@ const completionConfig = /*@__PURE__*/Facet.define({
function joinClass(a, b) {
return a ? b ? a + " " + b : a : b;
}
function defaultPositionInfo(view, list, option, info, space) {
let rtl = view.textDirection == Direction.RTL, left = rtl, narrow = false;
let side = "top", offset, maxWidth;
let spaceLeft = list.left - space.left, spaceRight = space.right - list.right;
let infoWidth = info.right - info.left, infoHeight = info.bottom - info.top;
if (left && spaceLeft < Math.min(infoWidth, spaceRight))
left = false;
else if (!left && spaceRight < Math.min(infoWidth, spaceLeft))
left = true;
if (infoWidth <= (left ? spaceLeft : spaceRight)) {
offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
}
else {
narrow = true;
maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
let spaceBelow = space.bottom - list.bottom;
if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
offset = option.bottom - list.top;
}
else { // Above it
side = "bottom";
offset = list.bottom - option.top;
}
}
return {
style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right")
};
}
function optionContent(config) {
let content = config.addToOptions.slice();
@ -362,8 +402,8 @@ function optionContent(config) {
render(completion, _s, match) {
let labelElt = document.createElement("span");
labelElt.className = "cm-completionLabel";
let { label } = completion, off = 0;
for (let j = 1; j < match.length;) {
let label = completion.displayLabel || completion.label, off = 0;
for (let j = 0; j < match.length;) {
let from = match[j++], to = match[j++];
if (from > off)
labelElt.appendChild(document.createTextNode(label.slice(off, from)));
@ -403,13 +443,15 @@ function rangeAroundSelected(total, selected, max) {
return { from: total - (off + 1) * max, to: total - off * max };
}
class CompletionTooltip {
constructor(view, stateField) {
constructor(view, stateField, applyCompletion) {
this.view = view;
this.stateField = stateField;
this.applyCompletion = applyCompletion;
this.info = null;
this.placeInfo = {
this.infoDestroy = null;
this.placeInfoReq = {
read: () => this.measureInfo(),
write: (pos) => this.positionInfo(pos),
write: (pos) => this.placeInfo(pos),
key: this
};
this.space = null;
@ -427,16 +469,22 @@ class CompletionTooltip {
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) {
applyCompletion(view, options[+match[1]]);
this.applyCompletion(view, options[+match[1]]);
e.preventDefault();
return;
}
}
});
this.dom.addEventListener("focusout", (e) => {
let state = view.state.field(this.stateField, false);
if (state && state.tooltip && view.state.facet(completionConfig).closeOnBlur &&
e.relatedTarget != view.contentDOM)
view.dispatch({ effects: closeCompletionEffect.of(null) });
});
this.list = this.dom.appendChild(this.createListBox(options, cState.id, this.range));
this.list.addEventListener("scroll", () => {
if (this.info)
this.view.requestMeasure(this.placeInfo);
this.view.requestMeasure(this.placeInfoReq);
});
}
mount() { this.updateSel(); }
@ -466,7 +514,7 @@ class CompletionTooltip {
positioned(space) {
this.space = space;
if (this.info)
this.view.requestMeasure(this.placeInfo);
this.view.requestMeasure(this.placeInfoReq);
}
updateSel() {
let cState = this.view.state.field(this.stateField), open = cState.open;
@ -476,43 +524,52 @@ class CompletionTooltip {
this.list = this.dom.appendChild(this.createListBox(open.options, cState.id, this.range));
this.list.addEventListener("scroll", () => {
if (this.info)
this.view.requestMeasure(this.placeInfo);
this.view.requestMeasure(this.placeInfoReq);
});
}
if (this.updateSelectedOption(open.selected)) {
if (this.info) {
this.info.remove();
this.info = null;
}
this.destroyInfo();
let { completion } = open.options[open.selected];
let { info } = completion;
if (!info)
return;
let infoResult = typeof info === 'string' ? document.createTextNode(info) : info(completion);
let infoResult = typeof info === "string" ? document.createTextNode(info) : info(completion);
if (!infoResult)
return;
if ('then' in infoResult) {
infoResult.then(node => {
if (node && this.view.state.field(this.stateField, false) == cState)
this.addInfoPane(node);
if ("then" in infoResult) {
infoResult.then(obj => {
if (obj && this.view.state.field(this.stateField, false) == cState)
this.addInfoPane(obj, completion);
}).catch(e => logException(this.view.state, e, "completion info"));
}
else {
this.addInfoPane(infoResult);
this.addInfoPane(infoResult, completion);
}
}
}
addInfoPane(content) {
let dom = this.info = document.createElement("div");
dom.className = "cm-tooltip cm-completionInfo";
dom.appendChild(content);
this.dom.appendChild(dom);
this.view.requestMeasure(this.placeInfo);
addInfoPane(content, completion) {
this.destroyInfo();
let wrap = this.info = document.createElement("div");
wrap.className = "cm-tooltip cm-completionInfo";
if (content.nodeType != null) {
wrap.appendChild(content);
this.infoDestroy = null;
}
else {
let { dom, destroy } = content;
wrap.appendChild(dom);
this.infoDestroy = destroy || null;
}
this.dom.appendChild(wrap);
this.view.requestMeasure(this.placeInfoReq);
}
updateSelectedOption(selected) {
let set = null;
for (let opt = this.list.firstChild, i = this.range.from; opt; opt = opt.nextSibling, i++) {
if (i == selected) {
if (opt.nodeName != "LI" || !opt.id) {
i--; // A section header
}
else if (i == selected) {
if (!opt.hasAttribute("aria-selected")) {
opt.setAttribute("aria-selected", "true");
set = opt;
@ -542,41 +599,17 @@ class CompletionTooltip {
if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
selRect.bottom < Math.max(space.top, listRect.top) + 10)
return null;
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;
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",
};
return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space);
}
positionInfo(pos) {
placeInfo(pos) {
if (this.info) {
if (pos) {
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;
if (pos.style)
this.info.style.cssText = pos.style;
this.info.className = "cm-tooltip cm-completionInfo " + (pos.class || "");
}
else {
this.info.style.top = "-1e6px";
this.info.style.cssText = "top: -1e6px";
}
}
}
@ -586,8 +619,22 @@ class CompletionTooltip {
ul.setAttribute("role", "listbox");
ul.setAttribute("aria-expanded", "true");
ul.setAttribute("aria-label", this.view.state.phrase("Completions"));
let curSection = null;
for (let i = range.from; i < range.to; i++) {
let { completion, match } = options[i];
let { completion, match } = options[i], { section } = completion;
if (section) {
let name = typeof section == "string" ? section : section.name;
if (name != curSection && (i > range.from || range.from == 0)) {
curSection = name;
if (typeof section != "string" && section.header) {
ul.appendChild(section.header(section));
}
else {
let header = ul.appendChild(document.createElement("completion-section"));
header.textContent = name;
}
}
}
const li = ul.appendChild(document.createElement("li"));
li.id = id + "-" + i;
li.setAttribute("role", "option");
@ -606,11 +653,22 @@ class CompletionTooltip {
ul.classList.add("cm-completionListIncompleteBottom");
return ul;
}
destroyInfo() {
if (this.info) {
if (this.infoDestroy)
this.infoDestroy();
this.info.remove();
this.info = null;
}
}
destroy() {
this.destroyInfo();
}
}
// We allocate a new function instance every time the completion
// changes to force redrawing/repositioning of the tooltip
function completionTooltip(stateField) {
return (view) => new CompletionTooltip(view, stateField);
function completionTooltip(stateField, applyCompletion) {
return (view) => new CompletionTooltip(view, stateField, applyCompletion);
}
function scrollIntoView(container, element) {
let parent = container.getBoundingClientRect();
@ -628,35 +686,56 @@ function score(option) {
(option.type ? 1 : 0);
}
function sortOptions(active, state) {
let options = [], i = 0;
let options = [];
let sections = null;
let addOption = (option) => {
options.push(option);
let { section } = option.completion;
if (section) {
if (!sections)
sections = [];
let name = typeof section == "string" ? section : section.name;
if (!sections.some(s => s.name == name))
sections.push(typeof section == "string" ? { name } : section);
}
};
for (let a of active)
if (a.hasResult()) {
let getMatch = a.result.getMatch;
if (a.result.filter === false) {
let getMatch = a.result.getMatch;
for (let option of a.result.options) {
let match = [1e9 - i++];
if (getMatch)
for (let n of getMatch(option))
match.push(n);
options.push(new Option(option, a, match));
addOption(new Option(option, a.source, getMatch ? getMatch(option) : [], 1e9 - options.length));
}
}
else {
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to)), match;
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to));
for (let option of a.result.options)
if (match = matcher.match(option.label)) {
if (option.boost != null)
match[0] += option.boost;
options.push(new Option(option, a, match));
if (matcher.match(option.label)) {
let matched = !option.displayLabel ? matcher.matched : getMatch ? getMatch(option, matcher.matched) : [];
addOption(new Option(option, a.source, matched, matcher.score + (option.boost || 0)));
}
}
}
if (sections) {
let sectionOrder = Object.create(null), pos = 0;
let cmp = (a, b) => { var _a, _b; return ((_a = a.rank) !== null && _a !== void 0 ? _a : 1e9) - ((_b = b.rank) !== null && _b !== void 0 ? _b : 1e9) || (a.name < b.name ? -1 : 1); };
for (let s of sections.sort(cmp)) {
pos -= 1e5;
sectionOrder[s.name] = pos;
}
for (let option of options) {
let { section } = option.completion;
if (section)
option.score += sectionOrder[typeof section == "string" ? section : section.name];
}
}
let result = [], prev = null;
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)
for (let opt of options.sort((a, b) => (b.score - a.score) || compare(a.completion, b.completion))) {
let cur = opt.completion;
if (!prev || prev.label != cur.label || prev.detail != cur.detail ||
(prev.type != null && cur.type != null && prev.type != cur.type) ||
prev.apply != cur.apply || prev.boost != cur.boost)
result.push(opt);
else if (score(opt.completion) > score(prev))
result[result.length - 1] = opt;
@ -680,7 +759,7 @@ class CompletionDialog {
static build(active, state, id, prev, conf) {
let options = sortOptions(active, state);
if (!options.length) {
return prev && active.some(a => a.state == 1 /* State.Pending */) ?
return prev && active.some(a => a.state == 1 /* Pending */) ?
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
}
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
@ -694,7 +773,7 @@ class CompletionDialog {
}
return new CompletionDialog(options, makeAttrs(id, selected), {
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
create: completionTooltip(completionState),
create: completionTooltip(completionState, applyCompletion),
above: conf.aboveCursor,
}, prev ? prev.timestamp : Date.now(), selected, false);
}
@ -717,7 +796,7 @@ 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 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
return value.update(tr, conf);
});
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
@ -728,10 +807,10 @@ class CompletionState {
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 */))
else if (open && open.disabled && !active.some(a => a.state == 1 /* 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);
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);
for (let effect of tr.effects)
if (effect.is(setSelectedEffect))
open = open && open.setSelected(effect.value, this.id);
@ -785,13 +864,13 @@ class ActiveSource {
value = value.handleUserEvent(tr, event, conf);
else if (tr.docChanged)
value = value.handleChange(tr);
else if (tr.selection && value.state != 0 /* State.Inactive */)
value = new ActiveSource(value.source, 0 /* State.Inactive */);
else if (tr.selection && value.state != 0 /* Inactive */)
value = new ActiveSource(value.source, 0 /* Inactive */);
for (let effect of tr.effects) {
if (effect.is(startCompletionEffect))
value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
else if (effect.is(closeCompletionEffect))
value = new ActiveSource(value.source, 0 /* State.Inactive */);
value = new ActiveSource(value.source, 0 /* Inactive */);
else if (effect.is(setActiveEffect))
for (let active of effect.value)
if (active.source == value.source)
@ -800,10 +879,10 @@ class ActiveSource {
return value;
}
handleUserEvent(tr, type, conf) {
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
}
handleChange(tr) {
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
}
map(changes) {
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
@ -811,7 +890,7 @@ class ActiveSource {
}
class ActiveResult extends ActiveSource {
constructor(source, explicitPos, result, from, to) {
super(source, 2 /* State.Result */, explicitPos);
super(source, 2 /* Result */, explicitPos);
this.result = result;
this.from = from;
this.to = to;
@ -824,17 +903,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 /* State.Pending */ : 0 /* State.Inactive */);
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* 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 /* State.Pending */, explicitPos);
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
}
handleChange(tr) {
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
}
map(mapping) {
return mapping.empty ? this :
@ -847,8 +926,6 @@ function checkValid(validFor, state, from, to) {
let text = state.sliceDoc(from, to);
return typeof validFor == "function" ? validFor(text, from, to, state) : ensureAnchor(validFor, true).test(text);
}
const startCompletionEffect = /*@__PURE__*/StateEffect.define();
const closeCompletionEffect = /*@__PURE__*/StateEffect.define();
const setActiveEffect = /*@__PURE__*/StateEffect.define({
map(sources, mapping) { return sources.map(s => s.map(mapping)); }
});
@ -861,6 +938,17 @@ const completionState = /*@__PURE__*/StateField.define({
EditorView.contentAttributes.from(f, state => state.attrs)
]
});
function applyCompletion(view, option) {
const apply = option.completion.apply || option.completion.label;
let result = view.state.field(completionState).active.find(a => a.source == option.source);
if (!(result instanceof ActiveResult))
return false;
if (typeof apply == "string")
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);
return true;
}
/**
Returns a command that moves the completion selection forward or
@ -891,12 +979,10 @@ Accept the current completion.
*/
const acceptCompletion = (view) => {
let cState = view.state.field(completionState, false);
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 || cState.open.disabled ||
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
return false;
if (!cState.open.disabled)
applyCompletion(view, cState.open.options[cState.open.selected]);
return true;
return applyCompletion(view, cState.open.options[cState.open.selected]);
};
/**
Explicitly start autocompletion.
@ -913,7 +999,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 /* State.Inactive */))
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
return false;
view.dispatch({ effects: closeCompletionEffect.of(null) });
return true;
@ -936,9 +1022,9 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
this.debounceUpdate = -1;
this.running = [];
this.debounceAccept = -1;
this.composing = 0 /* CompositionState.None */;
this.composing = 0 /* None */;
for (let active of view.state.field(completionState).active)
if (active.state == 1 /* State.Pending */)
if (active.state == 1 /* Pending */)
this.startQuery(active);
}
update(update) {
@ -969,21 +1055,21 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
}
if (this.debounceUpdate > -1)
clearTimeout(this.debounceUpdate);
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
if (this.composing != 0 /* CompositionState.None */)
if (this.composing != 0 /* None */)
for (let tr of update.transactions) {
if (getUserEvent(tr) == "input")
this.composing = 2 /* CompositionState.Changed */;
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
this.composing = 3 /* CompositionState.ChangedAndMoved */;
this.composing = 2 /* Changed */;
else if (this.composing == 2 /* Changed */ && tr.selection)
this.composing = 3 /* ChangedAndMoved */;
}
}
startUpdate() {
this.debounceUpdate = -1;
let { state } = this.view, cState = state.field(completionState);
for (let active of cState.active) {
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
this.startQuery(active);
}
}
@ -1034,14 +1120,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 /* State.Pending */) {
if (current && current.state == 1 /* 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 /* State.Inactive */);
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
for (let tr of query.updates)
active = active.update(tr, conf);
if (active.state != 1 /* State.Pending */)
if (active.state != 1 /* Pending */)
updated.push(active);
}
else {
@ -1055,21 +1141,24 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
}
}, {
eventHandlers: {
blur() {
blur(event) {
let state = this.view.state.field(completionState, false);
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur)
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
let dialog = state.open && getTooltip(this.view, state.open.tooltip);
if (!dialog || !dialog.dom.contains(event.relatedTarget))
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
}
},
compositionstart() {
this.composing = 1 /* CompositionState.Started */;
this.composing = 1 /* Started */;
},
compositionend() {
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
if (this.composing == 3 /* 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 /* CompositionState.None */;
this.composing = 0 /* None */;
}
}
});
@ -1088,13 +1177,21 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
listStyle: "none",
margin: 0,
padding: 0,
"& > li": {
overflowX: "hidden",
textOverflow: "ellipsis",
cursor: "pointer",
"& > li, & > completion-section": {
padding: "1px 3px",
lineHeight: 1.2
},
"& > li": {
overflowX: "hidden",
textOverflow: "ellipsis",
cursor: "pointer"
},
"& > completion-section": {
display: "list-item",
borderBottom: "1px solid silver",
paddingLeft: "0.5em",
opacity: 0.7
}
}
},
"&light .cm-tooltip-autocomplete ul li[aria-selected]": {
@ -1121,13 +1218,13 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
position: "absolute",
padding: "3px 9px",
width: "max-content",
maxWidth: `${400 /* Info.Width */}px`,
maxWidth: `${400 /* 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` },
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
"&light .cm-snippetField": { backgroundColor: "#00000022" },
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
".cm-snippetFieldPosition": {
@ -1352,11 +1449,12 @@ interpreted as indicating a placeholder.
*/
function snippet(template) {
let snippet = Snippet.parse(template);
return (editor, _completion, from, to) => {
return (editor, completion, from, to) => {
let { text, ranges } = snippet.instantiate(editor.state, from);
let spec = {
changes: { from, to, insert: Text.of(text) },
scrollIntoView: true
scrollIntoView: true,
annotations: completion ? pickedCompletion.of(completion) : undefined
};
if (ranges.length)
spec.selection = fieldSelection(ranges, 0);
@ -1400,6 +1498,22 @@ const nextSnippetField = /*@__PURE__*/moveField(1);
Move to the previous snippet field, if available.
*/
const prevSnippetField = /*@__PURE__*/moveField(-1);
/**
Check if there is an active snippet with a next field for
`nextSnippetField` to move to.
*/
function hasNextSnippetField(state) {
let active = state.field(snippetState, false);
return !!(active && active.ranges.some(r => r.field == active.active + 1));
}
/**
Returns true if there is an active snippet and a previous field
for `prevSnippetField` to move to.
*/
function hasPrevSnippetField(state) {
let active = state.field(snippetState, false);
return !!(active && active.active > 0);
}
const defaultSnippetKeymap = [
{ key: "Tab", run: nextSnippetField, shift: prevSnippetField },
{ key: "Escape", run: clearSnippet }
@ -1463,7 +1577,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 /* C.MaxList */)
if (result.length >= 2000 /* MaxList */)
return;
}
}
@ -1471,7 +1585,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
}
}
function collectWords(doc, cache, wordRE, to, ignoreAt) {
let big = doc.length >= 1000 /* C.MinCacheLen */;
let big = doc.length >= 1000 /* MinCacheLen */;
let cached = big && cache.get(doc);
if (cached)
return cached;
@ -1479,7 +1593,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
if (doc.children) {
let pos = 0;
for (let ch of doc.children) {
if (ch.length >= 1000 /* C.MinCacheLen */) {
if (ch.length >= 1000 /* MinCacheLen */) {
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
if (!seen[c.label]) {
seen[c.label] = true;
@ -1496,7 +1610,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
else {
storeWords(doc, wordRE, result, seen, ignoreAt);
}
if (big && result.length < 2000 /* C.MaxList */)
if (big && result.length < 2000 /* MaxList */)
cache.set(doc, result);
return result;
}
@ -1512,7 +1626,7 @@ 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 /* C.Range */, from);
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
return { from, options, validFor: mapRE(re, s => "^" + s) };
};
@ -1527,9 +1641,6 @@ const closeBracketEffect = /*@__PURE__*/StateEffect.define({
return mapped == null ? undefined : mapped;
}
});
const skipBracketEffect = /*@__PURE__*/StateEffect.define({
map(value, mapping) { return mapping.mapPos(value); }
});
const closedBracket = /*@__PURE__*/new class extends RangeValue {
};
closedBracket.startSide = 1;
@ -1544,12 +1655,9 @@ const bracketState = /*@__PURE__*/StateField.define({
value = RangeSet.empty;
}
value = value.map(tr.changes);
for (let effect of tr.effects) {
for (let effect of tr.effects)
if (effect.is(closeBracketEffect))
value = value.update({ add: [closedBracket.range(effect.value, effect.value + 1)] });
else if (effect.is(skipBracketEffect))
value = value.update({ filter: from => from != effect.value });
}
return value;
}
});
@ -1677,15 +1785,15 @@ function handleOpen(state, open, close, closeBefore) {
});
}
function handleClose(state, _open, close) {
let dont = null, moved = state.selection.ranges.map(range => {
let dont = null, changes = state.changeByRange(range => {
if (range.empty && nextChar(state.doc, range.head) == close)
return EditorSelection.cursor(range.head + close.length);
return dont = range;
return { changes: { from: range.head, to: range.head + close.length, insert: close },
range: EditorSelection.cursor(range.head + close.length) };
return dont = { range };
});
return dont ? null : state.update({
selection: EditorSelection.create(moved, state.selection.mainIndex),
return dont ? null : state.update(changes, {
scrollIntoView: true,
effects: state.selection.ranges.map(({ from }) => skipBracketEffect.of(from))
userEvent: "input.type"
});
}
// Handles cases where the open and close token are the same, and
@ -1706,8 +1814,9 @@ function handleSame(state, token, allowTriple, config) {
}
else if (closedBracketAt(state, pos)) {
let isTriple = allowTriple && state.sliceDoc(pos, pos + token.length * 3) == token + token + token;
return { range: EditorSelection.cursor(pos + token.length * (isTriple ? 3 : 1)),
effects: skipBracketEffect.of(pos) };
let content = isTriple ? token + token + token : token;
return { changes: { from: pos, to: pos + content.length, insert: content },
range: EditorSelection.cursor(pos + content.length) };
}
}
else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token &&
@ -1809,8 +1918,8 @@ returns `null`.
*/
function completionStatus(state) {
let cState = state.field(completionState, false);
return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
: cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
}
const completionArrayCache = /*@__PURE__*/new WeakMap;
/**
@ -1851,4 +1960,4 @@ function setSelectedCompletion(index) {
return setSelectedEffect.of(index);
}
export { CompletionContext, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, ifIn, ifNotIn, insertBracket, insertCompletionText, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
export { CompletionContext, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, hasNextSnippetField, hasPrevSnippetField, ifIn, ifNotIn, insertBracket, insertCompletionText, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };