@codemirror/autocomplete 0.19.5 → 0.19.9
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 +28 -0
- package/dist/index.cjs +22 -14
- package/dist/index.d.ts +6 -0
- package/dist/index.js +22 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## 0.19.9 (2021-11-26)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where info tooltips would be visible in an inappropriate position when there was no room to place them properly.
|
|
6
|
+
|
|
7
|
+
## 0.19.8 (2021-11-17)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Give the completion tooltip a minimal width, and show ellipsis when completions overflow the tooltip width.
|
|
12
|
+
|
|
13
|
+
### New features
|
|
14
|
+
|
|
15
|
+
`autocompletion` now accepts an `aboveCursor` option to make the completion tooltip show up above the cursor.
|
|
16
|
+
|
|
17
|
+
## 0.19.7 (2021-11-16)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
Make option deduplication less aggressive, so that options with different `type` or `apply` fields don't get merged.
|
|
22
|
+
|
|
23
|
+
## 0.19.6 (2021-11-12)
|
|
24
|
+
|
|
25
|
+
### Bug fixes
|
|
26
|
+
|
|
27
|
+
Fix an issue where parsing a snippet with a field that was labeled only by a number crashed.
|
|
28
|
+
|
|
1
29
|
## 0.19.5 (2021-11-09)
|
|
2
30
|
|
|
3
31
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -309,6 +309,7 @@ const completionConfig = state.Facet.define({
|
|
|
309
309
|
maxRenderedOptions: 100,
|
|
310
310
|
defaultKeymap: true,
|
|
311
311
|
optionClass: () => "",
|
|
312
|
+
aboveCursor: false,
|
|
312
313
|
icons: true,
|
|
313
314
|
addToOptions: []
|
|
314
315
|
}, {
|
|
@@ -483,9 +484,9 @@ class CompletionTooltip {
|
|
|
483
484
|
if (!sel || !this.info)
|
|
484
485
|
return null;
|
|
485
486
|
let rect = this.dom.getBoundingClientRect(), infoRect = this.info.getBoundingClientRect();
|
|
486
|
-
|
|
487
|
-
if (top < 0 || top > this.list.clientHeight - 10)
|
|
487
|
+
if (rect.top > innerHeight - 10 || rect.bottom < 10)
|
|
488
488
|
return null;
|
|
489
|
+
let top = Math.max(0, Math.min(sel.getBoundingClientRect().top, innerHeight - infoRect.height)) - rect.top;
|
|
489
490
|
let left = this.view.textDirection == view.Direction.RTL;
|
|
490
491
|
let spaceLeft = rect.left, spaceRight = innerWidth - rect.right;
|
|
491
492
|
if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
|
|
@@ -495,10 +496,12 @@ class CompletionTooltip {
|
|
|
495
496
|
return { top, left };
|
|
496
497
|
}
|
|
497
498
|
positionInfo(pos) {
|
|
498
|
-
if (this.info
|
|
499
|
-
this.info.style.top = pos.top + "px";
|
|
500
|
-
|
|
501
|
-
|
|
499
|
+
if (this.info) {
|
|
500
|
+
this.info.style.top = (pos ? pos.top : -1e6) + "px";
|
|
501
|
+
if (pos) {
|
|
502
|
+
this.info.classList.toggle("cm-completionInfo-left", pos.left);
|
|
503
|
+
this.info.classList.toggle("cm-completionInfo-right", !pos.left);
|
|
504
|
+
}
|
|
502
505
|
}
|
|
503
506
|
}
|
|
504
507
|
createListBox(options, id, range) {
|
|
@@ -570,7 +573,8 @@ function sortOptions(active, state) {
|
|
|
570
573
|
for (let opt of options.sort(cmpOption)) {
|
|
571
574
|
if (result.length == MaxOptions)
|
|
572
575
|
break;
|
|
573
|
-
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail
|
|
576
|
+
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail ||
|
|
577
|
+
prev.type != opt.completion.type || prev.apply != opt.completion.apply)
|
|
574
578
|
result.push(opt);
|
|
575
579
|
else if (score(opt.completion) > score(prev))
|
|
576
580
|
result[result.length - 1] = opt;
|
|
@@ -590,7 +594,7 @@ class CompletionDialog {
|
|
|
590
594
|
return selected == this.selected || selected >= this.options.length ? this
|
|
591
595
|
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected);
|
|
592
596
|
}
|
|
593
|
-
static build(active, state, id, prev) {
|
|
597
|
+
static build(active, state, id, prev, conf) {
|
|
594
598
|
let options = sortOptions(active, state);
|
|
595
599
|
if (!options.length)
|
|
596
600
|
return null;
|
|
@@ -604,7 +608,8 @@ class CompletionDialog {
|
|
|
604
608
|
}
|
|
605
609
|
return new CompletionDialog(options, makeAttrs(id, selected), {
|
|
606
610
|
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
607
|
-
create: completionTooltip(completionState)
|
|
611
|
+
create: completionTooltip(completionState),
|
|
612
|
+
above: conf.aboveCursor,
|
|
608
613
|
}, prev ? prev.timestamp : Date.now(), selected);
|
|
609
614
|
}
|
|
610
615
|
map(changes) {
|
|
@@ -632,7 +637,7 @@ class CompletionState {
|
|
|
632
637
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
633
638
|
active = this.active;
|
|
634
639
|
let open = tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
635
|
-
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open)
|
|
640
|
+
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open, conf)
|
|
636
641
|
: this.open && tr.docChanged ? this.open.map(tr.changes) : this.open;
|
|
637
642
|
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
638
643
|
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
@@ -968,16 +973,19 @@ const baseTheme = view.EditorView.baseTheme({
|
|
|
968
973
|
"& > ul": {
|
|
969
974
|
fontFamily: "monospace",
|
|
970
975
|
whiteSpace: "nowrap",
|
|
971
|
-
overflow: "auto",
|
|
976
|
+
overflow: "hidden auto",
|
|
972
977
|
maxWidth_fallback: "700px",
|
|
973
978
|
maxWidth: "min(700px, 95vw)",
|
|
979
|
+
minWidth: "250px",
|
|
974
980
|
maxHeight: "10em",
|
|
975
981
|
listStyle: "none",
|
|
976
982
|
margin: 0,
|
|
977
983
|
padding: 0,
|
|
978
984
|
"& > li": {
|
|
985
|
+
overflowX: "hidden",
|
|
986
|
+
textOverflow: "ellipsis",
|
|
979
987
|
cursor: "pointer",
|
|
980
|
-
padding: "1px
|
|
988
|
+
padding: "1px 3px",
|
|
981
989
|
lineHeight: 1.2
|
|
982
990
|
},
|
|
983
991
|
}
|
|
@@ -1108,7 +1116,7 @@ class Snippet {
|
|
|
1108
1116
|
let lines = [], positions = [], m;
|
|
1109
1117
|
for (let line of template.split(/\r\n?|\n/)) {
|
|
1110
1118
|
while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|([^}]*))\}/.exec(line)) {
|
|
1111
|
-
let seq = m[1] ? +m[1] : null, name = m[2] || m[3], found = -1;
|
|
1119
|
+
let seq = m[1] ? +m[1] : null, name = m[2] || m[3] || "", found = -1;
|
|
1112
1120
|
for (let i = 0; i < fields.length; i++) {
|
|
1113
1121
|
if (seq != null ? fields[i].seq == seq : name ? fields[i].name == name : false)
|
|
1114
1122
|
found = i;
|
|
@@ -1117,7 +1125,7 @@ class Snippet {
|
|
|
1117
1125
|
let i = 0;
|
|
1118
1126
|
while (i < fields.length && (seq == null || (fields[i].seq != null && fields[i].seq < seq)))
|
|
1119
1127
|
i++;
|
|
1120
|
-
fields.splice(i, 0, { seq, name
|
|
1128
|
+
fields.splice(i, 0, { seq, name });
|
|
1121
1129
|
found = i;
|
|
1122
1130
|
for (let pos of positions)
|
|
1123
1131
|
if (pos.field >= found)
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,12 @@ interface CompletionConfig {
|
|
|
30
30
|
*/
|
|
31
31
|
defaultKeymap?: boolean;
|
|
32
32
|
/**
|
|
33
|
+
By default, completions are shown below the cursor when there is
|
|
34
|
+
space. Setting this to true will make the extension put the
|
|
35
|
+
completions above the cursor when possible.
|
|
36
|
+
*/
|
|
37
|
+
aboveCursor?: boolean;
|
|
38
|
+
/**
|
|
33
39
|
This can be used to add additional CSS classes to completion
|
|
34
40
|
options.
|
|
35
41
|
*/
|
package/dist/index.js
CHANGED
|
@@ -305,6 +305,7 @@ const completionConfig = /*@__PURE__*/Facet.define({
|
|
|
305
305
|
maxRenderedOptions: 100,
|
|
306
306
|
defaultKeymap: true,
|
|
307
307
|
optionClass: () => "",
|
|
308
|
+
aboveCursor: false,
|
|
308
309
|
icons: true,
|
|
309
310
|
addToOptions: []
|
|
310
311
|
}, {
|
|
@@ -479,9 +480,9 @@ class CompletionTooltip {
|
|
|
479
480
|
if (!sel || !this.info)
|
|
480
481
|
return null;
|
|
481
482
|
let rect = this.dom.getBoundingClientRect(), infoRect = this.info.getBoundingClientRect();
|
|
482
|
-
|
|
483
|
-
if (top < 0 || top > this.list.clientHeight - 10)
|
|
483
|
+
if (rect.top > innerHeight - 10 || rect.bottom < 10)
|
|
484
484
|
return null;
|
|
485
|
+
let top = Math.max(0, Math.min(sel.getBoundingClientRect().top, innerHeight - infoRect.height)) - rect.top;
|
|
485
486
|
let left = this.view.textDirection == Direction.RTL;
|
|
486
487
|
let spaceLeft = rect.left, spaceRight = innerWidth - rect.right;
|
|
487
488
|
if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
|
|
@@ -491,10 +492,12 @@ class CompletionTooltip {
|
|
|
491
492
|
return { top, left };
|
|
492
493
|
}
|
|
493
494
|
positionInfo(pos) {
|
|
494
|
-
if (this.info
|
|
495
|
-
this.info.style.top = pos.top + "px";
|
|
496
|
-
|
|
497
|
-
|
|
495
|
+
if (this.info) {
|
|
496
|
+
this.info.style.top = (pos ? pos.top : -1e6) + "px";
|
|
497
|
+
if (pos) {
|
|
498
|
+
this.info.classList.toggle("cm-completionInfo-left", pos.left);
|
|
499
|
+
this.info.classList.toggle("cm-completionInfo-right", !pos.left);
|
|
500
|
+
}
|
|
498
501
|
}
|
|
499
502
|
}
|
|
500
503
|
createListBox(options, id, range) {
|
|
@@ -566,7 +569,8 @@ function sortOptions(active, state) {
|
|
|
566
569
|
for (let opt of options.sort(cmpOption)) {
|
|
567
570
|
if (result.length == MaxOptions)
|
|
568
571
|
break;
|
|
569
|
-
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail
|
|
572
|
+
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail ||
|
|
573
|
+
prev.type != opt.completion.type || prev.apply != opt.completion.apply)
|
|
570
574
|
result.push(opt);
|
|
571
575
|
else if (score(opt.completion) > score(prev))
|
|
572
576
|
result[result.length - 1] = opt;
|
|
@@ -586,7 +590,7 @@ class CompletionDialog {
|
|
|
586
590
|
return selected == this.selected || selected >= this.options.length ? this
|
|
587
591
|
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected);
|
|
588
592
|
}
|
|
589
|
-
static build(active, state, id, prev) {
|
|
593
|
+
static build(active, state, id, prev, conf) {
|
|
590
594
|
let options = sortOptions(active, state);
|
|
591
595
|
if (!options.length)
|
|
592
596
|
return null;
|
|
@@ -600,7 +604,8 @@ class CompletionDialog {
|
|
|
600
604
|
}
|
|
601
605
|
return new CompletionDialog(options, makeAttrs(id, selected), {
|
|
602
606
|
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
603
|
-
create: completionTooltip(completionState)
|
|
607
|
+
create: completionTooltip(completionState),
|
|
608
|
+
above: conf.aboveCursor,
|
|
604
609
|
}, prev ? prev.timestamp : Date.now(), selected);
|
|
605
610
|
}
|
|
606
611
|
map(changes) {
|
|
@@ -628,7 +633,7 @@ class CompletionState {
|
|
|
628
633
|
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
629
634
|
active = this.active;
|
|
630
635
|
let open = tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
631
|
-
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open)
|
|
636
|
+
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open, conf)
|
|
632
637
|
: this.open && tr.docChanged ? this.open.map(tr.changes) : this.open;
|
|
633
638
|
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
634
639
|
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
@@ -964,16 +969,19 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
964
969
|
"& > ul": {
|
|
965
970
|
fontFamily: "monospace",
|
|
966
971
|
whiteSpace: "nowrap",
|
|
967
|
-
overflow: "auto",
|
|
972
|
+
overflow: "hidden auto",
|
|
968
973
|
maxWidth_fallback: "700px",
|
|
969
974
|
maxWidth: "min(700px, 95vw)",
|
|
975
|
+
minWidth: "250px",
|
|
970
976
|
maxHeight: "10em",
|
|
971
977
|
listStyle: "none",
|
|
972
978
|
margin: 0,
|
|
973
979
|
padding: 0,
|
|
974
980
|
"& > li": {
|
|
981
|
+
overflowX: "hidden",
|
|
982
|
+
textOverflow: "ellipsis",
|
|
975
983
|
cursor: "pointer",
|
|
976
|
-
padding: "1px
|
|
984
|
+
padding: "1px 3px",
|
|
977
985
|
lineHeight: 1.2
|
|
978
986
|
},
|
|
979
987
|
}
|
|
@@ -1104,7 +1112,7 @@ class Snippet {
|
|
|
1104
1112
|
let lines = [], positions = [], m;
|
|
1105
1113
|
for (let line of template.split(/\r\n?|\n/)) {
|
|
1106
1114
|
while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|([^}]*))\}/.exec(line)) {
|
|
1107
|
-
let seq = m[1] ? +m[1] : null, name = m[2] || m[3], found = -1;
|
|
1115
|
+
let seq = m[1] ? +m[1] : null, name = m[2] || m[3] || "", found = -1;
|
|
1108
1116
|
for (let i = 0; i < fields.length; i++) {
|
|
1109
1117
|
if (seq != null ? fields[i].seq == seq : name ? fields[i].name == name : false)
|
|
1110
1118
|
found = i;
|
|
@@ -1113,7 +1121,7 @@ class Snippet {
|
|
|
1113
1121
|
let i = 0;
|
|
1114
1122
|
while (i < fields.length && (seq == null || (fields[i].seq != null && fields[i].seq < seq)))
|
|
1115
1123
|
i++;
|
|
1116
|
-
fields.splice(i, 0, { seq, name
|
|
1124
|
+
fields.splice(i, 0, { seq, name });
|
|
1117
1125
|
found = i;
|
|
1118
1126
|
for (let pos of positions)
|
|
1119
1127
|
if (pos.field >= found)
|