@codemirror/autocomplete 6.2.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/index.cjs +28 -11
- package/dist/index.d.ts +7 -1
- package/dist/index.js +28 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -509,7 +509,7 @@ class CompletionTooltip {
|
|
|
509
509
|
let sel = this.dom.querySelector("[aria-selected]");
|
|
510
510
|
if (!sel || !this.info)
|
|
511
511
|
return null;
|
|
512
|
-
let win = this.dom.ownerDocument.defaultView;
|
|
512
|
+
let win = this.dom.ownerDocument.defaultView || window;
|
|
513
513
|
let listRect = this.dom.getBoundingClientRect();
|
|
514
514
|
let infoRect = this.info.getBoundingClientRect();
|
|
515
515
|
let selRect = sel.getBoundingClientRect();
|
|
@@ -1091,6 +1091,7 @@ const baseTheme = view.EditorView.baseTheme({
|
|
|
1091
1091
|
verticalAlign: "text-top",
|
|
1092
1092
|
width: 0,
|
|
1093
1093
|
height: "1.15em",
|
|
1094
|
+
display: "inline-block",
|
|
1094
1095
|
margin: "0 -0.7px -.7em",
|
|
1095
1096
|
borderLeft: "1.4px dotted #888"
|
|
1096
1097
|
},
|
|
@@ -1474,7 +1475,8 @@ const completeAnyWord = context => {
|
|
|
1474
1475
|
|
|
1475
1476
|
const defaults = {
|
|
1476
1477
|
brackets: ["(", "[", "{", "'", '"'],
|
|
1477
|
-
before: ")]}:;>"
|
|
1478
|
+
before: ")]}:;>",
|
|
1479
|
+
stringPrefixes: []
|
|
1478
1480
|
};
|
|
1479
1481
|
const closeBracketEffect = state.StateEffect.define({
|
|
1480
1482
|
map(value, mapping) {
|
|
@@ -1590,7 +1592,7 @@ function insertBracket(state$1, bracket) {
|
|
|
1590
1592
|
for (let tok of tokens) {
|
|
1591
1593
|
let closed = closing(state.codePointAt(tok, 0));
|
|
1592
1594
|
if (bracket == tok)
|
|
1593
|
-
return closed == tok ? handleSame(state$1, tok, tokens.indexOf(tok + tok + tok) > -1)
|
|
1595
|
+
return closed == tok ? handleSame(state$1, tok, tokens.indexOf(tok + tok + tok) > -1, conf)
|
|
1594
1596
|
: handleOpen(state$1, tok, closed, conf.before || defaults.before);
|
|
1595
1597
|
if (bracket == closed && closedBracketAt(state$1, state$1.selection.main.from))
|
|
1596
1598
|
return handleClose(state$1, tok, closed);
|
|
@@ -1645,13 +1647,14 @@ function handleClose(state$1, _open, close) {
|
|
|
1645
1647
|
}
|
|
1646
1648
|
// Handles cases where the open and close token are the same, and
|
|
1647
1649
|
// possibly triple quotes (as in `"""abc"""`-style quoting).
|
|
1648
|
-
function handleSame(state$1, token, allowTriple) {
|
|
1650
|
+
function handleSame(state$1, token, allowTriple, config) {
|
|
1651
|
+
let stringPrefixes = config.stringPrefixes || defaults.stringPrefixes;
|
|
1649
1652
|
let dont = null, changes = state$1.changeByRange(range => {
|
|
1650
1653
|
if (!range.empty)
|
|
1651
1654
|
return { changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }],
|
|
1652
1655
|
effects: closeBracketEffect.of(range.to + token.length),
|
|
1653
1656
|
range: state.EditorSelection.range(range.anchor + token.length, range.head + token.length) };
|
|
1654
|
-
let pos = range.head, next = nextChar(state$1.doc, pos);
|
|
1657
|
+
let pos = range.head, next = nextChar(state$1.doc, pos), start;
|
|
1655
1658
|
if (next == token) {
|
|
1656
1659
|
if (nodeStart(state$1, pos)) {
|
|
1657
1660
|
return { changes: { insert: token + token, from: pos },
|
|
@@ -1665,14 +1668,14 @@ function handleSame(state$1, token, allowTriple) {
|
|
|
1665
1668
|
}
|
|
1666
1669
|
}
|
|
1667
1670
|
else if (allowTriple && state$1.sliceDoc(pos - 2 * token.length, pos) == token + token &&
|
|
1668
|
-
|
|
1671
|
+
(start = canStartStringAt(state$1, pos - 2 * token.length, stringPrefixes)) > -1 &&
|
|
1672
|
+
nodeStart(state$1, start)) {
|
|
1669
1673
|
return { changes: { insert: token + token + token + token, from: pos },
|
|
1670
1674
|
effects: closeBracketEffect.of(pos + token.length),
|
|
1671
1675
|
range: state.EditorSelection.cursor(pos + token.length) };
|
|
1672
1676
|
}
|
|
1673
1677
|
else if (state$1.charCategorizer(pos)(next) != state.CharCategory.Word) {
|
|
1674
|
-
|
|
1675
|
-
if (prev != token && state$1.charCategorizer(pos)(prev) != state.CharCategory.Word && !probablyInString(state$1, pos, token))
|
|
1678
|
+
if (canStartStringAt(state$1, pos, stringPrefixes) > -1 && !probablyInString(state$1, pos, token, stringPrefixes))
|
|
1676
1679
|
return { changes: { insert: token + token, from: pos },
|
|
1677
1680
|
effects: closeBracketEffect.of(pos + token.length),
|
|
1678
1681
|
range: state.EditorSelection.cursor(pos + token.length) };
|
|
@@ -1688,12 +1691,15 @@ function nodeStart(state, pos) {
|
|
|
1688
1691
|
let tree = language.syntaxTree(state).resolveInner(pos + 1);
|
|
1689
1692
|
return tree.parent && tree.from == pos;
|
|
1690
1693
|
}
|
|
1691
|
-
function probablyInString(state, pos, quoteToken) {
|
|
1694
|
+
function probablyInString(state, pos, quoteToken, prefixes) {
|
|
1692
1695
|
let node = language.syntaxTree(state).resolveInner(pos, -1);
|
|
1696
|
+
let maxPrefix = prefixes.reduce((m, p) => Math.max(m, p.length), 0);
|
|
1693
1697
|
for (let i = 0; i < 5; i++) {
|
|
1694
|
-
|
|
1698
|
+
let start = state.sliceDoc(node.from, Math.min(node.to, node.from + quoteToken.length + maxPrefix));
|
|
1699
|
+
let quotePos = start.indexOf(quoteToken);
|
|
1700
|
+
if (!quotePos || quotePos > -1 && prefixes.indexOf(start.slice(0, quotePos)) > -1) {
|
|
1695
1701
|
let first = node.firstChild;
|
|
1696
|
-
while (first && first.from == node.from && first.to - first.from > quoteToken.length) {
|
|
1702
|
+
while (first && first.from == node.from && first.to - first.from > quoteToken.length + quotePos) {
|
|
1697
1703
|
if (state.sliceDoc(first.to - quoteToken.length, first.to) == quoteToken)
|
|
1698
1704
|
return false;
|
|
1699
1705
|
first = first.firstChild;
|
|
@@ -1707,6 +1713,17 @@ function probablyInString(state, pos, quoteToken) {
|
|
|
1707
1713
|
}
|
|
1708
1714
|
return false;
|
|
1709
1715
|
}
|
|
1716
|
+
function canStartStringAt(state$1, pos, prefixes) {
|
|
1717
|
+
let charCat = state$1.charCategorizer(pos);
|
|
1718
|
+
if (charCat(state$1.sliceDoc(pos - 1, pos)) != state.CharCategory.Word)
|
|
1719
|
+
return pos;
|
|
1720
|
+
for (let prefix of prefixes) {
|
|
1721
|
+
let start = pos - prefix.length;
|
|
1722
|
+
if (state$1.sliceDoc(start, pos) == prefix && charCat(state$1.sliceDoc(start - 1, start)) != state.CharCategory.Word)
|
|
1723
|
+
return start;
|
|
1724
|
+
}
|
|
1725
|
+
return -1;
|
|
1726
|
+
}
|
|
1710
1727
|
|
|
1711
1728
|
/**
|
|
1712
1729
|
Returns an extension that enables autocompletion.
|
package/dist/index.d.ts
CHANGED
|
@@ -66,7 +66,8 @@ interface CompletionConfig {
|
|
|
66
66
|
completion, and should produce a DOM node to show. `position`
|
|
67
67
|
determines where in the DOM the result appears, relative to
|
|
68
68
|
other added widgets and the standard content. The default icons
|
|
69
|
-
have position 20, the label position 50, and the detail position
|
|
69
|
+
have position 20, the label position 50, and the detail position
|
|
70
|
+
80.
|
|
70
71
|
*/
|
|
71
72
|
addToOptions?: {
|
|
72
73
|
render: (completion: Completion, state: EditorState) => Node | null;
|
|
@@ -404,6 +405,11 @@ interface CloseBracketConfig {
|
|
|
404
405
|
whitespace. Defaults to `")]}:;>"`.
|
|
405
406
|
*/
|
|
406
407
|
before?: string;
|
|
408
|
+
/**
|
|
409
|
+
When determining whether a given node may be a string, recognize
|
|
410
|
+
these prefixes before the opening quote.
|
|
411
|
+
*/
|
|
412
|
+
stringPrefixes?: string[];
|
|
407
413
|
}
|
|
408
414
|
/**
|
|
409
415
|
Extension to enable bracket-closing behavior. When a closeable
|
package/dist/index.js
CHANGED
|
@@ -505,7 +505,7 @@ class CompletionTooltip {
|
|
|
505
505
|
let sel = this.dom.querySelector("[aria-selected]");
|
|
506
506
|
if (!sel || !this.info)
|
|
507
507
|
return null;
|
|
508
|
-
let win = this.dom.ownerDocument.defaultView;
|
|
508
|
+
let win = this.dom.ownerDocument.defaultView || window;
|
|
509
509
|
let listRect = this.dom.getBoundingClientRect();
|
|
510
510
|
let infoRect = this.info.getBoundingClientRect();
|
|
511
511
|
let selRect = sel.getBoundingClientRect();
|
|
@@ -1087,6 +1087,7 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
1087
1087
|
verticalAlign: "text-top",
|
|
1088
1088
|
width: 0,
|
|
1089
1089
|
height: "1.15em",
|
|
1090
|
+
display: "inline-block",
|
|
1090
1091
|
margin: "0 -0.7px -.7em",
|
|
1091
1092
|
borderLeft: "1.4px dotted #888"
|
|
1092
1093
|
},
|
|
@@ -1470,7 +1471,8 @@ const completeAnyWord = context => {
|
|
|
1470
1471
|
|
|
1471
1472
|
const defaults = {
|
|
1472
1473
|
brackets: ["(", "[", "{", "'", '"'],
|
|
1473
|
-
before: ")]}:;>"
|
|
1474
|
+
before: ")]}:;>",
|
|
1475
|
+
stringPrefixes: []
|
|
1474
1476
|
};
|
|
1475
1477
|
const closeBracketEffect = /*@__PURE__*/StateEffect.define({
|
|
1476
1478
|
map(value, mapping) {
|
|
@@ -1586,7 +1588,7 @@ function insertBracket(state, bracket) {
|
|
|
1586
1588
|
for (let tok of tokens) {
|
|
1587
1589
|
let closed = closing(codePointAt(tok, 0));
|
|
1588
1590
|
if (bracket == tok)
|
|
1589
|
-
return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1)
|
|
1591
|
+
return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1, conf)
|
|
1590
1592
|
: handleOpen(state, tok, closed, conf.before || defaults.before);
|
|
1591
1593
|
if (bracket == closed && closedBracketAt(state, state.selection.main.from))
|
|
1592
1594
|
return handleClose(state, tok, closed);
|
|
@@ -1641,13 +1643,14 @@ function handleClose(state, _open, close) {
|
|
|
1641
1643
|
}
|
|
1642
1644
|
// Handles cases where the open and close token are the same, and
|
|
1643
1645
|
// possibly triple quotes (as in `"""abc"""`-style quoting).
|
|
1644
|
-
function handleSame(state, token, allowTriple) {
|
|
1646
|
+
function handleSame(state, token, allowTriple, config) {
|
|
1647
|
+
let stringPrefixes = config.stringPrefixes || defaults.stringPrefixes;
|
|
1645
1648
|
let dont = null, changes = state.changeByRange(range => {
|
|
1646
1649
|
if (!range.empty)
|
|
1647
1650
|
return { changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }],
|
|
1648
1651
|
effects: closeBracketEffect.of(range.to + token.length),
|
|
1649
1652
|
range: EditorSelection.range(range.anchor + token.length, range.head + token.length) };
|
|
1650
|
-
let pos = range.head, next = nextChar(state.doc, pos);
|
|
1653
|
+
let pos = range.head, next = nextChar(state.doc, pos), start;
|
|
1651
1654
|
if (next == token) {
|
|
1652
1655
|
if (nodeStart(state, pos)) {
|
|
1653
1656
|
return { changes: { insert: token + token, from: pos },
|
|
@@ -1661,14 +1664,14 @@ function handleSame(state, token, allowTriple) {
|
|
|
1661
1664
|
}
|
|
1662
1665
|
}
|
|
1663
1666
|
else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token &&
|
|
1664
|
-
|
|
1667
|
+
(start = canStartStringAt(state, pos - 2 * token.length, stringPrefixes)) > -1 &&
|
|
1668
|
+
nodeStart(state, start)) {
|
|
1665
1669
|
return { changes: { insert: token + token + token + token, from: pos },
|
|
1666
1670
|
effects: closeBracketEffect.of(pos + token.length),
|
|
1667
1671
|
range: EditorSelection.cursor(pos + token.length) };
|
|
1668
1672
|
}
|
|
1669
1673
|
else if (state.charCategorizer(pos)(next) != CharCategory.Word) {
|
|
1670
|
-
|
|
1671
|
-
if (prev != token && state.charCategorizer(pos)(prev) != CharCategory.Word && !probablyInString(state, pos, token))
|
|
1674
|
+
if (canStartStringAt(state, pos, stringPrefixes) > -1 && !probablyInString(state, pos, token, stringPrefixes))
|
|
1672
1675
|
return { changes: { insert: token + token, from: pos },
|
|
1673
1676
|
effects: closeBracketEffect.of(pos + token.length),
|
|
1674
1677
|
range: EditorSelection.cursor(pos + token.length) };
|
|
@@ -1684,12 +1687,15 @@ function nodeStart(state, pos) {
|
|
|
1684
1687
|
let tree = syntaxTree(state).resolveInner(pos + 1);
|
|
1685
1688
|
return tree.parent && tree.from == pos;
|
|
1686
1689
|
}
|
|
1687
|
-
function probablyInString(state, pos, quoteToken) {
|
|
1690
|
+
function probablyInString(state, pos, quoteToken, prefixes) {
|
|
1688
1691
|
let node = syntaxTree(state).resolveInner(pos, -1);
|
|
1692
|
+
let maxPrefix = prefixes.reduce((m, p) => Math.max(m, p.length), 0);
|
|
1689
1693
|
for (let i = 0; i < 5; i++) {
|
|
1690
|
-
|
|
1694
|
+
let start = state.sliceDoc(node.from, Math.min(node.to, node.from + quoteToken.length + maxPrefix));
|
|
1695
|
+
let quotePos = start.indexOf(quoteToken);
|
|
1696
|
+
if (!quotePos || quotePos > -1 && prefixes.indexOf(start.slice(0, quotePos)) > -1) {
|
|
1691
1697
|
let first = node.firstChild;
|
|
1692
|
-
while (first && first.from == node.from && first.to - first.from > quoteToken.length) {
|
|
1698
|
+
while (first && first.from == node.from && first.to - first.from > quoteToken.length + quotePos) {
|
|
1693
1699
|
if (state.sliceDoc(first.to - quoteToken.length, first.to) == quoteToken)
|
|
1694
1700
|
return false;
|
|
1695
1701
|
first = first.firstChild;
|
|
@@ -1703,6 +1709,17 @@ function probablyInString(state, pos, quoteToken) {
|
|
|
1703
1709
|
}
|
|
1704
1710
|
return false;
|
|
1705
1711
|
}
|
|
1712
|
+
function canStartStringAt(state, pos, prefixes) {
|
|
1713
|
+
let charCat = state.charCategorizer(pos);
|
|
1714
|
+
if (charCat(state.sliceDoc(pos - 1, pos)) != CharCategory.Word)
|
|
1715
|
+
return pos;
|
|
1716
|
+
for (let prefix of prefixes) {
|
|
1717
|
+
let start = pos - prefix.length;
|
|
1718
|
+
if (state.sliceDoc(start, pos) == prefix && charCat(state.sliceDoc(start - 1, start)) != CharCategory.Word)
|
|
1719
|
+
return start;
|
|
1720
|
+
}
|
|
1721
|
+
return -1;
|
|
1722
|
+
}
|
|
1706
1723
|
|
|
1707
1724
|
/**
|
|
1708
1725
|
Returns an extension that enables autocompletion.
|