cspell-lib 10.2.0-alpha.7 → 10.2.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.
Files changed (30) hide show
  1. package/dist/lib/Settings/LanguageSettings.js +17 -1
  2. package/dist/lib/Settings/sanitizeSettings.js +3 -0
  3. package/dist/lib/Transform/IntlSegmentTextTransformer.d.ts +11 -0
  4. package/dist/lib/Transform/IntlSegmentTextTransformer.js +41 -0
  5. package/dist/lib/Transform/SubstitutionTransformer.d.ts +3 -1
  6. package/dist/lib/Transform/SubstitutionTransformer.js +10 -28
  7. package/dist/lib/Transform/TextMapEdit.d.ts +5 -0
  8. package/dist/lib/Transform/TextMapEdit.js +42 -0
  9. package/dist/lib/Transform/Transformer.d.ts +25 -0
  10. package/dist/lib/Transform/Transformer.js +27 -0
  11. package/dist/lib/Transform/index.d.ts +3 -0
  12. package/dist/lib/Transform/index.js +2 -0
  13. package/dist/lib/textValidation/docValidator.d.ts +3 -2
  14. package/dist/lib/textValidation/docValidator.js +22 -20
  15. package/dist/lib/textValidation/isRandomString.js +4 -3
  16. package/dist/lib/textValidation/lineValidatorFactory.d.ts +2 -2
  17. package/dist/lib/textValidation/lineValidatorFactory.js +7 -2
  18. package/dist/lib/textValidation/textValidator.d.ts +2 -2
  19. package/dist/lib/textValidation/traceWord.js +1 -1
  20. package/dist/lib/util/textRegex.js +1 -1
  21. package/dist/lib/util/wordSplitter/generateWordBreaks.d.ts +32 -0
  22. package/dist/lib/util/wordSplitter/generateWordBreaks.js +120 -0
  23. package/dist/lib/util/wordSplitter/index.d.ts +4 -0
  24. package/dist/lib/util/wordSplitter/index.js +3 -0
  25. package/dist/lib/util/{wordSplitter.d.ts → wordSplitter/wordSplitter.d.ts} +13 -22
  26. package/dist/lib/util/wordSplitter/wordSplitter.js +338 -0
  27. package/dist/lib/util/{wordSplitter.perf.js → wordSplitter/wordSplitter.perf.js} +2 -2
  28. package/package.json +20 -19
  29. package/dist/lib/util/wordSplitter.js +0 -331
  30. /package/dist/lib/util/{wordSplitter.perf.d.ts → wordSplitter/wordSplitter.perf.d.ts} +0 -0
@@ -1,331 +0,0 @@
1
- import { PairingHeap } from './PairingHeap.js';
2
- import { escapeRegEx } from './regexHelper.js';
3
- import { regExDanglingQuote, regExEscapeCharacters, regExNumericLiteral, regExPossibleWordBreaks, regExSplitWords, regExSplitWords2, regExTrailingEndings, regExWordsAndDigits, } from './textRegex.js';
4
- const ignoreBreak = Object.freeze([]);
5
- export function split(line, offset, isValidWord, options = {}) {
6
- const relWordToSplit = findNextWordText({ text: line.text, offset: offset - line.offset });
7
- const lineOffset = line.offset;
8
- const requested = new Map();
9
- const regExpIgnoreSegment = /^[-.+\d_eE'`\\\s]+$/;
10
- if (!relWordToSplit.text) {
11
- const text = rebaseTextOffset(relWordToSplit);
12
- return {
13
- line,
14
- offset,
15
- text: text,
16
- words: [],
17
- endOffset: text.offset + text.text.length,
18
- };
19
- }
20
- const lineSegment = {
21
- line,
22
- relStart: relWordToSplit.offset,
23
- relEnd: relWordToSplit.offset + relWordToSplit.text.length,
24
- };
25
- const possibleBreaks = generateWordBreaks(lineSegment, options);
26
- if (!possibleBreaks.length) {
27
- const text = rebaseTextOffset(relWordToSplit);
28
- return {
29
- line,
30
- offset,
31
- text: text,
32
- words: [{ ...text, isFound: isValidWord(text) }],
33
- endOffset: text.offset + text.text.length,
34
- };
35
- }
36
- function rebaseTextOffset(relText) {
37
- return {
38
- ...relText,
39
- offset: relText.offset + lineOffset,
40
- };
41
- }
42
- function has(word) {
43
- if (regExpIgnoreSegment.test(word.text)) {
44
- return true;
45
- }
46
- const i = word.offset;
47
- const j = word.text.length;
48
- let v = i + (j << 20);
49
- if (i < 1 << 20 && j < 1 << 11) {
50
- const b = requested.get(v);
51
- if (b !== undefined)
52
- return b;
53
- }
54
- else {
55
- v = -1;
56
- }
57
- const r = isValidWord(rebaseTextOffset(word));
58
- if (v >= 0) {
59
- requested.set(v, r);
60
- }
61
- return r;
62
- }
63
- // Add a dummy break at the end to avoid needing to check for last break.
64
- possibleBreaks.push({
65
- offset: lineSegment.relEnd,
66
- breaks: [ignoreBreak],
67
- });
68
- const result = {
69
- line,
70
- offset,
71
- text: rebaseTextOffset(relWordToSplit),
72
- words: splitIntoWords(lineSegment, possibleBreaks, has).map(rebaseTextOffset),
73
- endOffset: lineOffset + lineSegment.relEnd,
74
- };
75
- return result;
76
- }
77
- function findNextWordText({ text, offset }) {
78
- const reg = new RegExp(regExWordsAndDigits);
79
- reg.lastIndex = offset;
80
- const m = reg.exec(text);
81
- if (!m) {
82
- return {
83
- text: '',
84
- offset: offset + text.length,
85
- };
86
- }
87
- // Skip numeric literals.
88
- if (regExNumericLiteral.test(m[0])) {
89
- return findNextWordText({ text, offset: offset + m[0].length });
90
- }
91
- return {
92
- text: m[0],
93
- offset: m.index,
94
- };
95
- }
96
- function generateWordBreaks(line, options) {
97
- const camelBreaks = genWordBreakCamel(line);
98
- const symbolBreaks = genSymbolBreaks(line);
99
- const optionalBreaks = genOptionalWordBreaks(line, options.optionalWordBreakCharacters);
100
- return mergeSortedBreaks(...camelBreaks, ...symbolBreaks, ...optionalBreaks);
101
- }
102
- function offsetRegEx(reg, offset) {
103
- const r = new RegExp(reg);
104
- r.lastIndex = offset;
105
- return r;
106
- }
107
- function genWordBreakCamel(line) {
108
- const breaksCamel1 = [];
109
- const text = line.line.text.slice(0, line.relEnd);
110
- // lower,Upper: camelCase -> camel|Case
111
- for (const m of text.matchAll(offsetRegEx(regExSplitWords, line.relStart))) {
112
- if (m.index === undefined)
113
- break;
114
- const i = m.index + m[1].length;
115
- breaksCamel1.push({
116
- offset: m.index,
117
- breaks: [[i, i], ignoreBreak],
118
- });
119
- }
120
- const breaksCamel2 = [];
121
- // cspell:ignore ERRORC
122
- // Upper,Upper,lower: ERRORCodes -> ERROR|Codes, ERRORC|odes
123
- for (const m of text.matchAll(offsetRegEx(regExSplitWords2, line.relStart))) {
124
- if (m.index === undefined)
125
- break;
126
- const i = m.index + m[1].length;
127
- const j = i + m[3].length;
128
- breaksCamel2.push({
129
- offset: m.index,
130
- breaks: [[i, i], [j, j], ignoreBreak],
131
- });
132
- }
133
- return [breaksCamel1, breaksCamel2];
134
- }
135
- function calcBreaksForRegEx(line, reg, calcBreak) {
136
- const sb = [];
137
- const text = line.line.text.slice(0, line.relEnd);
138
- for (const m of text.matchAll(offsetRegEx(reg, line.relStart))) {
139
- const b = calcBreak(m);
140
- if (b) {
141
- sb.push(b);
142
- }
143
- }
144
- return sb;
145
- }
146
- function genOptionalWordBreaks(line, optionalBreakCharacters) {
147
- function calcBreaks(m) {
148
- const i = m.index;
149
- if (i === undefined)
150
- return;
151
- const j = i + m[0].length;
152
- return {
153
- offset: i,
154
- breaks: [
155
- [i, j], // Remove the characters
156
- ignoreBreak,
157
- ],
158
- };
159
- }
160
- const breaks = [
161
- calcBreaksForRegEx(line, regExDanglingQuote, calcBreaks),
162
- calcBreaksForRegEx(line, regExTrailingEndings, calcBreaks),
163
- ];
164
- if (optionalBreakCharacters) {
165
- const regex = new RegExp(`[${escapeRegEx(optionalBreakCharacters)}]`, 'gu');
166
- breaks.push(calcBreaksForRegEx(line, regex, calcBreaks));
167
- }
168
- return breaks;
169
- }
170
- function genSymbolBreaks(line) {
171
- function calcBreaks(m) {
172
- const i = m.index;
173
- if (i === undefined)
174
- return;
175
- const j = i + m[0].length;
176
- return {
177
- offset: i,
178
- breaks: [
179
- [i, j], // Remove the characters
180
- [i, i], // keep characters with word to right
181
- [j, j], // keep characters with word to left
182
- ignoreBreak,
183
- ],
184
- };
185
- }
186
- return [
187
- calcBreaksForRegEx(line, regExPossibleWordBreaks, calcBreaks),
188
- calcBreaksForRegEx(line, /\d+/g, calcBreaks),
189
- calcBreaksForRegEx(line, regExEscapeCharacters, calcBreaks),
190
- ];
191
- }
192
- function splitIntoWords(lineSeg, breaks, has) {
193
- const maxIndex = lineSeg.relEnd;
194
- const maxAttempts = 1000;
195
- const knownPathsByIndex = new Map();
196
- /**
197
- * Create a set of possible candidate to consider
198
- * @param p - prev candidate that lead to this one
199
- * @param i - offset within the string
200
- * @param bi - current index into the set of breaks
201
- * @param currentCost - current cost accrued
202
- */
203
- function makeCandidates(p, i, bi, currentCost) {
204
- const len = maxIndex;
205
- while (bi < breaks.length && breaks[bi].offset < i) {
206
- bi += 1;
207
- }
208
- if (bi >= breaks.length) {
209
- return [];
210
- }
211
- const br = breaks[bi];
212
- function c(bp) {
213
- const d = bp.length < 2 ? len - i : (bp[0] - i) * 0.5 + len - bp[1];
214
- const ec = currentCost + d;
215
- return {
216
- p,
217
- i,
218
- bi,
219
- bp,
220
- c: currentCost,
221
- ec,
222
- text: undefined,
223
- };
224
- }
225
- return br.breaks.map(c);
226
- }
227
- function checkTextOffset(text, offset) {
228
- const valid = has({ text, offset });
229
- return {
230
- text,
231
- offset,
232
- isFound: valid,
233
- };
234
- }
235
- function compare(a, b) {
236
- return a.ec - b.ec || b.i - a.i;
237
- }
238
- function pathToWords(node) {
239
- const results = [];
240
- for (let p = node; p; p = p.n) {
241
- if (p.text) {
242
- results.push(p.text);
243
- }
244
- }
245
- return results;
246
- }
247
- function addToKnownPaths(candidate, path) {
248
- for (let can = candidate; can !== undefined; can = can.p) {
249
- const t = can.text;
250
- const i = can.i;
251
- const cost = (!t || t.isFound ? 0 : t.text.length) + (path?.c ?? 0);
252
- const exitingPath = knownPathsByIndex.get(i);
253
- // Keep going only if this is a better candidate than the existing path
254
- if (exitingPath && exitingPath.c <= cost) {
255
- return undefined;
256
- }
257
- const node = {
258
- n: path,
259
- i,
260
- c: cost,
261
- text: t,
262
- };
263
- knownPathsByIndex.set(i, node);
264
- path = node;
265
- }
266
- return path;
267
- }
268
- let maxCost = lineSeg.relEnd - lineSeg.relStart;
269
- const candidates = new PairingHeap(compare);
270
- const text = lineSeg.line.text;
271
- candidates.append(makeCandidates(undefined, lineSeg.relStart, 0, 0));
272
- let attempts = 0;
273
- let bestPath;
274
- while (maxCost && candidates.length && attempts++ < maxAttempts) {
275
- /** Best Candidate Index */
276
- const best = candidates.dequeue();
277
- if (!best || best.c >= maxCost) {
278
- continue;
279
- }
280
- // Does it have a split?
281
- if (best.bp.length) {
282
- // yes
283
- const i = best.bp[0];
284
- const j = best.bp[1];
285
- const t = i > best.i ? checkTextOffset(text.slice(best.i, i), best.i) : undefined;
286
- const cost = !t || t.isFound ? 0 : t.text.length;
287
- const mc = maxIndex - j;
288
- best.c += cost;
289
- best.ec = best.c + mc;
290
- best.text = t;
291
- const possiblePath = knownPathsByIndex.get(j);
292
- if (possiblePath) {
293
- // We found a known apply to candidate
294
- const f = addToKnownPaths(best, possiblePath);
295
- bestPath = !bestPath || (f && f.c < bestPath.c) ? f : bestPath;
296
- }
297
- else if (best.c < maxCost) {
298
- const c = makeCandidates(t ? best : best.p, j, best.bi + 1, best.c);
299
- candidates.append(c);
300
- }
301
- }
302
- else {
303
- // It is a pass through
304
- const c = makeCandidates(best.p, best.i, best.bi + 1, best.c);
305
- candidates.append(c);
306
- if (!c.length) {
307
- const t = maxIndex > best.i ? checkTextOffset(text.slice(best.i, maxIndex), best.i) : undefined;
308
- const cost = !t || t.isFound ? 0 : t.text.length;
309
- best.c += cost;
310
- best.ec = best.c;
311
- best.text = t;
312
- const segText = t || best.p?.text || checkTextOffset('', best.i);
313
- const can = t ? { ...best, text: segText } : { ...best, ...best.p, text: segText };
314
- const f = addToKnownPaths(can, undefined);
315
- bestPath = !bestPath || (f && f.c < bestPath.c) ? f : bestPath;
316
- }
317
- }
318
- if (bestPath && bestPath.c < maxCost) {
319
- maxCost = bestPath.c;
320
- }
321
- }
322
- return pathToWords(bestPath);
323
- }
324
- function mergeSortedBreaks(...maps) {
325
- return maps.flat().sort((a, b) => a.offset - b.offset);
326
- }
327
- export const __testing__ = {
328
- generateWordBreaks,
329
- findNextWordText,
330
- };
331
- //# sourceMappingURL=wordSplitter.js.map