@codemirror/autocomplete 6.7.1 → 6.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.cjs +309 -291
- package/dist/index.d.cts +557 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.js +310 -292
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -220,7 +220,7 @@ class FuzzyMatcher {
|
|
|
220
220
|
// is. See `Penalty` above.
|
|
221
221
|
match(word) {
|
|
222
222
|
if (this.pattern.length == 0)
|
|
223
|
-
return [-100 /*
|
|
223
|
+
return [-100 /* NotFull */];
|
|
224
224
|
if (word.length < this.pattern.length)
|
|
225
225
|
return null;
|
|
226
226
|
let { chars, folded, any, precise, byWord } = this;
|
|
@@ -228,17 +228,17 @@ class FuzzyMatcher {
|
|
|
228
228
|
// at the start
|
|
229
229
|
if (chars.length == 1) {
|
|
230
230
|
let first = state.codePointAt(word, 0), firstSize = state.codePointSize(first);
|
|
231
|
-
let score = firstSize == word.length ? 0 : -100 /*
|
|
231
|
+
let score = firstSize == word.length ? 0 : -100 /* NotFull */;
|
|
232
232
|
if (first == chars[0]) ;
|
|
233
233
|
else if (first == folded[0])
|
|
234
|
-
score += -200 /*
|
|
234
|
+
score += -200 /* CaseFold */;
|
|
235
235
|
else
|
|
236
236
|
return null;
|
|
237
237
|
return [score, 0, firstSize];
|
|
238
238
|
}
|
|
239
239
|
let direct = word.indexOf(this.pattern);
|
|
240
240
|
if (direct == 0)
|
|
241
|
-
return [word.length == this.pattern.length ? 0 : -100 /*
|
|
241
|
+
return [word.length == this.pattern.length ? 0 : -100 /* NotFull */, 0, this.pattern.length];
|
|
242
242
|
let len = chars.length, anyTo = 0;
|
|
243
243
|
if (direct < 0) {
|
|
244
244
|
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
|
|
@@ -262,7 +262,7 @@ class FuzzyMatcher {
|
|
|
262
262
|
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
|
263
263
|
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
|
264
264
|
// Go over the option's text, scanning for the various kinds of matches
|
|
265
|
-
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /*
|
|
265
|
+
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
|
|
266
266
|
let next = state.codePointAt(word, i);
|
|
267
267
|
if (direct < 0) {
|
|
268
268
|
if (preciseTo < len && next == chars[preciseTo])
|
|
@@ -280,9 +280,9 @@ class FuzzyMatcher {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
let ch, type = next < 0xff
|
|
283
|
-
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /*
|
|
284
|
-
: ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /*
|
|
285
|
-
if (!i || type == 1 /*
|
|
283
|
+
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
|
|
284
|
+
: ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
|
|
285
|
+
if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
|
|
286
286
|
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
|
287
287
|
byWord[byWordTo++] = i;
|
|
288
288
|
else if (byWord.length)
|
|
@@ -292,17 +292,17 @@ class FuzzyMatcher {
|
|
|
292
292
|
i += state.codePointSize(next);
|
|
293
293
|
}
|
|
294
294
|
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
|
295
|
-
return this.result(-100 /*
|
|
295
|
+
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
|
296
296
|
if (adjacentTo == len && adjacentStart == 0)
|
|
297
|
-
return [-200 /*
|
|
297
|
+
return [-200 /* CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* NotFull */), 0, adjacentEnd];
|
|
298
298
|
if (direct > -1)
|
|
299
|
-
return [-700 /*
|
|
299
|
+
return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
|
|
300
300
|
if (adjacentTo == len)
|
|
301
|
-
return [-200 /*
|
|
301
|
+
return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
|
|
302
302
|
if (byWordTo == len)
|
|
303
|
-
return this.result(-100 /*
|
|
304
|
-
(wordAdjacent ? 0 : -1100 /*
|
|
305
|
-
return chars.length == 2 ? null : this.result((any[0] ? -700 /*
|
|
303
|
+
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
|
304
|
+
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
|
305
|
+
return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
|
|
306
306
|
}
|
|
307
307
|
result(score, positions, word) {
|
|
308
308
|
let result = [score - word.length], i = 1;
|
|
@@ -360,11 +360,11 @@ function defaultPositionInfo(view$1, list, option, info, space) {
|
|
|
360
360
|
left = true;
|
|
361
361
|
if (infoWidth <= (left ? spaceLeft : spaceRight)) {
|
|
362
362
|
offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
|
|
363
|
-
maxWidth = Math.min(400 /*
|
|
363
|
+
maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
|
|
364
364
|
}
|
|
365
365
|
else {
|
|
366
366
|
narrow = true;
|
|
367
|
-
maxWidth = Math.min(400 /*
|
|
367
|
+
maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
|
|
368
368
|
let spaceBelow = space.bottom - list.bottom;
|
|
369
369
|
if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
|
|
370
370
|
offset = option.bottom - list.top;
|
|
@@ -380,232 +380,6 @@ function defaultPositionInfo(view$1, list, option, info, space) {
|
|
|
380
380
|
};
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
/**
|
|
384
|
-
Returns a command that moves the completion selection forward or
|
|
385
|
-
backward by the given amount.
|
|
386
|
-
*/
|
|
387
|
-
function moveCompletionSelection(forward, by = "option") {
|
|
388
|
-
return (view$1) => {
|
|
389
|
-
let cState = view$1.state.field(completionState, false);
|
|
390
|
-
if (!cState || !cState.open || cState.open.disabled ||
|
|
391
|
-
Date.now() - cState.open.timestamp < view$1.state.facet(completionConfig).interactionDelay)
|
|
392
|
-
return false;
|
|
393
|
-
let step = 1, tooltip;
|
|
394
|
-
if (by == "page" && (tooltip = view.getTooltip(view$1, cState.open.tooltip)))
|
|
395
|
-
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
|
396
|
-
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
|
397
|
-
let { length } = cState.open.options;
|
|
398
|
-
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
|
399
|
-
if (selected < 0)
|
|
400
|
-
selected = by == "page" ? 0 : length - 1;
|
|
401
|
-
else if (selected >= length)
|
|
402
|
-
selected = by == "page" ? length - 1 : 0;
|
|
403
|
-
view$1.dispatch({ effects: setSelectedEffect.of(selected) });
|
|
404
|
-
return true;
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
Accept the current completion.
|
|
409
|
-
*/
|
|
410
|
-
const acceptCompletion = (view) => {
|
|
411
|
-
let cState = view.state.field(completionState, false);
|
|
412
|
-
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 ||
|
|
413
|
-
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
414
|
-
return false;
|
|
415
|
-
if (!cState.open.disabled)
|
|
416
|
-
return applyCompletion(view, cState.open.options[cState.open.selected]);
|
|
417
|
-
return true;
|
|
418
|
-
};
|
|
419
|
-
/**
|
|
420
|
-
Explicitly start autocompletion.
|
|
421
|
-
*/
|
|
422
|
-
const startCompletion = (view) => {
|
|
423
|
-
let cState = view.state.field(completionState, false);
|
|
424
|
-
if (!cState)
|
|
425
|
-
return false;
|
|
426
|
-
view.dispatch({ effects: startCompletionEffect.of(true) });
|
|
427
|
-
return true;
|
|
428
|
-
};
|
|
429
|
-
/**
|
|
430
|
-
Close the currently active completion.
|
|
431
|
-
*/
|
|
432
|
-
const closeCompletion = (view) => {
|
|
433
|
-
let cState = view.state.field(completionState, false);
|
|
434
|
-
if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
|
|
435
|
-
return false;
|
|
436
|
-
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
437
|
-
return true;
|
|
438
|
-
};
|
|
439
|
-
class RunningQuery {
|
|
440
|
-
constructor(active, context) {
|
|
441
|
-
this.active = active;
|
|
442
|
-
this.context = context;
|
|
443
|
-
this.time = Date.now();
|
|
444
|
-
this.updates = [];
|
|
445
|
-
// Note that 'undefined' means 'not done yet', whereas 'null' means
|
|
446
|
-
// 'query returned null'.
|
|
447
|
-
this.done = undefined;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
|
|
451
|
-
const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
452
|
-
constructor(view) {
|
|
453
|
-
this.view = view;
|
|
454
|
-
this.debounceUpdate = -1;
|
|
455
|
-
this.running = [];
|
|
456
|
-
this.debounceAccept = -1;
|
|
457
|
-
this.composing = 0 /* CompositionState.None */;
|
|
458
|
-
for (let active of view.state.field(completionState).active)
|
|
459
|
-
if (active.state == 1 /* State.Pending */)
|
|
460
|
-
this.startQuery(active);
|
|
461
|
-
}
|
|
462
|
-
update(update) {
|
|
463
|
-
let cState = update.state.field(completionState);
|
|
464
|
-
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
|
|
465
|
-
return;
|
|
466
|
-
let doesReset = update.transactions.some(tr => {
|
|
467
|
-
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
|
|
468
|
-
});
|
|
469
|
-
for (let i = 0; i < this.running.length; i++) {
|
|
470
|
-
let query = this.running[i];
|
|
471
|
-
if (doesReset ||
|
|
472
|
-
query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
|
|
473
|
-
for (let handler of query.context.abortListeners) {
|
|
474
|
-
try {
|
|
475
|
-
handler();
|
|
476
|
-
}
|
|
477
|
-
catch (e) {
|
|
478
|
-
view.logException(this.view.state, e);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
query.context.abortListeners = null;
|
|
482
|
-
this.running.splice(i--, 1);
|
|
483
|
-
}
|
|
484
|
-
else {
|
|
485
|
-
query.updates.push(...update.transactions);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
if (this.debounceUpdate > -1)
|
|
489
|
-
clearTimeout(this.debounceUpdate);
|
|
490
|
-
this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
491
|
-
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
492
|
-
if (this.composing != 0 /* CompositionState.None */)
|
|
493
|
-
for (let tr of update.transactions) {
|
|
494
|
-
if (getUserEvent(tr) == "input")
|
|
495
|
-
this.composing = 2 /* CompositionState.Changed */;
|
|
496
|
-
else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
|
|
497
|
-
this.composing = 3 /* CompositionState.ChangedAndMoved */;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
startUpdate() {
|
|
501
|
-
this.debounceUpdate = -1;
|
|
502
|
-
let { state } = this.view, cState = state.field(completionState);
|
|
503
|
-
for (let active of cState.active) {
|
|
504
|
-
if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
505
|
-
this.startQuery(active);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
startQuery(active) {
|
|
509
|
-
let { state } = this.view, pos = cur(state);
|
|
510
|
-
let context = new CompletionContext(state, pos, active.explicitPos == pos);
|
|
511
|
-
let pending = new RunningQuery(active, context);
|
|
512
|
-
this.running.push(pending);
|
|
513
|
-
Promise.resolve(active.source(context)).then(result => {
|
|
514
|
-
if (!pending.context.aborted) {
|
|
515
|
-
pending.done = result || null;
|
|
516
|
-
this.scheduleAccept();
|
|
517
|
-
}
|
|
518
|
-
}, err => {
|
|
519
|
-
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
520
|
-
view.logException(this.view.state, err);
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
scheduleAccept() {
|
|
524
|
-
if (this.running.every(q => q.done !== undefined))
|
|
525
|
-
this.accept();
|
|
526
|
-
else if (this.debounceAccept < 0)
|
|
527
|
-
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
|
|
528
|
-
}
|
|
529
|
-
// For each finished query in this.running, try to create a result
|
|
530
|
-
// or, if appropriate, restart the query.
|
|
531
|
-
accept() {
|
|
532
|
-
var _a;
|
|
533
|
-
if (this.debounceAccept > -1)
|
|
534
|
-
clearTimeout(this.debounceAccept);
|
|
535
|
-
this.debounceAccept = -1;
|
|
536
|
-
let updated = [];
|
|
537
|
-
let conf = this.view.state.facet(completionConfig);
|
|
538
|
-
for (let i = 0; i < this.running.length; i++) {
|
|
539
|
-
let query = this.running[i];
|
|
540
|
-
if (query.done === undefined)
|
|
541
|
-
continue;
|
|
542
|
-
this.running.splice(i--, 1);
|
|
543
|
-
if (query.done) {
|
|
544
|
-
let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
|
|
545
|
-
// Replay the transactions that happened since the start of
|
|
546
|
-
// the request and see if that preserves the result
|
|
547
|
-
for (let tr of query.updates)
|
|
548
|
-
active = active.update(tr, conf);
|
|
549
|
-
if (active.hasResult()) {
|
|
550
|
-
updated.push(active);
|
|
551
|
-
continue;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
555
|
-
if (current && current.state == 1 /* State.Pending */) {
|
|
556
|
-
if (query.done == null) {
|
|
557
|
-
// Explicitly failed. Should clear the pending status if it
|
|
558
|
-
// hasn't been re-set in the meantime.
|
|
559
|
-
let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
|
|
560
|
-
for (let tr of query.updates)
|
|
561
|
-
active = active.update(tr, conf);
|
|
562
|
-
if (active.state != 1 /* State.Pending */)
|
|
563
|
-
updated.push(active);
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
// Cleared by subsequent transactions. Restart.
|
|
567
|
-
this.startQuery(current);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
if (updated.length)
|
|
572
|
-
this.view.dispatch({ effects: setActiveEffect.of(updated) });
|
|
573
|
-
}
|
|
574
|
-
}, {
|
|
575
|
-
eventHandlers: {
|
|
576
|
-
blur(event) {
|
|
577
|
-
let state = this.view.state.field(completionState, false);
|
|
578
|
-
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
|
|
579
|
-
let dialog = state.open && view.getTooltip(this.view, state.open.tooltip);
|
|
580
|
-
if (!dialog || !dialog.dom.contains(event.relatedTarget))
|
|
581
|
-
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
582
|
-
}
|
|
583
|
-
},
|
|
584
|
-
compositionstart() {
|
|
585
|
-
this.composing = 1 /* CompositionState.Started */;
|
|
586
|
-
},
|
|
587
|
-
compositionend() {
|
|
588
|
-
if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
|
|
589
|
-
// Safari fires compositionend events synchronously, possibly
|
|
590
|
-
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
591
|
-
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
592
|
-
}
|
|
593
|
-
this.composing = 0 /* CompositionState.None */;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
function applyCompletion(view, option) {
|
|
598
|
-
const apply = option.completion.apply || option.completion.label;
|
|
599
|
-
let result = view.state.field(completionState).active.find(a => a.source == option.source);
|
|
600
|
-
if (!(result instanceof ActiveResult))
|
|
601
|
-
return false;
|
|
602
|
-
if (typeof apply == "string")
|
|
603
|
-
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
|
604
|
-
else
|
|
605
|
-
apply(view, option.completion, result.from, result.to);
|
|
606
|
-
return true;
|
|
607
|
-
}
|
|
608
|
-
|
|
609
383
|
function optionContent(config) {
|
|
610
384
|
let content = config.addToOptions.slice();
|
|
611
385
|
if (config.icons)
|
|
@@ -665,10 +439,12 @@ function rangeAroundSelected(total, selected, max) {
|
|
|
665
439
|
return { from: total - (off + 1) * max, to: total - off * max };
|
|
666
440
|
}
|
|
667
441
|
class CompletionTooltip {
|
|
668
|
-
constructor(view, stateField) {
|
|
442
|
+
constructor(view, stateField, applyCompletion) {
|
|
669
443
|
this.view = view;
|
|
670
444
|
this.stateField = stateField;
|
|
445
|
+
this.applyCompletion = applyCompletion;
|
|
671
446
|
this.info = null;
|
|
447
|
+
this.infoDestroy = null;
|
|
672
448
|
this.placeInfoReq = {
|
|
673
449
|
read: () => this.measureInfo(),
|
|
674
450
|
write: (pos) => this.placeInfo(pos),
|
|
@@ -689,7 +465,7 @@ class CompletionTooltip {
|
|
|
689
465
|
this.dom.addEventListener("mousedown", (e) => {
|
|
690
466
|
for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) {
|
|
691
467
|
if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) {
|
|
692
|
-
applyCompletion(view, options[+match[1]]);
|
|
468
|
+
this.applyCompletion(view, options[+match[1]]);
|
|
693
469
|
e.preventDefault();
|
|
694
470
|
return;
|
|
695
471
|
}
|
|
@@ -748,33 +524,39 @@ class CompletionTooltip {
|
|
|
748
524
|
});
|
|
749
525
|
}
|
|
750
526
|
if (this.updateSelectedOption(open.selected)) {
|
|
751
|
-
|
|
752
|
-
this.info.remove();
|
|
753
|
-
this.info = null;
|
|
754
|
-
}
|
|
527
|
+
this.destroyInfo();
|
|
755
528
|
let { completion } = open.options[open.selected];
|
|
756
529
|
let { info } = completion;
|
|
757
530
|
if (!info)
|
|
758
531
|
return;
|
|
759
|
-
let infoResult = typeof info ===
|
|
532
|
+
let infoResult = typeof info === "string" ? document.createTextNode(info) : info(completion);
|
|
760
533
|
if (!infoResult)
|
|
761
534
|
return;
|
|
762
|
-
if (
|
|
763
|
-
infoResult.then(
|
|
764
|
-
if (
|
|
765
|
-
this.addInfoPane(
|
|
535
|
+
if ("then" in infoResult) {
|
|
536
|
+
infoResult.then(obj => {
|
|
537
|
+
if (obj && this.view.state.field(this.stateField, false) == cState)
|
|
538
|
+
this.addInfoPane(obj, completion);
|
|
766
539
|
}).catch(e => view.logException(this.view.state, e, "completion info"));
|
|
767
540
|
}
|
|
768
541
|
else {
|
|
769
|
-
this.addInfoPane(infoResult);
|
|
542
|
+
this.addInfoPane(infoResult, completion);
|
|
770
543
|
}
|
|
771
544
|
}
|
|
772
545
|
}
|
|
773
|
-
addInfoPane(content) {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
546
|
+
addInfoPane(content, completion) {
|
|
547
|
+
this.destroyInfo();
|
|
548
|
+
let wrap = this.info = document.createElement("div");
|
|
549
|
+
wrap.className = "cm-tooltip cm-completionInfo";
|
|
550
|
+
if (content.nodeType != null) {
|
|
551
|
+
wrap.appendChild(content);
|
|
552
|
+
this.infoDestroy = null;
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
let { dom, destroy } = content;
|
|
556
|
+
wrap.appendChild(dom);
|
|
557
|
+
this.infoDestroy = destroy || null;
|
|
558
|
+
}
|
|
559
|
+
this.dom.appendChild(wrap);
|
|
778
560
|
this.view.requestMeasure(this.placeInfoReq);
|
|
779
561
|
}
|
|
780
562
|
updateSelectedOption(selected) {
|
|
@@ -867,11 +649,22 @@ class CompletionTooltip {
|
|
|
867
649
|
ul.classList.add("cm-completionListIncompleteBottom");
|
|
868
650
|
return ul;
|
|
869
651
|
}
|
|
652
|
+
destroyInfo() {
|
|
653
|
+
if (this.info) {
|
|
654
|
+
if (this.infoDestroy)
|
|
655
|
+
this.infoDestroy();
|
|
656
|
+
this.info.remove();
|
|
657
|
+
this.info = null;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
destroy() {
|
|
661
|
+
this.destroyInfo();
|
|
662
|
+
}
|
|
870
663
|
}
|
|
871
664
|
// We allocate a new function instance every time the completion
|
|
872
665
|
// changes to force redrawing/repositioning of the tooltip
|
|
873
|
-
function completionTooltip(stateField) {
|
|
874
|
-
return (view) => new CompletionTooltip(view, stateField);
|
|
666
|
+
function completionTooltip(stateField, applyCompletion) {
|
|
667
|
+
return (view) => new CompletionTooltip(view, stateField, applyCompletion);
|
|
875
668
|
}
|
|
876
669
|
function scrollIntoView(container, element) {
|
|
877
670
|
let parent = container.getBoundingClientRect();
|
|
@@ -938,9 +731,10 @@ function sortOptions(active, state) {
|
|
|
938
731
|
let result = [], prev = null;
|
|
939
732
|
let compare = state.facet(completionConfig).compareCompletions;
|
|
940
733
|
for (let opt of options.sort((a, b) => (b.score - a.score) || compare(a.completion, b.completion))) {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
prev.
|
|
734
|
+
let cur = opt.completion;
|
|
735
|
+
if (!prev || prev.label != cur.label || prev.detail != cur.detail ||
|
|
736
|
+
(prev.type != null && cur.type != null && prev.type != cur.type) ||
|
|
737
|
+
prev.apply != cur.apply || prev.boost != cur.boost)
|
|
944
738
|
result.push(opt);
|
|
945
739
|
else if (score(opt.completion) > score(prev))
|
|
946
740
|
result[result.length - 1] = opt;
|
|
@@ -964,7 +758,7 @@ class CompletionDialog {
|
|
|
964
758
|
static build(active, state, id, prev, conf) {
|
|
965
759
|
let options = sortOptions(active, state);
|
|
966
760
|
if (!options.length) {
|
|
967
|
-
return prev && active.some(a => a.state == 1 /*
|
|
761
|
+
return prev && active.some(a => a.state == 1 /* Pending */) ?
|
|
968
762
|
new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
|
|
969
763
|
}
|
|
970
764
|
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
|
@@ -978,7 +772,7 @@ class CompletionDialog {
|
|
|
978
772
|
}
|
|
979
773
|
return new CompletionDialog(options, makeAttrs(id, selected), {
|
|
980
774
|
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
981
|
-
create: completionTooltip(completionState),
|
|
775
|
+
create: completionTooltip(completionState, applyCompletion),
|
|
982
776
|
above: conf.aboveCursor,
|
|
983
777
|
}, prev ? prev.timestamp : Date.now(), selected, false);
|
|
984
778
|
}
|
|
@@ -1001,7 +795,7 @@ class CompletionState {
|
|
|
1001
795
|
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
1002
796
|
let active = sources.map(source => {
|
|
1003
797
|
let value = this.active.find(s => s.source == source) ||
|
|
1004
|
-
new ActiveSource(source, this.active.some(a => a.state != 0 /*
|
|
798
|
+
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
|
1005
799
|
return value.update(tr, conf);
|
|
1006
800
|
});
|
|
1007
801
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
@@ -1012,10 +806,10 @@ class CompletionState {
|
|
|
1012
806
|
if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
1013
807
|
!sameResults(active, this.active))
|
|
1014
808
|
open = CompletionDialog.build(active, state, this.id, open, conf);
|
|
1015
|
-
else if (open && open.disabled && !active.some(a => a.state == 1 /*
|
|
809
|
+
else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
|
|
1016
810
|
open = null;
|
|
1017
|
-
if (!open && active.every(a => a.state != 1 /*
|
|
1018
|
-
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /*
|
|
811
|
+
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
812
|
+
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
1019
813
|
for (let effect of tr.effects)
|
|
1020
814
|
if (effect.is(setSelectedEffect))
|
|
1021
815
|
open = open && open.setSelected(effect.value, this.id);
|
|
@@ -1069,13 +863,13 @@ class ActiveSource {
|
|
|
1069
863
|
value = value.handleUserEvent(tr, event, conf);
|
|
1070
864
|
else if (tr.docChanged)
|
|
1071
865
|
value = value.handleChange(tr);
|
|
1072
|
-
else if (tr.selection && value.state != 0 /*
|
|
1073
|
-
value = new ActiveSource(value.source, 0 /*
|
|
866
|
+
else if (tr.selection && value.state != 0 /* Inactive */)
|
|
867
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
1074
868
|
for (let effect of tr.effects) {
|
|
1075
869
|
if (effect.is(startCompletionEffect))
|
|
1076
|
-
value = new ActiveSource(value.source, 1 /*
|
|
870
|
+
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
|
1077
871
|
else if (effect.is(closeCompletionEffect))
|
|
1078
|
-
value = new ActiveSource(value.source, 0 /*
|
|
872
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
1079
873
|
else if (effect.is(setActiveEffect))
|
|
1080
874
|
for (let active of effect.value)
|
|
1081
875
|
if (active.source == value.source)
|
|
@@ -1084,10 +878,10 @@ class ActiveSource {
|
|
|
1084
878
|
return value;
|
|
1085
879
|
}
|
|
1086
880
|
handleUserEvent(tr, type, conf) {
|
|
1087
|
-
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /*
|
|
881
|
+
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
|
1088
882
|
}
|
|
1089
883
|
handleChange(tr) {
|
|
1090
|
-
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /*
|
|
884
|
+
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
1091
885
|
}
|
|
1092
886
|
map(changes) {
|
|
1093
887
|
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
|
@@ -1095,7 +889,7 @@ class ActiveSource {
|
|
|
1095
889
|
}
|
|
1096
890
|
class ActiveResult extends ActiveSource {
|
|
1097
891
|
constructor(source, explicitPos, result, from, to) {
|
|
1098
|
-
super(source, 2 /*
|
|
892
|
+
super(source, 2 /* Result */, explicitPos);
|
|
1099
893
|
this.result = result;
|
|
1100
894
|
this.from = from;
|
|
1101
895
|
this.to = to;
|
|
@@ -1108,17 +902,17 @@ class ActiveResult extends ActiveSource {
|
|
|
1108
902
|
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
|
1109
903
|
pos > to ||
|
|
1110
904
|
type == "delete" && cur(tr.startState) == this.from)
|
|
1111
|
-
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /*
|
|
905
|
+
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
|
1112
906
|
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
|
1113
907
|
if (checkValid(this.result.validFor, tr.state, from, to))
|
|
1114
908
|
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
|
1115
909
|
if (this.result.update &&
|
|
1116
910
|
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
|
1117
911
|
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
|
1118
|
-
return new ActiveSource(this.source, 1 /*
|
|
912
|
+
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
|
1119
913
|
}
|
|
1120
914
|
handleChange(tr) {
|
|
1121
|
-
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /*
|
|
915
|
+
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
1122
916
|
}
|
|
1123
917
|
map(mapping) {
|
|
1124
918
|
return mapping.empty ? this :
|
|
@@ -1143,6 +937,230 @@ const completionState = state.StateField.define({
|
|
|
1143
937
|
view.EditorView.contentAttributes.from(f, state => state.attrs)
|
|
1144
938
|
]
|
|
1145
939
|
});
|
|
940
|
+
function applyCompletion(view, option) {
|
|
941
|
+
const apply = option.completion.apply || option.completion.label;
|
|
942
|
+
let result = view.state.field(completionState).active.find(a => a.source == option.source);
|
|
943
|
+
if (!(result instanceof ActiveResult))
|
|
944
|
+
return false;
|
|
945
|
+
if (typeof apply == "string")
|
|
946
|
+
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
|
947
|
+
else
|
|
948
|
+
apply(view, option.completion, result.from, result.to);
|
|
949
|
+
return true;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
Returns a command that moves the completion selection forward or
|
|
954
|
+
backward by the given amount.
|
|
955
|
+
*/
|
|
956
|
+
function moveCompletionSelection(forward, by = "option") {
|
|
957
|
+
return (view$1) => {
|
|
958
|
+
let cState = view$1.state.field(completionState, false);
|
|
959
|
+
if (!cState || !cState.open || cState.open.disabled ||
|
|
960
|
+
Date.now() - cState.open.timestamp < view$1.state.facet(completionConfig).interactionDelay)
|
|
961
|
+
return false;
|
|
962
|
+
let step = 1, tooltip;
|
|
963
|
+
if (by == "page" && (tooltip = view.getTooltip(view$1, cState.open.tooltip)))
|
|
964
|
+
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
|
965
|
+
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
|
966
|
+
let { length } = cState.open.options;
|
|
967
|
+
let selected = cState.open.selected > -1 ? cState.open.selected + step * (forward ? 1 : -1) : forward ? 0 : length - 1;
|
|
968
|
+
if (selected < 0)
|
|
969
|
+
selected = by == "page" ? 0 : length - 1;
|
|
970
|
+
else if (selected >= length)
|
|
971
|
+
selected = by == "page" ? length - 1 : 0;
|
|
972
|
+
view$1.dispatch({ effects: setSelectedEffect.of(selected) });
|
|
973
|
+
return true;
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
Accept the current completion.
|
|
978
|
+
*/
|
|
979
|
+
const acceptCompletion = (view) => {
|
|
980
|
+
let cState = view.state.field(completionState, false);
|
|
981
|
+
if (view.state.readOnly || !cState || !cState.open || cState.open.selected < 0 || cState.open.disabled ||
|
|
982
|
+
Date.now() - cState.open.timestamp < view.state.facet(completionConfig).interactionDelay)
|
|
983
|
+
return false;
|
|
984
|
+
return applyCompletion(view, cState.open.options[cState.open.selected]);
|
|
985
|
+
};
|
|
986
|
+
/**
|
|
987
|
+
Explicitly start autocompletion.
|
|
988
|
+
*/
|
|
989
|
+
const startCompletion = (view) => {
|
|
990
|
+
let cState = view.state.field(completionState, false);
|
|
991
|
+
if (!cState)
|
|
992
|
+
return false;
|
|
993
|
+
view.dispatch({ effects: startCompletionEffect.of(true) });
|
|
994
|
+
return true;
|
|
995
|
+
};
|
|
996
|
+
/**
|
|
997
|
+
Close the currently active completion.
|
|
998
|
+
*/
|
|
999
|
+
const closeCompletion = (view) => {
|
|
1000
|
+
let cState = view.state.field(completionState, false);
|
|
1001
|
+
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
|
1002
|
+
return false;
|
|
1003
|
+
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1004
|
+
return true;
|
|
1005
|
+
};
|
|
1006
|
+
class RunningQuery {
|
|
1007
|
+
constructor(active, context) {
|
|
1008
|
+
this.active = active;
|
|
1009
|
+
this.context = context;
|
|
1010
|
+
this.time = Date.now();
|
|
1011
|
+
this.updates = [];
|
|
1012
|
+
// Note that 'undefined' means 'not done yet', whereas 'null' means
|
|
1013
|
+
// 'query returned null'.
|
|
1014
|
+
this.done = undefined;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
|
|
1018
|
+
const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
1019
|
+
constructor(view) {
|
|
1020
|
+
this.view = view;
|
|
1021
|
+
this.debounceUpdate = -1;
|
|
1022
|
+
this.running = [];
|
|
1023
|
+
this.debounceAccept = -1;
|
|
1024
|
+
this.composing = 0 /* None */;
|
|
1025
|
+
for (let active of view.state.field(completionState).active)
|
|
1026
|
+
if (active.state == 1 /* Pending */)
|
|
1027
|
+
this.startQuery(active);
|
|
1028
|
+
}
|
|
1029
|
+
update(update) {
|
|
1030
|
+
let cState = update.state.field(completionState);
|
|
1031
|
+
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
|
|
1032
|
+
return;
|
|
1033
|
+
let doesReset = update.transactions.some(tr => {
|
|
1034
|
+
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
|
|
1035
|
+
});
|
|
1036
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
1037
|
+
let query = this.running[i];
|
|
1038
|
+
if (doesReset ||
|
|
1039
|
+
query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
|
|
1040
|
+
for (let handler of query.context.abortListeners) {
|
|
1041
|
+
try {
|
|
1042
|
+
handler();
|
|
1043
|
+
}
|
|
1044
|
+
catch (e) {
|
|
1045
|
+
view.logException(this.view.state, e);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
query.context.abortListeners = null;
|
|
1049
|
+
this.running.splice(i--, 1);
|
|
1050
|
+
}
|
|
1051
|
+
else {
|
|
1052
|
+
query.updates.push(...update.transactions);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
if (this.debounceUpdate > -1)
|
|
1056
|
+
clearTimeout(this.debounceUpdate);
|
|
1057
|
+
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
1058
|
+
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
1059
|
+
if (this.composing != 0 /* None */)
|
|
1060
|
+
for (let tr of update.transactions) {
|
|
1061
|
+
if (getUserEvent(tr) == "input")
|
|
1062
|
+
this.composing = 2 /* Changed */;
|
|
1063
|
+
else if (this.composing == 2 /* Changed */ && tr.selection)
|
|
1064
|
+
this.composing = 3 /* ChangedAndMoved */;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
startUpdate() {
|
|
1068
|
+
this.debounceUpdate = -1;
|
|
1069
|
+
let { state } = this.view, cState = state.field(completionState);
|
|
1070
|
+
for (let active of cState.active) {
|
|
1071
|
+
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
1072
|
+
this.startQuery(active);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
startQuery(active) {
|
|
1076
|
+
let { state } = this.view, pos = cur(state);
|
|
1077
|
+
let context = new CompletionContext(state, pos, active.explicitPos == pos);
|
|
1078
|
+
let pending = new RunningQuery(active, context);
|
|
1079
|
+
this.running.push(pending);
|
|
1080
|
+
Promise.resolve(active.source(context)).then(result => {
|
|
1081
|
+
if (!pending.context.aborted) {
|
|
1082
|
+
pending.done = result || null;
|
|
1083
|
+
this.scheduleAccept();
|
|
1084
|
+
}
|
|
1085
|
+
}, err => {
|
|
1086
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1087
|
+
view.logException(this.view.state, err);
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
scheduleAccept() {
|
|
1091
|
+
if (this.running.every(q => q.done !== undefined))
|
|
1092
|
+
this.accept();
|
|
1093
|
+
else if (this.debounceAccept < 0)
|
|
1094
|
+
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
|
|
1095
|
+
}
|
|
1096
|
+
// For each finished query in this.running, try to create a result
|
|
1097
|
+
// or, if appropriate, restart the query.
|
|
1098
|
+
accept() {
|
|
1099
|
+
var _a;
|
|
1100
|
+
if (this.debounceAccept > -1)
|
|
1101
|
+
clearTimeout(this.debounceAccept);
|
|
1102
|
+
this.debounceAccept = -1;
|
|
1103
|
+
let updated = [];
|
|
1104
|
+
let conf = this.view.state.facet(completionConfig);
|
|
1105
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
1106
|
+
let query = this.running[i];
|
|
1107
|
+
if (query.done === undefined)
|
|
1108
|
+
continue;
|
|
1109
|
+
this.running.splice(i--, 1);
|
|
1110
|
+
if (query.done) {
|
|
1111
|
+
let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
|
|
1112
|
+
// Replay the transactions that happened since the start of
|
|
1113
|
+
// the request and see if that preserves the result
|
|
1114
|
+
for (let tr of query.updates)
|
|
1115
|
+
active = active.update(tr, conf);
|
|
1116
|
+
if (active.hasResult()) {
|
|
1117
|
+
updated.push(active);
|
|
1118
|
+
continue;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
1122
|
+
if (current && current.state == 1 /* Pending */) {
|
|
1123
|
+
if (query.done == null) {
|
|
1124
|
+
// Explicitly failed. Should clear the pending status if it
|
|
1125
|
+
// hasn't been re-set in the meantime.
|
|
1126
|
+
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
|
1127
|
+
for (let tr of query.updates)
|
|
1128
|
+
active = active.update(tr, conf);
|
|
1129
|
+
if (active.state != 1 /* Pending */)
|
|
1130
|
+
updated.push(active);
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
// Cleared by subsequent transactions. Restart.
|
|
1134
|
+
this.startQuery(current);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
if (updated.length)
|
|
1139
|
+
this.view.dispatch({ effects: setActiveEffect.of(updated) });
|
|
1140
|
+
}
|
|
1141
|
+
}, {
|
|
1142
|
+
eventHandlers: {
|
|
1143
|
+
blur(event) {
|
|
1144
|
+
let state = this.view.state.field(completionState, false);
|
|
1145
|
+
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur) {
|
|
1146
|
+
let dialog = state.open && view.getTooltip(this.view, state.open.tooltip);
|
|
1147
|
+
if (!dialog || !dialog.dom.contains(event.relatedTarget))
|
|
1148
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1151
|
+
compositionstart() {
|
|
1152
|
+
this.composing = 1 /* Started */;
|
|
1153
|
+
},
|
|
1154
|
+
compositionend() {
|
|
1155
|
+
if (this.composing == 3 /* ChangedAndMoved */) {
|
|
1156
|
+
// Safari fires compositionend events synchronously, possibly
|
|
1157
|
+
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
1158
|
+
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
1159
|
+
}
|
|
1160
|
+
this.composing = 0 /* None */;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
});
|
|
1146
1164
|
|
|
1147
1165
|
const baseTheme = view.EditorView.baseTheme({
|
|
1148
1166
|
".cm-tooltip.cm-tooltip-autocomplete": {
|
|
@@ -1199,13 +1217,13 @@ const baseTheme = view.EditorView.baseTheme({
|
|
|
1199
1217
|
position: "absolute",
|
|
1200
1218
|
padding: "3px 9px",
|
|
1201
1219
|
width: "max-content",
|
|
1202
|
-
maxWidth: `${400 /*
|
|
1220
|
+
maxWidth: `${400 /* Width */}px`,
|
|
1203
1221
|
boxSizing: "border-box"
|
|
1204
1222
|
},
|
|
1205
1223
|
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
|
1206
1224
|
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
|
1207
|
-
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /*
|
|
1208
|
-
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /*
|
|
1225
|
+
".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
|
|
1226
|
+
".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
|
|
1209
1227
|
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
|
1210
1228
|
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
|
1211
1229
|
".cm-snippetFieldPosition": {
|
|
@@ -1558,7 +1576,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1558
1576
|
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
|
1559
1577
|
result.push({ type: "text", label: m[0] });
|
|
1560
1578
|
seen[m[0]] = true;
|
|
1561
|
-
if (result.length >= 2000 /*
|
|
1579
|
+
if (result.length >= 2000 /* MaxList */)
|
|
1562
1580
|
return;
|
|
1563
1581
|
}
|
|
1564
1582
|
}
|
|
@@ -1566,7 +1584,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
|
1566
1584
|
}
|
|
1567
1585
|
}
|
|
1568
1586
|
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
1569
|
-
let big = doc.length >= 1000 /*
|
|
1587
|
+
let big = doc.length >= 1000 /* MinCacheLen */;
|
|
1570
1588
|
let cached = big && cache.get(doc);
|
|
1571
1589
|
if (cached)
|
|
1572
1590
|
return cached;
|
|
@@ -1574,7 +1592,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1574
1592
|
if (doc.children) {
|
|
1575
1593
|
let pos = 0;
|
|
1576
1594
|
for (let ch of doc.children) {
|
|
1577
|
-
if (ch.length >= 1000 /*
|
|
1595
|
+
if (ch.length >= 1000 /* MinCacheLen */) {
|
|
1578
1596
|
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
|
1579
1597
|
if (!seen[c.label]) {
|
|
1580
1598
|
seen[c.label] = true;
|
|
@@ -1591,7 +1609,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
|
1591
1609
|
else {
|
|
1592
1610
|
storeWords(doc, wordRE, result, seen, ignoreAt);
|
|
1593
1611
|
}
|
|
1594
|
-
if (big && result.length < 2000 /*
|
|
1612
|
+
if (big && result.length < 2000 /* MaxList */)
|
|
1595
1613
|
cache.set(doc, result);
|
|
1596
1614
|
return result;
|
|
1597
1615
|
}
|
|
@@ -1607,7 +1625,7 @@ const completeAnyWord = context => {
|
|
|
1607
1625
|
if (!token && !context.explicit)
|
|
1608
1626
|
return null;
|
|
1609
1627
|
let from = token ? token.from : context.pos;
|
|
1610
|
-
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /*
|
|
1628
|
+
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
|
1611
1629
|
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
|
1612
1630
|
};
|
|
1613
1631
|
|
|
@@ -1899,8 +1917,8 @@ returns `null`.
|
|
|
1899
1917
|
*/
|
|
1900
1918
|
function completionStatus(state) {
|
|
1901
1919
|
let cState = state.field(completionState, false);
|
|
1902
|
-
return cState && cState.active.some(a => a.state == 1 /*
|
|
1903
|
-
: cState && cState.active.some(a => a.state != 0 /*
|
|
1920
|
+
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
|
1921
|
+
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
|
1904
1922
|
}
|
|
1905
1923
|
const completionArrayCache = new WeakMap;
|
|
1906
1924
|
/**
|