@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.
- package/CHANGELOG.md +8 -0
- package/afm-cc/tsconfig.json +1 -4
- package/afm-jira/tsconfig.json +1 -4
- package/afm-products/tsconfig.json +1 -4
- package/build/tsconfig.json +2 -6
- package/build/url-module.d.ts +8 -0
- package/dist/cjs/pm-plugins/autocomplete-plugin.js +11 -4
- package/dist/cjs/pm-plugins/scoring-pipeline.js +1 -3
- package/dist/cjs/pm-plugins/slow-lane-client.js +3 -1
- package/dist/cjs/pm-plugins/text-predictor.js +32 -22
- package/dist/es2019/pm-plugins/autocomplete-plugin.js +11 -3
- package/dist/es2019/pm-plugins/scoring-pipeline.js +0 -3
- package/dist/es2019/pm-plugins/slow-lane-client.js +5 -2
- package/dist/es2019/pm-plugins/text-predictor.js +16 -9
- package/dist/esm/pm-plugins/autocomplete-plugin.js +11 -3
- package/dist/esm/pm-plugins/scoring-pipeline.js +0 -3
- package/dist/esm/pm-plugins/slow-lane-client.js +3 -1
- package/dist/esm/pm-plugins/text-predictor.js +32 -22
- package/dist/types/pm-plugins/autocomplete-plugin.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts +1 -1
- package/package.json +1 -1
- package/src/pm-plugins/autocomplete-plugin.ts +19 -5
- package/src/pm-plugins/data/combined_l2_l3_pos_tags.json +73571 -3
- package/src/pm-plugins/data/ghost_pos_tags.json +43 -3
- package/src/pm-plugins/data/grammar_transitions_10k.json +46 -3
- package/src/pm-plugins/data/l3_vocabulary.json +20002 -3
- package/src/pm-plugins/data/vocabulary_10k.json +38794 -3
- package/src/pm-plugins/data/word_index_10k.json +7760 -3
- package/src/pm-plugins/scoring-pipeline.ts +0 -3
- package/src/pm-plugins/slow-lane-client.ts +4 -2
- package/src/pm-plugins/text-predictor.ts +18 -9
- package/tsconfig.app.json +3 -2
- package/tsconfig.json +2 -1
- 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
|
package/afm-cc/tsconfig.json
CHANGED
|
@@ -6,10 +6,7 @@
|
|
|
6
6
|
"rootDir": "../",
|
|
7
7
|
"composite": true,
|
|
8
8
|
"noCheck": true,
|
|
9
|
-
|
|
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",
|
package/afm-jira/tsconfig.json
CHANGED
|
@@ -6,10 +6,7 @@
|
|
|
6
6
|
"rootDir": "../",
|
|
7
7
|
"composite": true,
|
|
8
8
|
"noCheck": true,
|
|
9
|
-
|
|
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
|
-
|
|
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",
|
package/build/tsconfig.json
CHANGED
|
@@ -2,13 +2,9 @@
|
|
|
2
2
|
"extends": "../tsconfig",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"paths": {},
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)(
|
|
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
|
-
*/
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
708
|
-
_context.prev =
|
|
709
|
-
_context.next =
|
|
717
|
+
url = options.vectorsUrl;
|
|
718
|
+
_context.prev = 7;
|
|
719
|
+
_context.next = 10;
|
|
710
720
|
return fetch(url);
|
|
711
|
-
case
|
|
721
|
+
case 10:
|
|
712
722
|
res = _context.sent;
|
|
713
723
|
if (res.ok) {
|
|
714
|
-
_context.next =
|
|
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
|
|
722
|
-
_context.next =
|
|
731
|
+
case 15:
|
|
732
|
+
_context.next = 17;
|
|
723
733
|
return res.arrayBuffer();
|
|
724
|
-
case
|
|
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 =
|
|
754
|
+
_context.next = 31;
|
|
745
755
|
break;
|
|
746
|
-
case
|
|
747
|
-
_context.prev =
|
|
748
|
-
_context.t0 = _context["catch"](
|
|
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
|
|
762
|
+
case 31:
|
|
753
763
|
case "end":
|
|
754
764
|
return _context.stop();
|
|
755
765
|
}
|
|
756
|
-
}, _callee, null, [[
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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+/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
705
|
-
_context.prev =
|
|
706
|
-
_context.next =
|
|
714
|
+
url = options.vectorsUrl;
|
|
715
|
+
_context.prev = 7;
|
|
716
|
+
_context.next = 10;
|
|
707
717
|
return fetch(url);
|
|
708
|
-
case
|
|
718
|
+
case 10:
|
|
709
719
|
res = _context.sent;
|
|
710
720
|
if (res.ok) {
|
|
711
|
-
_context.next =
|
|
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
|
|
719
|
-
_context.next =
|
|
728
|
+
case 15:
|
|
729
|
+
_context.next = 17;
|
|
720
730
|
return res.arrayBuffer();
|
|
721
|
-
case
|
|
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 =
|
|
751
|
+
_context.next = 31;
|
|
742
752
|
break;
|
|
743
|
-
case
|
|
744
|
-
_context.prev =
|
|
745
|
-
_context.t0 = _context["catch"](
|
|
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
|
|
759
|
+
case 31:
|
|
750
760
|
case "end":
|
|
751
761
|
return _context.stop();
|
|
752
762
|
}
|
|
753
|
-
}, _callee, null, [[
|
|
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<
|
|
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<
|
|
36
|
+
export declare const createAutocompletePlugin: (options?: AutocompletePluginOptions) => SafePlugin<any>;
|