@atlaskit/editor-plugin-autocomplete 0.2.0 → 0.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/afm-cc/tsconfig.json +1 -4
  3. package/afm-jira/tsconfig.json +1 -4
  4. package/afm-products/tsconfig.json +1 -4
  5. package/build/tsconfig.json +2 -6
  6. package/build/url-module.d.ts +8 -0
  7. package/dist/cjs/pm-plugins/autocomplete-plugin.js +11 -4
  8. package/dist/cjs/pm-plugins/scoring-pipeline.js +1 -3
  9. package/dist/cjs/pm-plugins/slow-lane-client.js +3 -1
  10. package/dist/cjs/pm-plugins/text-predictor.js +32 -22
  11. package/dist/es2019/pm-plugins/autocomplete-plugin.js +11 -3
  12. package/dist/es2019/pm-plugins/scoring-pipeline.js +0 -3
  13. package/dist/es2019/pm-plugins/slow-lane-client.js +5 -2
  14. package/dist/es2019/pm-plugins/text-predictor.js +16 -9
  15. package/dist/esm/pm-plugins/autocomplete-plugin.js +11 -3
  16. package/dist/esm/pm-plugins/scoring-pipeline.js +0 -3
  17. package/dist/esm/pm-plugins/slow-lane-client.js +3 -1
  18. package/dist/esm/pm-plugins/text-predictor.js +32 -22
  19. package/dist/types/pm-plugins/autocomplete-plugin.d.ts +1 -1
  20. package/dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts +1 -1
  21. package/package.json +1 -1
  22. package/src/pm-plugins/autocomplete-plugin.ts +19 -5
  23. package/src/pm-plugins/data/combined_l2_l3_pos_tags.json +73571 -3
  24. package/src/pm-plugins/data/ghost_pos_tags.json +43 -3
  25. package/src/pm-plugins/data/grammar_transitions_10k.json +46 -3
  26. package/src/pm-plugins/data/l3_vocabulary.json +20002 -3
  27. package/src/pm-plugins/data/vocabulary_10k.json +38794 -3
  28. package/src/pm-plugins/data/word_index_10k.json +7760 -3
  29. package/src/pm-plugins/scoring-pipeline.ts +0 -3
  30. package/src/pm-plugins/slow-lane-client.ts +4 -2
  31. package/src/pm-plugins/text-predictor.ts +18 -9
  32. package/tsconfig.app.json +3 -2
  33. package/tsconfig.json +2 -1
  34. package/src/pm-plugins/typings.d.ts +0 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-autocomplete
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`87965237565b6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/87965237565b6) -
8
+ [ux] Add autocomplete plugin to inline comment editor behind
9
+ `platform_editor_ai_autocomplete_conf_comments` experiment
10
+
3
11
  ## 0.2.0
4
12
 
5
13
  ### Minor Changes
@@ -6,10 +6,7 @@
6
6
  "rootDir": "../",
7
7
  "composite": true,
8
8
  "noCheck": true,
9
- // resolveJsonModule must remain false: this package contains LFS-tracked JSON data files
10
- // that appear as pointer text (not valid JSON) in CI environments where LFS is skipped.
11
- // Enabling resolveJsonModule would cause TS to attempt parsing these files and fail.
12
- "resolveJsonModule": false
9
+ "resolveJsonModule": true
13
10
  },
14
11
  "include": [
15
12
  "../src/**/*.ts",
@@ -6,10 +6,7 @@
6
6
  "rootDir": "../",
7
7
  "composite": true,
8
8
  "noCheck": true,
9
- // resolveJsonModule must remain false: this package contains LFS-tracked JSON data files
10
- // that appear as pointer text (not valid JSON) in CI environments where LFS is skipped.
11
- // Enabling resolveJsonModule would cause TS to attempt parsing these files and fail.
12
- "resolveJsonModule": false
9
+ "resolveJsonModule": true
13
10
  },
14
11
  "include": [
15
12
  "../src/**/*.ts",
@@ -6,10 +6,7 @@
6
6
  "rootDir": "../",
7
7
  "composite": true,
8
8
  "noCheck": true,
9
- // resolveJsonModule must remain false: this package contains LFS-tracked JSON data files
10
- // that appear as pointer text (not valid JSON) in CI environments where LFS is skipped.
11
- // Enabling resolveJsonModule would cause TS to attempt parsing these files and fail.
12
- "resolveJsonModule": false
9
+ "resolveJsonModule": true
13
10
  },
14
11
  "include": [
15
12
  "../src/**/*.ts",
@@ -2,13 +2,9 @@
2
2
  "extends": "../tsconfig",
3
3
  "compilerOptions": {
4
4
  "paths": {},
5
- // resolveJsonModule must remain false: this package contains LFS-tracked JSON data files
6
- // that appear as pointer text (not valid JSON) in CI environments where LFS is skipped.
7
- // We also intentionally do not set "target": "es5" here (unlike the standard generated
8
- // build tsconfig) because the ESLint require-unicode-regexp rule enforces the 'u' flag
9
- // on regexes, which requires es6+ target to compile.
10
- "resolveJsonModule": false
5
+ "resolveJsonModule": true
11
6
  },
7
+ "files": ["./url-module.d.ts"],
12
8
  "include": ["../src/**/*.ts", "../src/**/*.tsx"],
13
9
  "exclude": [
14
10
  "../src/**/__tests__/*",
@@ -0,0 +1,8 @@
1
+ // Ambient declaration for Atlaspack/Parcel url: prefix imports.
2
+ // The url: prefix instructs the bundler to emit the referenced file as a
3
+ // content-hashed asset and return its public URL as a string.
4
+ // For rspack, this is handled via staticAssetsLoader config.
5
+ declare module 'url:*' {
6
+ const url: string;
7
+ export default url;
8
+ }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.createAutocompletePlugin = exports.autocompletePluginKey = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _wordVectors_10k = _interopRequireDefault(require("url:./data/word-vectors_10k.bin"));
9
10
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
10
11
  var _keymap = require("@atlaskit/editor-prosemirror/keymap");
11
12
  var _state = require("@atlaskit/editor-prosemirror/state");
@@ -14,7 +15,9 @@ var _ghostTextDecoration = require("./ghost-text-decoration");
14
15
  var _slowLaneClient = require("./slow-lane-client");
15
16
  var _textPredictor = require("./text-predictor");
16
17
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
17
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
18
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // url: prefix is an Atlaspack/Parcel directive that resolves this file as an emitted
19
+ // asset URL (content-hashed). For rspack, this is handled via staticAssetsLoader.
20
+ // eslint-disable-next-line @repo/internal/import/no-unresolved
18
21
  var SLOW_LANE_ENDPOINT = '/gateway/api/v1/autocomplete/typeahead-encodings';
19
22
  var autocompletePluginKey = exports.autocompletePluginKey = new _state.PluginKey('autocomplete');
20
23
  var DEBOUNCE_MS = 150;
@@ -214,14 +217,16 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
214
217
  return;
215
218
  }
216
219
  var lastChar = newText[newText.length - 1];
217
- if (!/[\t-\r !,\.:;\?\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/.test(lastChar)) {
220
+ // eslint-disable-next-line require-unicode-regexp
221
+ if (!/[\s.,;:!?]/.test(lastChar)) {
218
222
  return;
219
223
  }
220
224
 
221
225
  // Only fire if the previous state did not already end on a boundary,
222
226
  // so we don't double-count when multiple boundary chars are inserted.
223
227
  var prevLastChar = prevText[prevText.length - 1];
224
- if (prevLastChar && /[\t-\r !,\.:;\?\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/.test(prevLastChar)) {
228
+ // eslint-disable-next-line require-unicode-regexp
229
+ if (prevLastChar && /[\s.,;:!?]/.test(prevLastChar)) {
225
230
  return;
226
231
  }
227
232
  var beforeBoundary = newText.slice(0, -1).trimEnd();
@@ -299,7 +304,9 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
299
304
  },
300
305
  focus: function focus() {
301
306
  (0, _textPredictor.loadDefaultVocabulary)();
302
- (0, _textPredictor.loadVectorsAsync)().catch(function () {});
307
+ (0, _textPredictor.loadVectorsAsync)({
308
+ vectorsUrl: _wordVectors_10k.default
309
+ }).catch(function () {});
303
310
  if (!hasIngestedPage) {
304
311
  hasIngestedPage = true;
305
312
  if (options !== null && options !== void 0 && options.getContext) {
@@ -16,9 +16,7 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
16
16
  *
17
17
  * Operates synchronously on pre-loaded data. Each stage gracefully degrades
18
18
  * when its required data isn't available (cold → warm → full warm).
19
- */ // resolveJsonModule is disabled for this package (see tsconfig.json) to prevent
20
- // TypeScript from parsing LFS pointer files during CI typecheck. JSON imports
21
- // are typed via the '*.json' declaration in typings.d.ts.
19
+ */
22
20
  // ─── Types ──────────────────────────────────────────────────
23
21
 
24
22
  /** Metadata returned by the grammar filter for debug logging in the caller. */
@@ -25,7 +25,8 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
25
25
 
26
26
  // ─── Constants ───────────────────────────────────────────────────────────────
27
27
 
28
- var WORD_BOUNDARY_CHARS = /[\t-\r !,\.:;\?\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/;
28
+ // eslint-disable-next-line require-unicode-regexp
29
+ var WORD_BOUNDARY_CHARS = /[\s.,;:!?]/;
29
30
  var DEFAULT_DEBOUNCE_MS = 300;
30
31
 
31
32
  /**
@@ -75,6 +76,7 @@ var createSlowLaneClient = exports.createSlowLaneClient = function createSlowLan
75
76
  }
76
77
  return _context.abrupt("return");
77
78
  case 2:
79
+ // eslint-disable-next-line require-unicode-regexp
78
80
  url = "".concat(baseUrl.replace(/\/$/, '')).concat(endpoint);
79
81
  payload = {
80
82
  text: text,
@@ -37,7 +37,8 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
37
37
  // import { rankCandidates, isGrammarAllowed } from './scoring-pipeline';
38
38
  // ─── Constants ───────────────────────────────────────────────────────────────
39
39
 
40
- var PUNCTUATION_BOUNDARY_REGEX = /^[!"'-\),\.:;\?\[\]`\{\}]+|[!"'-\),\.:;\?\[\]`\{\}]+$/g;
40
+ // eslint-disable-next-line require-unicode-regexp
41
+ var PUNCTUATION_BOUNDARY_REGEX = /^[.,;:!?()\[\]{}"'`]+|[.,;:!?()\[\]{}"'`]+$/g;
41
42
  var MIN_PREFIX_LENGTH = 3;
42
43
  var MAX_CANDIDATES = 200;
43
44
  var CONTEXT_WORDS = 10;
@@ -311,8 +312,8 @@ var getContextVectorForScoring = function getContextVectorForScoring(textBefore)
311
312
  };
312
313
  var tokenize = function tokenize(text) {
313
314
  var tokens = [];
314
- // eslint-disable-next-line @atlassian/perf-linting/no-expensive-split-replace
315
- var _iterator7 = _createForOfIteratorHelper(text.toLowerCase().split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/)),
315
+ // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace
316
+ var _iterator7 = _createForOfIteratorHelper(text.toLowerCase().split(/\s+/)),
316
317
  _step7;
317
318
  try {
318
319
  for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
@@ -332,13 +333,15 @@ var tokenize = function tokenize(text) {
332
333
  };
333
334
  var extractPreviousWord = function extractPreviousWord(text) {
334
335
  // 1. Split the text by newlines or punctuation (. ? !)
335
- var sentences = text.split(/[\n!\.\?]+/);
336
+ // eslint-disable-next-line require-unicode-regexp
337
+ var sentences = text.split(/[\n.?!]+/);
336
338
 
337
339
  // 2. Only look at the current sentence/line the user is typing in
338
340
  var currentSentence = sentences[sentences.length - 1];
339
341
 
340
342
  // 3. Extract the previous word as normal
341
- var words = currentSentence.trimEnd().split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/);
343
+ // eslint-disable-next-line require-unicode-regexp
344
+ var words = currentSentence.trimEnd().split(/\s+/);
342
345
  return words.length >= 2 ? words[words.length - 2] : '';
343
346
  };
344
347
 
@@ -489,7 +492,8 @@ var predict = exports.predict = function predict(textBefore) {
489
492
  // }
490
493
 
491
494
  // ── Step 2: Prefix completion (≥3 chars typed) ──────────────────────────
492
- if (textBefore.length > 0 && /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]$/.test(textBefore)) {
495
+ // eslint-disable-next-line require-unicode-regexp
496
+ if (textBefore.length > 0 && /\s$/.test(textBefore)) {
493
497
  return null;
494
498
  }
495
499
  var trimmed = textBefore.trimEnd();
@@ -689,10 +693,8 @@ var predict = exports.predict = function predict(textBefore) {
689
693
 
690
694
  // ─── Data Loading ────────────────────────────────────────────────────────────
691
695
 
692
- var DEFAULT_VECTORS_URL = '/data/word-vectors_10k.bin';
693
696
  var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
694
697
  var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(options) {
695
- var _options$vectorsUrl;
696
698
  var url, res, buffer, float32, wordIndex, nWords, dim;
697
699
  return _regenerator.default.wrap(function _callee$(_context) {
698
700
  while (1) switch (_context.prev = _context.next) {
@@ -703,25 +705,33 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
703
705
  }
704
706
  return _context.abrupt("return");
705
707
  case 2:
708
+ if (options !== null && options !== void 0 && options.vectorsUrl) {
709
+ _context.next = 5;
710
+ break;
711
+ }
712
+ // eslint-disable-next-line no-console
713
+ console.warn('[text-predictor] loadVectorsAsync called without a vectorsUrl — vectors will not load. Pass vectorsUrl via plugin options.');
714
+ return _context.abrupt("return");
715
+ case 5:
706
716
  vectorsLoadStarted = true;
707
- url = (_options$vectorsUrl = options === null || options === void 0 ? void 0 : options.vectorsUrl) !== null && _options$vectorsUrl !== void 0 ? _options$vectorsUrl : DEFAULT_VECTORS_URL;
708
- _context.prev = 4;
709
- _context.next = 7;
717
+ url = options.vectorsUrl;
718
+ _context.prev = 7;
719
+ _context.next = 10;
710
720
  return fetch(url);
711
- case 7:
721
+ case 10:
712
722
  res = _context.sent;
713
723
  if (res.ok) {
714
- _context.next = 12;
724
+ _context.next = 15;
715
725
  break;
716
726
  }
717
727
  vectorsLoadStarted = false;
718
728
  // eslint-disable-next-line no-console
719
729
  console.warn("[text-predictor] Failed to load vectors: ".concat(res.status));
720
730
  return _context.abrupt("return");
721
- case 12:
722
- _context.next = 14;
731
+ case 15:
732
+ _context.next = 17;
723
733
  return res.arrayBuffer();
724
- case 14:
734
+ case 17:
725
735
  buffer = _context.sent;
726
736
  float32 = new Float32Array(buffer);
727
737
  wordIndex = _word_index_10k.default;
@@ -741,19 +751,19 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
741
751
  sizeBytes: float32.byteLength
742
752
  });
743
753
  }
744
- _context.next = 28;
754
+ _context.next = 31;
745
755
  break;
746
- case 24:
747
- _context.prev = 24;
748
- _context.t0 = _context["catch"](4);
756
+ case 27:
757
+ _context.prev = 27;
758
+ _context.t0 = _context["catch"](7);
749
759
  vectorsLoadStarted = false;
750
760
  // eslint-disable-next-line no-console
751
761
  console.warn('[text-predictor] Failed to load vectors:', _context.t0);
752
- case 28:
762
+ case 31:
753
763
  case "end":
754
764
  return _context.stop();
755
765
  }
756
- }, _callee, null, [[4, 24]]);
766
+ }, _callee, null, [[7, 27]]);
757
767
  }));
758
768
  return function loadVectorsAsync(_x) {
759
769
  return _ref4.apply(this, arguments);
@@ -1,3 +1,7 @@
1
+ // url: prefix is an Atlaspack/Parcel directive that resolves this file as an emitted
2
+ // asset URL (content-hashed). For rspack, this is handled via staticAssetsLoader.
3
+ // eslint-disable-next-line @repo/internal/import/no-unresolved
4
+ import wordVectorsUrl from 'url:./data/word-vectors_10k.bin';
1
5
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
6
  import { keydownHandler } from '@atlaskit/editor-prosemirror/keymap';
3
7
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
@@ -212,14 +216,16 @@ export const createAutocompletePlugin = options => {
212
216
  return;
213
217
  }
214
218
  const lastChar = newText[newText.length - 1];
215
- if (!/[\s.,;:!?]/u.test(lastChar)) {
219
+ // eslint-disable-next-line require-unicode-regexp
220
+ if (!/[\s.,;:!?]/.test(lastChar)) {
216
221
  return;
217
222
  }
218
223
 
219
224
  // Only fire if the previous state did not already end on a boundary,
220
225
  // so we don't double-count when multiple boundary chars are inserted.
221
226
  const prevLastChar = prevText[prevText.length - 1];
222
- if (prevLastChar && /[\s.,;:!?]/u.test(prevLastChar)) {
227
+ // eslint-disable-next-line require-unicode-regexp
228
+ if (prevLastChar && /[\s.,;:!?]/.test(prevLastChar)) {
223
229
  return;
224
230
  }
225
231
  const beforeBoundary = newText.slice(0, -1).trimEnd();
@@ -300,7 +306,9 @@ export const createAutocompletePlugin = options => {
300
306
  },
301
307
  focus: () => {
302
308
  loadDefaultVocabulary();
303
- loadVectorsAsync().catch(() => {});
309
+ loadVectorsAsync({
310
+ vectorsUrl: wordVectorsUrl
311
+ }).catch(() => {});
304
312
  if (!hasIngestedPage) {
305
313
  hasIngestedPage = true;
306
314
  if (options !== null && options !== void 0 && options.getContext) {
@@ -5,9 +5,6 @@
5
5
  * when its required data isn't available (cold → warm → full warm).
6
6
  */
7
7
 
8
- // resolveJsonModule is disabled for this package (see tsconfig.json) to prevent
9
- // TypeScript from parsing LFS pointer files during CI typecheck. JSON imports
10
- // are typed via the '*.json' declaration in typings.d.ts.
11
8
  import posTagsData from './data/combined_l2_l3_pos_tags.json';
12
9
  import ghostPosTagsData from './data/ghost_pos_tags.json';
13
10
  import grammarTransitionsData from './data/grammar_transitions_10k.json';
@@ -15,7 +15,8 @@
15
15
 
16
16
  // ─── Constants ───────────────────────────────────────────────────────────────
17
17
 
18
- const WORD_BOUNDARY_CHARS = /[\s.,;:!?]/u;
18
+ // eslint-disable-next-line require-unicode-regexp
19
+ const WORD_BOUNDARY_CHARS = /[\s.,;:!?]/;
19
20
  const DEFAULT_DEBOUNCE_MS = 300;
20
21
 
21
22
  /**
@@ -55,7 +56,9 @@ export const createSlowLaneClient = config => {
55
56
  if (!text || text.trim().length === 0) {
56
57
  return;
57
58
  }
58
- const url = `${baseUrl.replace(/\/$/u, '')}${endpoint}`;
59
+
60
+ // eslint-disable-next-line require-unicode-regexp
61
+ const url = `${baseUrl.replace(/\/$/, '')}${endpoint}`;
59
62
  const payload = {
60
63
  text,
61
64
  session_id: sessionId
@@ -26,7 +26,8 @@ import { getStoredContextVector, getStoredLmLogits } from './slow-lane-client';
26
26
 
27
27
  // ─── Constants ───────────────────────────────────────────────────────────────
28
28
 
29
- const PUNCTUATION_BOUNDARY_REGEX = /^[.,;:!?()\[\]{}"'`]+|[.,;:!?()\[\]{}"'`]+$/gu;
29
+ // eslint-disable-next-line require-unicode-regexp
30
+ const PUNCTUATION_BOUNDARY_REGEX = /^[.,;:!?()\[\]{}"'`]+|[.,;:!?()\[\]{}"'`]+$/g;
30
31
  const MIN_PREFIX_LENGTH = 3;
31
32
  const MAX_CANDIDATES = 200;
32
33
  const CONTEXT_WORDS = 10;
@@ -236,8 +237,8 @@ const getContextVectorForScoring = textBefore => {
236
237
  };
237
238
  const tokenize = text => {
238
239
  const tokens = [];
239
- // eslint-disable-next-line @atlassian/perf-linting/no-expensive-split-replace
240
- for (const raw of text.toLowerCase().split(/\s+/u)) {
240
+ // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace
241
+ for (const raw of text.toLowerCase().split(/\s+/)) {
241
242
  // eslint-disable-next-line @atlassian/perf-linting/no-expensive-split-replace
242
243
  const clean = raw.replace(PUNCTUATION_BOUNDARY_REGEX, '');
243
244
  if (clean.length >= 2) {
@@ -248,13 +249,15 @@ const tokenize = text => {
248
249
  };
249
250
  const extractPreviousWord = text => {
250
251
  // 1. Split the text by newlines or punctuation (. ? !)
251
- const sentences = text.split(/[\n.?!]+/u);
252
+ // eslint-disable-next-line require-unicode-regexp
253
+ const sentences = text.split(/[\n.?!]+/);
252
254
 
253
255
  // 2. Only look at the current sentence/line the user is typing in
254
256
  const currentSentence = sentences[sentences.length - 1];
255
257
 
256
258
  // 3. Extract the previous word as normal
257
- const words = currentSentence.trimEnd().split(/\s+/u);
259
+ // eslint-disable-next-line require-unicode-regexp
260
+ const words = currentSentence.trimEnd().split(/\s+/);
258
261
  return words.length >= 2 ? words[words.length - 2] : '';
259
262
  };
260
263
 
@@ -387,7 +390,8 @@ export const predict = textBefore => {
387
390
  // }
388
391
 
389
392
  // ── Step 2: Prefix completion (≥3 chars typed) ──────────────────────────
390
- if (textBefore.length > 0 && /\s$/u.test(textBefore)) {
393
+ // eslint-disable-next-line require-unicode-regexp
394
+ if (textBefore.length > 0 && /\s$/.test(textBefore)) {
391
395
  return null;
392
396
  }
393
397
  const trimmed = textBefore.trimEnd();
@@ -561,14 +565,17 @@ export const predict = textBefore => {
561
565
 
562
566
  // ─── Data Loading ────────────────────────────────────────────────────────────
563
567
 
564
- const DEFAULT_VECTORS_URL = '/data/word-vectors_10k.bin';
565
568
  export const loadVectorsAsync = async options => {
566
- var _options$vectorsUrl;
567
569
  if (vectorStore || vectorsLoadStarted) {
568
570
  return;
569
571
  }
572
+ if (!(options !== null && options !== void 0 && options.vectorsUrl)) {
573
+ // eslint-disable-next-line no-console
574
+ console.warn('[text-predictor] loadVectorsAsync called without a vectorsUrl — vectors will not load. Pass vectorsUrl via plugin options.');
575
+ return;
576
+ }
570
577
  vectorsLoadStarted = true;
571
- const url = (_options$vectorsUrl = options === null || options === void 0 ? void 0 : options.vectorsUrl) !== null && _options$vectorsUrl !== void 0 ? _options$vectorsUrl : DEFAULT_VECTORS_URL;
578
+ const url = options.vectorsUrl;
572
579
  try {
573
580
  const res = await fetch(url);
574
581
  if (!res.ok) {
@@ -1,6 +1,10 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ // url: prefix is an Atlaspack/Parcel directive that resolves this file as an emitted
5
+ // asset URL (content-hashed). For rspack, this is handled via staticAssetsLoader.
6
+ // eslint-disable-next-line @repo/internal/import/no-unresolved
7
+ import wordVectorsUrl from 'url:./data/word-vectors_10k.bin';
4
8
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
5
9
  import { keydownHandler } from '@atlaskit/editor-prosemirror/keymap';
6
10
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
@@ -207,14 +211,16 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options)
207
211
  return;
208
212
  }
209
213
  var lastChar = newText[newText.length - 1];
210
- if (!/[\t-\r !,\.:;\?\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/.test(lastChar)) {
214
+ // eslint-disable-next-line require-unicode-regexp
215
+ if (!/[\s.,;:!?]/.test(lastChar)) {
211
216
  return;
212
217
  }
213
218
 
214
219
  // Only fire if the previous state did not already end on a boundary,
215
220
  // so we don't double-count when multiple boundary chars are inserted.
216
221
  var prevLastChar = prevText[prevText.length - 1];
217
- if (prevLastChar && /[\t-\r !,\.:;\?\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/.test(prevLastChar)) {
222
+ // eslint-disable-next-line require-unicode-regexp
223
+ if (prevLastChar && /[\s.,;:!?]/.test(prevLastChar)) {
218
224
  return;
219
225
  }
220
226
  var beforeBoundary = newText.slice(0, -1).trimEnd();
@@ -292,7 +298,9 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options)
292
298
  },
293
299
  focus: function focus() {
294
300
  loadDefaultVocabulary();
295
- loadVectorsAsync().catch(function () {});
301
+ loadVectorsAsync({
302
+ vectorsUrl: wordVectorsUrl
303
+ }).catch(function () {});
296
304
  if (!hasIngestedPage) {
297
305
  hasIngestedPage = true;
298
306
  if (options !== null && options !== void 0 && options.getContext) {
@@ -9,9 +9,6 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
9
9
  * when its required data isn't available (cold → warm → full warm).
10
10
  */
11
11
 
12
- // resolveJsonModule is disabled for this package (see tsconfig.json) to prevent
13
- // TypeScript from parsing LFS pointer files during CI typecheck. JSON imports
14
- // are typed via the '*.json' declaration in typings.d.ts.
15
12
  import posTagsData from './data/combined_l2_l3_pos_tags.json';
16
13
  import ghostPosTagsData from './data/ghost_pos_tags.json';
17
14
  import grammarTransitionsData from './data/grammar_transitions_10k.json';
@@ -18,7 +18,8 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
18
18
 
19
19
  // ─── Constants ───────────────────────────────────────────────────────────────
20
20
 
21
- var WORD_BOUNDARY_CHARS = /[\t-\r !,\.:;\?\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/;
21
+ // eslint-disable-next-line require-unicode-regexp
22
+ var WORD_BOUNDARY_CHARS = /[\s.,;:!?]/;
22
23
  var DEFAULT_DEBOUNCE_MS = 300;
23
24
 
24
25
  /**
@@ -68,6 +69,7 @@ export var createSlowLaneClient = function createSlowLaneClient(config) {
68
69
  }
69
70
  return _context.abrupt("return");
70
71
  case 2:
72
+ // eslint-disable-next-line require-unicode-regexp
71
73
  url = "".concat(baseUrl.replace(/\/$/, '')).concat(endpoint);
72
74
  payload = {
73
75
  text: text,
@@ -34,7 +34,8 @@ import { getStoredContextVector, getStoredLmLogits } from './slow-lane-client';
34
34
 
35
35
  // ─── Constants ───────────────────────────────────────────────────────────────
36
36
 
37
- var PUNCTUATION_BOUNDARY_REGEX = /^[!"'-\),\.:;\?\[\]`\{\}]+|[!"'-\),\.:;\?\[\]`\{\}]+$/g;
37
+ // eslint-disable-next-line require-unicode-regexp
38
+ var PUNCTUATION_BOUNDARY_REGEX = /^[.,;:!?()\[\]{}"'`]+|[.,;:!?()\[\]{}"'`]+$/g;
38
39
  var MIN_PREFIX_LENGTH = 3;
39
40
  var MAX_CANDIDATES = 200;
40
41
  var CONTEXT_WORDS = 10;
@@ -308,8 +309,8 @@ var getContextVectorForScoring = function getContextVectorForScoring(textBefore)
308
309
  };
309
310
  var tokenize = function tokenize(text) {
310
311
  var tokens = [];
311
- // eslint-disable-next-line @atlassian/perf-linting/no-expensive-split-replace
312
- var _iterator7 = _createForOfIteratorHelper(text.toLowerCase().split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/)),
312
+ // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace
313
+ var _iterator7 = _createForOfIteratorHelper(text.toLowerCase().split(/\s+/)),
313
314
  _step7;
314
315
  try {
315
316
  for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
@@ -329,13 +330,15 @@ var tokenize = function tokenize(text) {
329
330
  };
330
331
  var extractPreviousWord = function extractPreviousWord(text) {
331
332
  // 1. Split the text by newlines or punctuation (. ? !)
332
- var sentences = text.split(/[\n!\.\?]+/);
333
+ // eslint-disable-next-line require-unicode-regexp
334
+ var sentences = text.split(/[\n.?!]+/);
333
335
 
334
336
  // 2. Only look at the current sentence/line the user is typing in
335
337
  var currentSentence = sentences[sentences.length - 1];
336
338
 
337
339
  // 3. Extract the previous word as normal
338
- var words = currentSentence.trimEnd().split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/);
340
+ // eslint-disable-next-line require-unicode-regexp
341
+ var words = currentSentence.trimEnd().split(/\s+/);
339
342
  return words.length >= 2 ? words[words.length - 2] : '';
340
343
  };
341
344
 
@@ -486,7 +489,8 @@ export var predict = function predict(textBefore) {
486
489
  // }
487
490
 
488
491
  // ── Step 2: Prefix completion (≥3 chars typed) ──────────────────────────
489
- if (textBefore.length > 0 && /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]$/.test(textBefore)) {
492
+ // eslint-disable-next-line require-unicode-regexp
493
+ if (textBefore.length > 0 && /\s$/.test(textBefore)) {
490
494
  return null;
491
495
  }
492
496
  var trimmed = textBefore.trimEnd();
@@ -686,10 +690,8 @@ export var predict = function predict(textBefore) {
686
690
 
687
691
  // ─── Data Loading ────────────────────────────────────────────────────────────
688
692
 
689
- var DEFAULT_VECTORS_URL = '/data/word-vectors_10k.bin';
690
693
  export var loadVectorsAsync = /*#__PURE__*/function () {
691
694
  var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
692
- var _options$vectorsUrl;
693
695
  var url, res, buffer, float32, wordIndex, nWords, dim;
694
696
  return _regeneratorRuntime.wrap(function _callee$(_context) {
695
697
  while (1) switch (_context.prev = _context.next) {
@@ -700,25 +702,33 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
700
702
  }
701
703
  return _context.abrupt("return");
702
704
  case 2:
705
+ if (options !== null && options !== void 0 && options.vectorsUrl) {
706
+ _context.next = 5;
707
+ break;
708
+ }
709
+ // eslint-disable-next-line no-console
710
+ console.warn('[text-predictor] loadVectorsAsync called without a vectorsUrl — vectors will not load. Pass vectorsUrl via plugin options.');
711
+ return _context.abrupt("return");
712
+ case 5:
703
713
  vectorsLoadStarted = true;
704
- url = (_options$vectorsUrl = options === null || options === void 0 ? void 0 : options.vectorsUrl) !== null && _options$vectorsUrl !== void 0 ? _options$vectorsUrl : DEFAULT_VECTORS_URL;
705
- _context.prev = 4;
706
- _context.next = 7;
714
+ url = options.vectorsUrl;
715
+ _context.prev = 7;
716
+ _context.next = 10;
707
717
  return fetch(url);
708
- case 7:
718
+ case 10:
709
719
  res = _context.sent;
710
720
  if (res.ok) {
711
- _context.next = 12;
721
+ _context.next = 15;
712
722
  break;
713
723
  }
714
724
  vectorsLoadStarted = false;
715
725
  // eslint-disable-next-line no-console
716
726
  console.warn("[text-predictor] Failed to load vectors: ".concat(res.status));
717
727
  return _context.abrupt("return");
718
- case 12:
719
- _context.next = 14;
728
+ case 15:
729
+ _context.next = 17;
720
730
  return res.arrayBuffer();
721
- case 14:
731
+ case 17:
722
732
  buffer = _context.sent;
723
733
  float32 = new Float32Array(buffer);
724
734
  wordIndex = wordIndexData;
@@ -738,19 +748,19 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
738
748
  sizeBytes: float32.byteLength
739
749
  });
740
750
  }
741
- _context.next = 28;
751
+ _context.next = 31;
742
752
  break;
743
- case 24:
744
- _context.prev = 24;
745
- _context.t0 = _context["catch"](4);
753
+ case 27:
754
+ _context.prev = 27;
755
+ _context.t0 = _context["catch"](7);
746
756
  vectorsLoadStarted = false;
747
757
  // eslint-disable-next-line no-console
748
758
  console.warn('[text-predictor] Failed to load vectors:', _context.t0);
749
- case 28:
759
+ case 31:
750
760
  case "end":
751
761
  return _context.stop();
752
762
  }
753
- }, _callee, null, [[4, 24]]);
763
+ }, _callee, null, [[7, 27]]);
754
764
  }));
755
765
  return function loadVectorsAsync(_x) {
756
766
  return _ref4.apply(this, arguments);
@@ -33,4 +33,4 @@ export interface AutocompletePluginOptions {
33
33
  */
34
34
  getContext?: () => Promise<AutocompleteContext | undefined>;
35
35
  }
36
- export declare const createAutocompletePlugin: (options?: AutocompletePluginOptions) => SafePlugin<AutocompletePluginState>;
36
+ export declare const createAutocompletePlugin: (options?: AutocompletePluginOptions) => SafePlugin<any>;
@@ -33,4 +33,4 @@ export interface AutocompletePluginOptions {
33
33
  */
34
34
  getContext?: () => Promise<AutocompleteContext | undefined>;
35
35
  }
36
- export declare const createAutocompletePlugin: (options?: AutocompletePluginOptions) => SafePlugin<AutocompletePluginState>;
36
+ export declare const createAutocompletePlugin: (options?: AutocompletePluginOptions) => SafePlugin<any>;