@codemirror/autocomplete 0.19.9 → 0.19.10

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 CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.19.10 (2022-01-05)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure the info tooltip is hidden when the selected option is scrolled out of view.
6
+
7
+ Fix a bug in the completion ranking that would sometimes give options that match the input by word start chars higher scores than appropriate.
8
+
9
+ Options are now sorted (ascending) by length when their match score is otherwise identical.
10
+
1
11
  ## 0.19.9 (2021-11-26)
2
12
 
3
13
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -246,7 +246,7 @@ class FuzzyMatcher {
246
246
  let byWordTo = 0, byWordFolded = false;
247
247
  // If we've found a partial adjacent match, these track its state
248
248
  let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
249
- let hasLower = /[a-z]/.test(word);
249
+ let hasLower = /[a-z]/.test(word), wordAdjacent = true;
250
250
  // Go over the option's text, scanning for the various kinds of matches
251
251
  for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
252
252
  let next = text.codePointAt(word, i);
@@ -268,26 +268,30 @@ class FuzzyMatcher {
268
268
  let ch, type = next < 0xff
269
269
  ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
270
270
  : ((ch = text.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
271
- if ((type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) &&
272
- (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true))))
273
- byWord[byWordTo++] = i;
271
+ if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
272
+ if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
273
+ byWord[byWordTo++] = i;
274
+ else if (byWord.length)
275
+ wordAdjacent = false;
276
+ }
274
277
  prevType = type;
275
278
  i += text.codePointSize(next);
276
279
  }
277
- if (byWordTo == len && byWord[0] == 0)
280
+ if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
278
281
  return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
279
282
  if (adjacentTo == len && adjacentStart == 0)
280
- return [-200 /* CaseFold */, 0, adjacentEnd];
283
+ return [-200 /* CaseFold */ - word.length, 0, adjacentEnd];
281
284
  if (direct > -1)
282
- return [-700 /* NotStart */, direct, direct + this.pattern.length];
285
+ return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
283
286
  if (adjacentTo == len)
284
- return [-200 /* CaseFold */ + -700 /* NotStart */, adjacentStart, adjacentEnd];
287
+ return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
285
288
  if (byWordTo == len)
286
- return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */, byWord, word);
289
+ return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
290
+ (wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
287
291
  return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
288
292
  }
289
293
  result(score, positions, word) {
290
- let result = [score], i = 1;
294
+ let result = [score - word.length], i = 1;
291
295
  for (let pos of positions) {
292
296
  let to = pos + (this.astral ? text.codePointSize(text.codePointAt(word, pos)) : 1);
293
297
  if (i > 1 && result[i - 1] == pos)
@@ -483,12 +487,14 @@ class CompletionTooltip {
483
487
  let sel = this.dom.querySelector("[aria-selected]");
484
488
  if (!sel || !this.info)
485
489
  return null;
486
- let rect = this.dom.getBoundingClientRect(), infoRect = this.info.getBoundingClientRect();
487
- if (rect.top > innerHeight - 10 || rect.bottom < 10)
490
+ let listRect = this.dom.getBoundingClientRect();
491
+ let infoRect = this.info.getBoundingClientRect();
492
+ let selRect = sel.getBoundingClientRect();
493
+ if (selRect.top > Math.min(innerHeight, listRect.bottom) - 10 || selRect.bottom < Math.max(0, listRect.top) + 10)
488
494
  return null;
489
- let top = Math.max(0, Math.min(sel.getBoundingClientRect().top, innerHeight - infoRect.height)) - rect.top;
495
+ let top = Math.max(0, Math.min(selRect.top, innerHeight - infoRect.height)) - listRect.top;
490
496
  let left = this.view.textDirection == view.Direction.RTL;
491
- let spaceLeft = rect.left, spaceRight = innerWidth - rect.right;
497
+ let spaceLeft = listRect.left, spaceRight = innerWidth - listRect.right;
492
498
  if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
493
499
  left = false;
494
500
  else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
package/dist/index.js CHANGED
@@ -242,7 +242,7 @@ class FuzzyMatcher {
242
242
  let byWordTo = 0, byWordFolded = false;
243
243
  // If we've found a partial adjacent match, these track its state
244
244
  let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
245
- let hasLower = /[a-z]/.test(word);
245
+ let hasLower = /[a-z]/.test(word), wordAdjacent = true;
246
246
  // Go over the option's text, scanning for the various kinds of matches
247
247
  for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
248
248
  let next = codePointAt(word, i);
@@ -264,26 +264,30 @@ class FuzzyMatcher {
264
264
  let ch, type = next < 0xff
265
265
  ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
266
266
  : ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
267
- if ((type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) &&
268
- (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true))))
269
- byWord[byWordTo++] = i;
267
+ if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
268
+ if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
269
+ byWord[byWordTo++] = i;
270
+ else if (byWord.length)
271
+ wordAdjacent = false;
272
+ }
270
273
  prevType = type;
271
274
  i += codePointSize(next);
272
275
  }
273
- if (byWordTo == len && byWord[0] == 0)
276
+ if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
274
277
  return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
275
278
  if (adjacentTo == len && adjacentStart == 0)
276
- return [-200 /* CaseFold */, 0, adjacentEnd];
279
+ return [-200 /* CaseFold */ - word.length, 0, adjacentEnd];
277
280
  if (direct > -1)
278
- return [-700 /* NotStart */, direct, direct + this.pattern.length];
281
+ return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
279
282
  if (adjacentTo == len)
280
- return [-200 /* CaseFold */ + -700 /* NotStart */, adjacentStart, adjacentEnd];
283
+ return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
281
284
  if (byWordTo == len)
282
- return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */, byWord, word);
285
+ return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
286
+ (wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
283
287
  return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
284
288
  }
285
289
  result(score, positions, word) {
286
- let result = [score], i = 1;
290
+ let result = [score - word.length], i = 1;
287
291
  for (let pos of positions) {
288
292
  let to = pos + (this.astral ? codePointSize(codePointAt(word, pos)) : 1);
289
293
  if (i > 1 && result[i - 1] == pos)
@@ -479,12 +483,14 @@ class CompletionTooltip {
479
483
  let sel = this.dom.querySelector("[aria-selected]");
480
484
  if (!sel || !this.info)
481
485
  return null;
482
- let rect = this.dom.getBoundingClientRect(), infoRect = this.info.getBoundingClientRect();
483
- if (rect.top > innerHeight - 10 || rect.bottom < 10)
486
+ let listRect = this.dom.getBoundingClientRect();
487
+ let infoRect = this.info.getBoundingClientRect();
488
+ let selRect = sel.getBoundingClientRect();
489
+ if (selRect.top > Math.min(innerHeight, listRect.bottom) - 10 || selRect.bottom < Math.max(0, listRect.top) + 10)
484
490
  return null;
485
- let top = Math.max(0, Math.min(sel.getBoundingClientRect().top, innerHeight - infoRect.height)) - rect.top;
491
+ let top = Math.max(0, Math.min(selRect.top, innerHeight - infoRect.height)) - listRect.top;
486
492
  let left = this.view.textDirection == Direction.RTL;
487
- let spaceLeft = rect.left, spaceRight = innerWidth - rect.right;
493
+ let spaceLeft = listRect.left, spaceRight = innerWidth - listRect.right;
488
494
  if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
489
495
  left = false;
490
496
  else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/autocomplete",
3
- "version": "0.19.9",
3
+ "version": "0.19.10",
4
4
  "description": "Autocompletion for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",