@atlaskit/editor-plugin-autocomplete 4.0.0 → 4.0.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
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-autocomplete
|
|
2
2
|
|
|
3
|
+
## 4.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`560ddb7a914f6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/560ddb7a914f6) -
|
|
8
|
+
[ux] Fixes a bug where autocomplete suggestions were shown when the cursor was positioned in the
|
|
9
|
+
middle of an existing word. Suggestions are now suppressed unless the cursor is at the trailing
|
|
10
|
+
edge of a token.
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
3
13
|
## 4.0.0
|
|
4
14
|
|
|
5
15
|
### Major Changes
|
|
@@ -188,6 +188,38 @@ var buildSlowLaneText = function buildSlowLaneText(docText, context) {
|
|
|
188
188
|
lines.push("reply ".concat(nextReplyNumber, ": ").concat(docText));
|
|
189
189
|
return lines.join('\n');
|
|
190
190
|
};
|
|
191
|
+
var createMidWordCharacterRegex = function createMidWordCharacterRegex() {
|
|
192
|
+
try {
|
|
193
|
+
// string-built regex avoids TS1501 under the package's ES5 build target
|
|
194
|
+
return new RegExp('[\\p{L}\\p{N}_]', 'u');
|
|
195
|
+
} catch (_unused) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
var midWordCharacterRegex = createMidWordCharacterRegex();
|
|
200
|
+
var isAsciiWordCharacter = function isAsciiWordCharacter(char) {
|
|
201
|
+
if (char === '_') {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
var charCode = char.charCodeAt(0);
|
|
205
|
+
return charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122;
|
|
206
|
+
};
|
|
207
|
+
var isMidWordCharacter = function isMidWordCharacter(char) {
|
|
208
|
+
if (midWordCharacterRegex) {
|
|
209
|
+
return midWordCharacterRegex.test(char);
|
|
210
|
+
}
|
|
211
|
+
if (isAsciiWordCharacter(char)) {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
return char.toLocaleLowerCase() !== char.toLocaleUpperCase();
|
|
215
|
+
};
|
|
216
|
+
var getLeadingTextCharacter = function getLeadingTextCharacter(text) {
|
|
217
|
+
var firstCodePoint = text === null || text === void 0 ? void 0 : text.codePointAt(0);
|
|
218
|
+
if (firstCodePoint === undefined) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
return String.fromCodePoint(firstCodePoint);
|
|
222
|
+
};
|
|
191
223
|
var getTypedLengthForPrediction = function getTypedLengthForPrediction(textBefore) {
|
|
192
224
|
var _textBefore$match$, _textBefore$match;
|
|
193
225
|
if ((0, _slowLaneClient.isWordBoundary)(textBefore)) {
|
|
@@ -440,6 +472,19 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
440
472
|
if (!selection.empty) {
|
|
441
473
|
return;
|
|
442
474
|
}
|
|
475
|
+
|
|
476
|
+
// Suppress suggestions when the cursor is mid-word — only offer
|
|
477
|
+
// completions when the cursor is at the trailing edge of a token.
|
|
478
|
+
// nodeAfter correctly handles inline atoms (mentions, emojis) where
|
|
479
|
+
// parentOffset and textContent indices diverge.
|
|
480
|
+
var nodeAfter = selection.$from.nodeAfter;
|
|
481
|
+
var charAfterCursor = nodeAfter !== null && nodeAfter !== void 0 && nodeAfter.isText ? getLeadingTextCharacter(nodeAfter.text) : undefined;
|
|
482
|
+
// Only suppress for Unicode letters, digits, and underscore — hyphens,
|
|
483
|
+
// apostrophes, and similar punctuation are valid left-edge boundaries
|
|
484
|
+
// and should not block suggestions (e.g. cursor before '-' in compound-word).
|
|
485
|
+
if (charAfterCursor && isMidWordCharacter(charAfterCursor)) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
443
488
|
var textBefore = getTextBeforeCursor(state);
|
|
444
489
|
|
|
445
490
|
// Suppress re-showing the same suggestion the user just dismissed.
|
|
@@ -176,6 +176,38 @@ const buildSlowLaneText = (docText, context) => {
|
|
|
176
176
|
lines.push(`reply ${nextReplyNumber}: ${docText}`);
|
|
177
177
|
return lines.join('\n');
|
|
178
178
|
};
|
|
179
|
+
const createMidWordCharacterRegex = () => {
|
|
180
|
+
try {
|
|
181
|
+
// string-built regex avoids TS1501 under the package's ES5 build target
|
|
182
|
+
return new RegExp('[\\p{L}\\p{N}_]', 'u');
|
|
183
|
+
} catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const midWordCharacterRegex = createMidWordCharacterRegex();
|
|
188
|
+
const isAsciiWordCharacter = char => {
|
|
189
|
+
if (char === '_') {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
const charCode = char.charCodeAt(0);
|
|
193
|
+
return charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122;
|
|
194
|
+
};
|
|
195
|
+
const isMidWordCharacter = char => {
|
|
196
|
+
if (midWordCharacterRegex) {
|
|
197
|
+
return midWordCharacterRegex.test(char);
|
|
198
|
+
}
|
|
199
|
+
if (isAsciiWordCharacter(char)) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return char.toLocaleLowerCase() !== char.toLocaleUpperCase();
|
|
203
|
+
};
|
|
204
|
+
const getLeadingTextCharacter = text => {
|
|
205
|
+
const firstCodePoint = text === null || text === void 0 ? void 0 : text.codePointAt(0);
|
|
206
|
+
if (firstCodePoint === undefined) {
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
return String.fromCodePoint(firstCodePoint);
|
|
210
|
+
};
|
|
179
211
|
const getTypedLengthForPrediction = textBefore => {
|
|
180
212
|
var _textBefore$match$, _textBefore$match;
|
|
181
213
|
if (isWordBoundary(textBefore)) {
|
|
@@ -424,6 +456,19 @@ export const createAutocompletePlugin = (options, api) => {
|
|
|
424
456
|
if (!selection.empty) {
|
|
425
457
|
return;
|
|
426
458
|
}
|
|
459
|
+
|
|
460
|
+
// Suppress suggestions when the cursor is mid-word — only offer
|
|
461
|
+
// completions when the cursor is at the trailing edge of a token.
|
|
462
|
+
// nodeAfter correctly handles inline atoms (mentions, emojis) where
|
|
463
|
+
// parentOffset and textContent indices diverge.
|
|
464
|
+
const nodeAfter = selection.$from.nodeAfter;
|
|
465
|
+
const charAfterCursor = nodeAfter !== null && nodeAfter !== void 0 && nodeAfter.isText ? getLeadingTextCharacter(nodeAfter.text) : undefined;
|
|
466
|
+
// Only suppress for Unicode letters, digits, and underscore — hyphens,
|
|
467
|
+
// apostrophes, and similar punctuation are valid left-edge boundaries
|
|
468
|
+
// and should not block suggestions (e.g. cursor before '-' in compound-word).
|
|
469
|
+
if (charAfterCursor && isMidWordCharacter(charAfterCursor)) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
427
472
|
const textBefore = getTextBeforeCursor(state);
|
|
428
473
|
|
|
429
474
|
// Suppress re-showing the same suggestion the user just dismissed.
|
|
@@ -181,6 +181,38 @@ var buildSlowLaneText = function buildSlowLaneText(docText, context) {
|
|
|
181
181
|
lines.push("reply ".concat(nextReplyNumber, ": ").concat(docText));
|
|
182
182
|
return lines.join('\n');
|
|
183
183
|
};
|
|
184
|
+
var createMidWordCharacterRegex = function createMidWordCharacterRegex() {
|
|
185
|
+
try {
|
|
186
|
+
// string-built regex avoids TS1501 under the package's ES5 build target
|
|
187
|
+
return new RegExp('[\\p{L}\\p{N}_]', 'u');
|
|
188
|
+
} catch (_unused) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var midWordCharacterRegex = createMidWordCharacterRegex();
|
|
193
|
+
var isAsciiWordCharacter = function isAsciiWordCharacter(char) {
|
|
194
|
+
if (char === '_') {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
var charCode = char.charCodeAt(0);
|
|
198
|
+
return charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122;
|
|
199
|
+
};
|
|
200
|
+
var isMidWordCharacter = function isMidWordCharacter(char) {
|
|
201
|
+
if (midWordCharacterRegex) {
|
|
202
|
+
return midWordCharacterRegex.test(char);
|
|
203
|
+
}
|
|
204
|
+
if (isAsciiWordCharacter(char)) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
return char.toLocaleLowerCase() !== char.toLocaleUpperCase();
|
|
208
|
+
};
|
|
209
|
+
var getLeadingTextCharacter = function getLeadingTextCharacter(text) {
|
|
210
|
+
var firstCodePoint = text === null || text === void 0 ? void 0 : text.codePointAt(0);
|
|
211
|
+
if (firstCodePoint === undefined) {
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
return String.fromCodePoint(firstCodePoint);
|
|
215
|
+
};
|
|
184
216
|
var getTypedLengthForPrediction = function getTypedLengthForPrediction(textBefore) {
|
|
185
217
|
var _textBefore$match$, _textBefore$match;
|
|
186
218
|
if (isWordBoundary(textBefore)) {
|
|
@@ -433,6 +465,19 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
|
|
|
433
465
|
if (!selection.empty) {
|
|
434
466
|
return;
|
|
435
467
|
}
|
|
468
|
+
|
|
469
|
+
// Suppress suggestions when the cursor is mid-word — only offer
|
|
470
|
+
// completions when the cursor is at the trailing edge of a token.
|
|
471
|
+
// nodeAfter correctly handles inline atoms (mentions, emojis) where
|
|
472
|
+
// parentOffset and textContent indices diverge.
|
|
473
|
+
var nodeAfter = selection.$from.nodeAfter;
|
|
474
|
+
var charAfterCursor = nodeAfter !== null && nodeAfter !== void 0 && nodeAfter.isText ? getLeadingTextCharacter(nodeAfter.text) : undefined;
|
|
475
|
+
// Only suppress for Unicode letters, digits, and underscore — hyphens,
|
|
476
|
+
// apostrophes, and similar punctuation are valid left-edge boundaries
|
|
477
|
+
// and should not block suggestions (e.g. cursor before '-' in compound-word).
|
|
478
|
+
if (charAfterCursor && isMidWordCharacter(charAfterCursor)) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
436
481
|
var textBefore = getTextBeforeCursor(state);
|
|
437
482
|
|
|
438
483
|
// Suppress re-showing the same suggestion the user just dismissed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-autocomplete",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Client-side text autocomplete plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"wink-nlp": "^2.4.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@atlaskit/editor-common": "^116.
|
|
30
|
+
"@atlaskit/editor-common": "^116.4.0",
|
|
31
31
|
"@atlaskit/editor-plugin-analytics": "^12.0.0",
|
|
32
32
|
"react": "^18.2.0"
|
|
33
33
|
},
|
|
@@ -243,6 +243,52 @@ const buildSlowLaneText = (docText: string, context?: AutocompleteContext): stri
|
|
|
243
243
|
return lines.join('\n');
|
|
244
244
|
};
|
|
245
245
|
|
|
246
|
+
const createMidWordCharacterRegex = (): RegExp | null => {
|
|
247
|
+
try {
|
|
248
|
+
// string-built regex avoids TS1501 under the package's ES5 build target
|
|
249
|
+
return new RegExp('[\\p{L}\\p{N}_]', 'u');
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const midWordCharacterRegex = createMidWordCharacterRegex();
|
|
256
|
+
|
|
257
|
+
const isAsciiWordCharacter = (char: string): boolean => {
|
|
258
|
+
if (char === '_') {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const charCode = char.charCodeAt(0);
|
|
263
|
+
return (
|
|
264
|
+
(charCode >= 48 && charCode <= 57) ||
|
|
265
|
+
(charCode >= 65 && charCode <= 90) ||
|
|
266
|
+
(charCode >= 97 && charCode <= 122)
|
|
267
|
+
);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const isMidWordCharacter = (char: string): boolean => {
|
|
271
|
+
if (midWordCharacterRegex) {
|
|
272
|
+
return midWordCharacterRegex.test(char);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (isAsciiWordCharacter(char)) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return char.toLocaleLowerCase() !== char.toLocaleUpperCase();
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const getLeadingTextCharacter = (text?: string): string | undefined => {
|
|
283
|
+
const firstCodePoint = text?.codePointAt(0);
|
|
284
|
+
|
|
285
|
+
if (firstCodePoint === undefined) {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return String.fromCodePoint(firstCodePoint);
|
|
290
|
+
};
|
|
291
|
+
|
|
246
292
|
const getTypedLengthForPrediction = (textBefore: string): number => {
|
|
247
293
|
if (isWordBoundary(textBefore)) {
|
|
248
294
|
return 0;
|
|
@@ -514,6 +560,19 @@ export const createAutocompletePlugin = (
|
|
|
514
560
|
return;
|
|
515
561
|
}
|
|
516
562
|
|
|
563
|
+
// Suppress suggestions when the cursor is mid-word — only offer
|
|
564
|
+
// completions when the cursor is at the trailing edge of a token.
|
|
565
|
+
// nodeAfter correctly handles inline atoms (mentions, emojis) where
|
|
566
|
+
// parentOffset and textContent indices diverge.
|
|
567
|
+
const nodeAfter = selection.$from.nodeAfter;
|
|
568
|
+
const charAfterCursor = nodeAfter?.isText ? getLeadingTextCharacter(nodeAfter.text) : undefined;
|
|
569
|
+
// Only suppress for Unicode letters, digits, and underscore — hyphens,
|
|
570
|
+
// apostrophes, and similar punctuation are valid left-edge boundaries
|
|
571
|
+
// and should not block suggestions (e.g. cursor before '-' in compound-word).
|
|
572
|
+
if (charAfterCursor && isMidWordCharacter(charAfterCursor)) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
|
|
517
576
|
const textBefore = getTextBeforeCursor(state);
|
|
518
577
|
|
|
519
578
|
// Suppress re-showing the same suggestion the user just dismissed.
|