litura-app 0.3.7 → 0.4.2
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 +10 -0
- package/index.js +15 -7
- package/package.json +5 -2
- package/public/app.js +1267 -201
- package/public/dictionary/LICENSE +347 -0
- package/public/dictionary/en.aff +205 -0
- package/public/dictionary/en.dic +49569 -0
- package/public/index.html +0 -1
- package/public/style.css +51 -34
- package/review.js +1 -1
- package/suggestions.js +16 -4
package/public/app.js
CHANGED
|
@@ -1,4 +1,1000 @@
|
|
|
1
1
|
(() => {
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
// node_modules/is-buffer/index.js
|
|
29
|
+
var require_is_buffer = __commonJS({
|
|
30
|
+
"node_modules/is-buffer/index.js"(exports, module) {
|
|
31
|
+
module.exports = function isBuffer(obj) {
|
|
32
|
+
return obj != null && obj.constructor != null && typeof obj.constructor.isBuffer === "function" && obj.constructor.isBuffer(obj);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// node_modules/nspell/lib/util/rule-codes.js
|
|
38
|
+
var require_rule_codes = __commonJS({
|
|
39
|
+
"node_modules/nspell/lib/util/rule-codes.js"(exports, module) {
|
|
40
|
+
"use strict";
|
|
41
|
+
module.exports = ruleCodes;
|
|
42
|
+
var NO_CODES = [];
|
|
43
|
+
function ruleCodes(flags, value) {
|
|
44
|
+
var index = 0;
|
|
45
|
+
var result;
|
|
46
|
+
if (!value) return NO_CODES;
|
|
47
|
+
if (flags.FLAG === "long") {
|
|
48
|
+
result = new Array(Math.ceil(value.length / 2));
|
|
49
|
+
while (index < value.length) {
|
|
50
|
+
result[index / 2] = value.slice(index, index + 2);
|
|
51
|
+
index += 2;
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
return value.split(flags.FLAG === "num" ? "," : "");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// node_modules/nspell/lib/util/affix.js
|
|
61
|
+
var require_affix = __commonJS({
|
|
62
|
+
"node_modules/nspell/lib/util/affix.js"(exports, module) {
|
|
63
|
+
"use strict";
|
|
64
|
+
var parse = require_rule_codes();
|
|
65
|
+
module.exports = affix;
|
|
66
|
+
var push = [].push;
|
|
67
|
+
var alphabet = "etaoinshrdlcumwfgypbvkjxqz".split("");
|
|
68
|
+
var whiteSpaceExpression = /\s+/;
|
|
69
|
+
var defaultKeyboardLayout = [
|
|
70
|
+
"qwertzuop",
|
|
71
|
+
"yxcvbnm",
|
|
72
|
+
"qaw",
|
|
73
|
+
"say",
|
|
74
|
+
"wse",
|
|
75
|
+
"dsx",
|
|
76
|
+
"sy",
|
|
77
|
+
"edr",
|
|
78
|
+
"fdc",
|
|
79
|
+
"dx",
|
|
80
|
+
"rft",
|
|
81
|
+
"gfv",
|
|
82
|
+
"fc",
|
|
83
|
+
"tgz",
|
|
84
|
+
"hgb",
|
|
85
|
+
"gv",
|
|
86
|
+
"zhu",
|
|
87
|
+
"jhn",
|
|
88
|
+
"hb",
|
|
89
|
+
"uji",
|
|
90
|
+
"kjm",
|
|
91
|
+
"jn",
|
|
92
|
+
"iko",
|
|
93
|
+
"lkm"
|
|
94
|
+
];
|
|
95
|
+
function affix(doc2) {
|
|
96
|
+
var rules = /* @__PURE__ */ Object.create(null);
|
|
97
|
+
var compoundRuleCodes = /* @__PURE__ */ Object.create(null);
|
|
98
|
+
var flags = /* @__PURE__ */ Object.create(null);
|
|
99
|
+
var replacementTable = [];
|
|
100
|
+
var conversion = { in: [], out: [] };
|
|
101
|
+
var compoundRules = [];
|
|
102
|
+
var aff = doc2.toString("utf8");
|
|
103
|
+
var lines = [];
|
|
104
|
+
var last = 0;
|
|
105
|
+
var index = aff.indexOf("\n");
|
|
106
|
+
var parts;
|
|
107
|
+
var line;
|
|
108
|
+
var ruleType;
|
|
109
|
+
var count;
|
|
110
|
+
var remove2;
|
|
111
|
+
var add2;
|
|
112
|
+
var source;
|
|
113
|
+
var entry;
|
|
114
|
+
var position;
|
|
115
|
+
var rule;
|
|
116
|
+
var value;
|
|
117
|
+
var offset;
|
|
118
|
+
var character;
|
|
119
|
+
flags.KEY = [];
|
|
120
|
+
while (index > -1) {
|
|
121
|
+
pushLine(aff.slice(last, index));
|
|
122
|
+
last = index + 1;
|
|
123
|
+
index = aff.indexOf("\n", last);
|
|
124
|
+
}
|
|
125
|
+
pushLine(aff.slice(last));
|
|
126
|
+
index = -1;
|
|
127
|
+
while (++index < lines.length) {
|
|
128
|
+
line = lines[index];
|
|
129
|
+
parts = line.split(whiteSpaceExpression);
|
|
130
|
+
ruleType = parts[0];
|
|
131
|
+
if (ruleType === "REP") {
|
|
132
|
+
count = index + parseInt(parts[1], 10);
|
|
133
|
+
while (++index <= count) {
|
|
134
|
+
parts = lines[index].split(whiteSpaceExpression);
|
|
135
|
+
replacementTable.push([parts[1], parts[2]]);
|
|
136
|
+
}
|
|
137
|
+
index--;
|
|
138
|
+
} else if (ruleType === "ICONV" || ruleType === "OCONV") {
|
|
139
|
+
count = index + parseInt(parts[1], 10);
|
|
140
|
+
entry = conversion[ruleType === "ICONV" ? "in" : "out"];
|
|
141
|
+
while (++index <= count) {
|
|
142
|
+
parts = lines[index].split(whiteSpaceExpression);
|
|
143
|
+
entry.push([new RegExp(parts[1], "g"), parts[2]]);
|
|
144
|
+
}
|
|
145
|
+
index--;
|
|
146
|
+
} else if (ruleType === "COMPOUNDRULE") {
|
|
147
|
+
count = index + parseInt(parts[1], 10);
|
|
148
|
+
while (++index <= count) {
|
|
149
|
+
rule = lines[index].split(whiteSpaceExpression)[1];
|
|
150
|
+
position = -1;
|
|
151
|
+
compoundRules.push(rule);
|
|
152
|
+
while (++position < rule.length) {
|
|
153
|
+
compoundRuleCodes[rule.charAt(position)] = [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
index--;
|
|
157
|
+
} else if (ruleType === "PFX" || ruleType === "SFX") {
|
|
158
|
+
count = index + parseInt(parts[3], 10);
|
|
159
|
+
rule = {
|
|
160
|
+
type: ruleType,
|
|
161
|
+
combineable: parts[2] === "Y",
|
|
162
|
+
entries: []
|
|
163
|
+
};
|
|
164
|
+
rules[parts[1]] = rule;
|
|
165
|
+
while (++index <= count) {
|
|
166
|
+
parts = lines[index].split(whiteSpaceExpression);
|
|
167
|
+
remove2 = parts[2];
|
|
168
|
+
add2 = parts[3].split("/");
|
|
169
|
+
source = parts[4];
|
|
170
|
+
entry = {
|
|
171
|
+
add: "",
|
|
172
|
+
remove: "",
|
|
173
|
+
match: "",
|
|
174
|
+
continuation: parse(flags, add2[1])
|
|
175
|
+
};
|
|
176
|
+
if (add2 && add2[0] !== "0") {
|
|
177
|
+
entry.add = add2[0];
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
if (remove2 !== "0") {
|
|
181
|
+
entry.remove = ruleType === "SFX" ? end(remove2) : remove2;
|
|
182
|
+
}
|
|
183
|
+
if (source && source !== ".") {
|
|
184
|
+
entry.match = ruleType === "SFX" ? end(source) : start(source);
|
|
185
|
+
}
|
|
186
|
+
} catch (_) {
|
|
187
|
+
entry = null;
|
|
188
|
+
}
|
|
189
|
+
if (entry) {
|
|
190
|
+
rule.entries.push(entry);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
index--;
|
|
194
|
+
} else if (ruleType === "TRY") {
|
|
195
|
+
source = parts[1];
|
|
196
|
+
offset = -1;
|
|
197
|
+
value = [];
|
|
198
|
+
while (++offset < source.length) {
|
|
199
|
+
character = source.charAt(offset);
|
|
200
|
+
if (character.toLowerCase() === character) {
|
|
201
|
+
value.push(character);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
offset = -1;
|
|
205
|
+
while (++offset < alphabet.length) {
|
|
206
|
+
if (source.indexOf(alphabet[offset]) < 0) {
|
|
207
|
+
value.push(alphabet[offset]);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
flags[ruleType] = value;
|
|
211
|
+
} else if (ruleType === "KEY") {
|
|
212
|
+
push.apply(flags[ruleType], parts[1].split("|"));
|
|
213
|
+
} else if (ruleType === "COMPOUNDMIN") {
|
|
214
|
+
flags[ruleType] = Number(parts[1]);
|
|
215
|
+
} else if (ruleType === "ONLYINCOMPOUND") {
|
|
216
|
+
flags[ruleType] = parts[1];
|
|
217
|
+
compoundRuleCodes[parts[1]] = [];
|
|
218
|
+
} else if (ruleType === "FLAG" || ruleType === "KEEPCASE" || ruleType === "NOSUGGEST" || ruleType === "WORDCHARS") {
|
|
219
|
+
flags[ruleType] = parts[1];
|
|
220
|
+
} else {
|
|
221
|
+
flags[ruleType] = parts[1];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (isNaN(flags.COMPOUNDMIN)) {
|
|
225
|
+
flags.COMPOUNDMIN = 3;
|
|
226
|
+
}
|
|
227
|
+
if (!flags.KEY.length) {
|
|
228
|
+
flags.KEY = defaultKeyboardLayout;
|
|
229
|
+
}
|
|
230
|
+
if (!flags.TRY) {
|
|
231
|
+
flags.TRY = alphabet.concat();
|
|
232
|
+
}
|
|
233
|
+
if (!flags.KEEPCASE) {
|
|
234
|
+
flags.KEEPCASE = false;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
compoundRuleCodes,
|
|
238
|
+
replacementTable,
|
|
239
|
+
conversion,
|
|
240
|
+
compoundRules,
|
|
241
|
+
rules,
|
|
242
|
+
flags
|
|
243
|
+
};
|
|
244
|
+
function pushLine(line2) {
|
|
245
|
+
line2 = line2.trim();
|
|
246
|
+
if (line2 && line2.charCodeAt(0) !== 35) {
|
|
247
|
+
lines.push(line2);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function end(source) {
|
|
252
|
+
return new RegExp(source + "$");
|
|
253
|
+
}
|
|
254
|
+
function start(source) {
|
|
255
|
+
return new RegExp("^" + source);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// node_modules/nspell/lib/util/normalize.js
|
|
261
|
+
var require_normalize = __commonJS({
|
|
262
|
+
"node_modules/nspell/lib/util/normalize.js"(exports, module) {
|
|
263
|
+
"use strict";
|
|
264
|
+
module.exports = normalize;
|
|
265
|
+
function normalize(value, patterns) {
|
|
266
|
+
var index = -1;
|
|
267
|
+
while (++index < patterns.length) {
|
|
268
|
+
value = value.replace(patterns[index][0], patterns[index][1]);
|
|
269
|
+
}
|
|
270
|
+
return value;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// node_modules/nspell/lib/util/flag.js
|
|
276
|
+
var require_flag = __commonJS({
|
|
277
|
+
"node_modules/nspell/lib/util/flag.js"(exports, module) {
|
|
278
|
+
"use strict";
|
|
279
|
+
module.exports = flag;
|
|
280
|
+
function flag(values, value, flags) {
|
|
281
|
+
return flags && value in values && flags.indexOf(values[value]) > -1;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// node_modules/nspell/lib/util/exact.js
|
|
287
|
+
var require_exact = __commonJS({
|
|
288
|
+
"node_modules/nspell/lib/util/exact.js"(exports, module) {
|
|
289
|
+
"use strict";
|
|
290
|
+
var flag = require_flag();
|
|
291
|
+
module.exports = exact;
|
|
292
|
+
function exact(context, value) {
|
|
293
|
+
var index = -1;
|
|
294
|
+
if (context.data[value]) {
|
|
295
|
+
return !flag(context.flags, "ONLYINCOMPOUND", context.data[value]);
|
|
296
|
+
}
|
|
297
|
+
if (value.length >= context.flags.COMPOUNDMIN) {
|
|
298
|
+
while (++index < context.compoundRules.length) {
|
|
299
|
+
if (context.compoundRules[index].test(value)) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// node_modules/nspell/lib/util/form.js
|
|
310
|
+
var require_form = __commonJS({
|
|
311
|
+
"node_modules/nspell/lib/util/form.js"(exports, module) {
|
|
312
|
+
"use strict";
|
|
313
|
+
var normalize = require_normalize();
|
|
314
|
+
var exact = require_exact();
|
|
315
|
+
var flag = require_flag();
|
|
316
|
+
module.exports = form;
|
|
317
|
+
function form(context, value, all) {
|
|
318
|
+
var normal = value.trim();
|
|
319
|
+
var alternative;
|
|
320
|
+
if (!normal) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
normal = normalize(normal, context.conversion.in);
|
|
324
|
+
if (exact(context, normal)) {
|
|
325
|
+
if (!all && flag(context.flags, "FORBIDDENWORD", context.data[normal])) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
return normal;
|
|
329
|
+
}
|
|
330
|
+
if (normal.toUpperCase() === normal) {
|
|
331
|
+
alternative = normal.charAt(0) + normal.slice(1).toLowerCase();
|
|
332
|
+
if (ignore(context.flags, context.data[alternative], all)) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (exact(context, alternative)) {
|
|
336
|
+
return alternative;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
alternative = normal.toLowerCase();
|
|
340
|
+
if (alternative !== normal) {
|
|
341
|
+
if (ignore(context.flags, context.data[alternative], all)) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
if (exact(context, alternative)) {
|
|
345
|
+
return alternative;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
function ignore(flags, dict, all) {
|
|
351
|
+
return flag(flags, "KEEPCASE", dict) || all || flag(flags, "FORBIDDENWORD", dict);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// node_modules/nspell/lib/correct.js
|
|
357
|
+
var require_correct = __commonJS({
|
|
358
|
+
"node_modules/nspell/lib/correct.js"(exports, module) {
|
|
359
|
+
"use strict";
|
|
360
|
+
var form = require_form();
|
|
361
|
+
module.exports = correct;
|
|
362
|
+
function correct(value) {
|
|
363
|
+
return Boolean(form(this, value));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// node_modules/nspell/lib/util/casing.js
|
|
369
|
+
var require_casing = __commonJS({
|
|
370
|
+
"node_modules/nspell/lib/util/casing.js"(exports, module) {
|
|
371
|
+
"use strict";
|
|
372
|
+
module.exports = casing;
|
|
373
|
+
function casing(value) {
|
|
374
|
+
var head = exact(value.charAt(0));
|
|
375
|
+
var rest = value.slice(1);
|
|
376
|
+
if (!rest) {
|
|
377
|
+
return head;
|
|
378
|
+
}
|
|
379
|
+
rest = exact(rest);
|
|
380
|
+
if (head === rest) {
|
|
381
|
+
return head;
|
|
382
|
+
}
|
|
383
|
+
if (head === "u" && rest === "l") {
|
|
384
|
+
return "s";
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
function exact(value) {
|
|
389
|
+
return value === value.toLowerCase() ? "l" : value === value.toUpperCase() ? "u" : null;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// node_modules/nspell/lib/suggest.js
|
|
395
|
+
var require_suggest = __commonJS({
|
|
396
|
+
"node_modules/nspell/lib/suggest.js"(exports, module) {
|
|
397
|
+
"use strict";
|
|
398
|
+
var casing = require_casing();
|
|
399
|
+
var normalize = require_normalize();
|
|
400
|
+
var flag = require_flag();
|
|
401
|
+
var form = require_form();
|
|
402
|
+
module.exports = suggest;
|
|
403
|
+
var push = [].push;
|
|
404
|
+
function suggest(value) {
|
|
405
|
+
var self = this;
|
|
406
|
+
var charAdded = {};
|
|
407
|
+
var suggestions = [];
|
|
408
|
+
var weighted = {};
|
|
409
|
+
var memory;
|
|
410
|
+
var replacement;
|
|
411
|
+
var edits = [];
|
|
412
|
+
var values;
|
|
413
|
+
var index;
|
|
414
|
+
var offset;
|
|
415
|
+
var position;
|
|
416
|
+
var count;
|
|
417
|
+
var otherOffset;
|
|
418
|
+
var otherCharacter;
|
|
419
|
+
var character;
|
|
420
|
+
var group;
|
|
421
|
+
var before;
|
|
422
|
+
var after;
|
|
423
|
+
var upper;
|
|
424
|
+
var insensitive;
|
|
425
|
+
var firstLevel;
|
|
426
|
+
var previous;
|
|
427
|
+
var next;
|
|
428
|
+
var nextCharacter;
|
|
429
|
+
var max;
|
|
430
|
+
var distance;
|
|
431
|
+
var size;
|
|
432
|
+
var normalized;
|
|
433
|
+
var suggestion;
|
|
434
|
+
var currentCase;
|
|
435
|
+
value = normalize(value.trim(), self.conversion.in);
|
|
436
|
+
if (!value || self.correct(value)) {
|
|
437
|
+
return [];
|
|
438
|
+
}
|
|
439
|
+
currentCase = casing(value);
|
|
440
|
+
index = -1;
|
|
441
|
+
while (++index < self.replacementTable.length) {
|
|
442
|
+
replacement = self.replacementTable[index];
|
|
443
|
+
offset = value.indexOf(replacement[0]);
|
|
444
|
+
while (offset > -1) {
|
|
445
|
+
edits.push(value.replace(replacement[0], replacement[1]));
|
|
446
|
+
offset = value.indexOf(replacement[0], offset + 1);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
index = -1;
|
|
450
|
+
while (++index < value.length) {
|
|
451
|
+
character = value.charAt(index);
|
|
452
|
+
before = value.slice(0, index);
|
|
453
|
+
after = value.slice(index + 1);
|
|
454
|
+
insensitive = character.toLowerCase();
|
|
455
|
+
upper = insensitive !== character;
|
|
456
|
+
charAdded = {};
|
|
457
|
+
offset = -1;
|
|
458
|
+
while (++offset < self.flags.KEY.length) {
|
|
459
|
+
group = self.flags.KEY[offset];
|
|
460
|
+
position = group.indexOf(insensitive);
|
|
461
|
+
if (position < 0) {
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
otherOffset = -1;
|
|
465
|
+
while (++otherOffset < group.length) {
|
|
466
|
+
if (otherOffset !== position) {
|
|
467
|
+
otherCharacter = group.charAt(otherOffset);
|
|
468
|
+
if (charAdded[otherCharacter]) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
charAdded[otherCharacter] = true;
|
|
472
|
+
if (upper) {
|
|
473
|
+
otherCharacter = otherCharacter.toUpperCase();
|
|
474
|
+
}
|
|
475
|
+
edits.push(before + otherCharacter + after);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
index = -1;
|
|
481
|
+
nextCharacter = value.charAt(0);
|
|
482
|
+
values = [""];
|
|
483
|
+
max = 1;
|
|
484
|
+
distance = 0;
|
|
485
|
+
while (++index < value.length) {
|
|
486
|
+
character = nextCharacter;
|
|
487
|
+
nextCharacter = value.charAt(index + 1);
|
|
488
|
+
before = value.slice(0, index);
|
|
489
|
+
replacement = character === nextCharacter ? "" : character + character;
|
|
490
|
+
offset = -1;
|
|
491
|
+
count = values.length;
|
|
492
|
+
while (++offset < count) {
|
|
493
|
+
if (offset <= max) {
|
|
494
|
+
values.push(values[offset] + replacement);
|
|
495
|
+
}
|
|
496
|
+
values[offset] += character;
|
|
497
|
+
}
|
|
498
|
+
if (++distance < 3) {
|
|
499
|
+
max = values.length;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
push.apply(edits, values);
|
|
503
|
+
values = [value];
|
|
504
|
+
replacement = value.toLowerCase();
|
|
505
|
+
if (value === replacement || currentCase === null) {
|
|
506
|
+
values.push(value.charAt(0).toUpperCase() + replacement.slice(1));
|
|
507
|
+
}
|
|
508
|
+
replacement = value.toUpperCase();
|
|
509
|
+
if (value !== replacement) {
|
|
510
|
+
values.push(replacement);
|
|
511
|
+
}
|
|
512
|
+
memory = {
|
|
513
|
+
state: {},
|
|
514
|
+
weighted,
|
|
515
|
+
suggestions
|
|
516
|
+
};
|
|
517
|
+
firstLevel = generate(self, memory, values, edits);
|
|
518
|
+
previous = 0;
|
|
519
|
+
max = Math.min(firstLevel.length, Math.pow(Math.max(15 - value.length, 3), 3));
|
|
520
|
+
size = Math.max(Math.pow(10 - value.length, 3), 1);
|
|
521
|
+
while (!suggestions.length && previous < max) {
|
|
522
|
+
next = previous + size;
|
|
523
|
+
generate(self, memory, firstLevel.slice(previous, next));
|
|
524
|
+
previous = next;
|
|
525
|
+
}
|
|
526
|
+
suggestions.sort(sort);
|
|
527
|
+
values = [];
|
|
528
|
+
normalized = [];
|
|
529
|
+
index = -1;
|
|
530
|
+
while (++index < suggestions.length) {
|
|
531
|
+
suggestion = normalize(suggestions[index], self.conversion.out);
|
|
532
|
+
replacement = suggestion.toLowerCase();
|
|
533
|
+
if (normalized.indexOf(replacement) < 0) {
|
|
534
|
+
values.push(suggestion);
|
|
535
|
+
normalized.push(replacement);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return values;
|
|
539
|
+
function sort(a, b) {
|
|
540
|
+
return sortWeight(a, b) || sortCasing(a, b) || sortAlpha(a, b);
|
|
541
|
+
}
|
|
542
|
+
function sortWeight(a, b) {
|
|
543
|
+
return weighted[a] === weighted[b] ? 0 : weighted[a] > weighted[b] ? -1 : 1;
|
|
544
|
+
}
|
|
545
|
+
function sortCasing(a, b) {
|
|
546
|
+
var leftCasing = casing(a);
|
|
547
|
+
var rightCasing = casing(b);
|
|
548
|
+
return leftCasing === rightCasing ? 0 : leftCasing === currentCase ? -1 : rightCasing === currentCase ? 1 : void 0;
|
|
549
|
+
}
|
|
550
|
+
function sortAlpha(a, b) {
|
|
551
|
+
return a.localeCompare(b);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
function generate(context, memory, words, edits) {
|
|
555
|
+
var characters = context.flags.TRY;
|
|
556
|
+
var data = context.data;
|
|
557
|
+
var flags = context.flags;
|
|
558
|
+
var result = [];
|
|
559
|
+
var index = -1;
|
|
560
|
+
var word;
|
|
561
|
+
var before;
|
|
562
|
+
var character;
|
|
563
|
+
var nextCharacter;
|
|
564
|
+
var nextAfter;
|
|
565
|
+
var nextNextAfter;
|
|
566
|
+
var nextUpper;
|
|
567
|
+
var currentCase;
|
|
568
|
+
var position;
|
|
569
|
+
var after;
|
|
570
|
+
var upper;
|
|
571
|
+
var inject;
|
|
572
|
+
var offset;
|
|
573
|
+
if (edits) {
|
|
574
|
+
while (++index < edits.length) {
|
|
575
|
+
check(edits[index], true);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
index = -1;
|
|
579
|
+
while (++index < words.length) {
|
|
580
|
+
word = words[index];
|
|
581
|
+
before = "";
|
|
582
|
+
character = "";
|
|
583
|
+
nextCharacter = word.charAt(0);
|
|
584
|
+
nextAfter = word;
|
|
585
|
+
nextNextAfter = word.slice(1);
|
|
586
|
+
nextUpper = nextCharacter.toLowerCase() !== nextCharacter;
|
|
587
|
+
currentCase = casing(word);
|
|
588
|
+
position = -1;
|
|
589
|
+
while (++position <= word.length) {
|
|
590
|
+
before += character;
|
|
591
|
+
after = nextAfter;
|
|
592
|
+
nextAfter = nextNextAfter;
|
|
593
|
+
nextNextAfter = nextAfter.slice(1);
|
|
594
|
+
character = nextCharacter;
|
|
595
|
+
nextCharacter = word.charAt(position + 1);
|
|
596
|
+
upper = nextUpper;
|
|
597
|
+
if (nextCharacter) {
|
|
598
|
+
nextUpper = nextCharacter.toLowerCase() !== nextCharacter;
|
|
599
|
+
}
|
|
600
|
+
if (nextAfter && upper !== nextUpper) {
|
|
601
|
+
check(before + switchCase(nextAfter));
|
|
602
|
+
check(
|
|
603
|
+
before + switchCase(nextCharacter) + switchCase(character) + nextNextAfter
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
check(before + nextAfter);
|
|
607
|
+
if (nextAfter) {
|
|
608
|
+
check(before + nextCharacter + character + nextNextAfter);
|
|
609
|
+
}
|
|
610
|
+
offset = -1;
|
|
611
|
+
while (++offset < characters.length) {
|
|
612
|
+
inject = characters[offset];
|
|
613
|
+
if (upper && inject !== inject.toUpperCase()) {
|
|
614
|
+
if (currentCase !== "s") {
|
|
615
|
+
check(before + inject + after);
|
|
616
|
+
check(before + inject + nextAfter);
|
|
617
|
+
}
|
|
618
|
+
inject = inject.toUpperCase();
|
|
619
|
+
check(before + inject + after);
|
|
620
|
+
check(before + inject + nextAfter);
|
|
621
|
+
} else {
|
|
622
|
+
check(before + inject + after);
|
|
623
|
+
check(before + inject + nextAfter);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return result;
|
|
629
|
+
function check(value, double) {
|
|
630
|
+
var state = memory.state[value];
|
|
631
|
+
var corrected;
|
|
632
|
+
if (state !== Boolean(state)) {
|
|
633
|
+
result.push(value);
|
|
634
|
+
corrected = form(context, value);
|
|
635
|
+
state = corrected && !flag(flags, "NOSUGGEST", data[corrected]);
|
|
636
|
+
memory.state[value] = state;
|
|
637
|
+
if (state) {
|
|
638
|
+
memory.weighted[value] = double ? 10 : 0;
|
|
639
|
+
memory.suggestions.push(value);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (state) {
|
|
643
|
+
memory.weighted[value]++;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
function switchCase(fragment) {
|
|
647
|
+
var first = fragment.charAt(0);
|
|
648
|
+
return (first.toLowerCase() === first ? first.toUpperCase() : first.toLowerCase()) + fragment.slice(1);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// node_modules/nspell/lib/spell.js
|
|
655
|
+
var require_spell = __commonJS({
|
|
656
|
+
"node_modules/nspell/lib/spell.js"(exports, module) {
|
|
657
|
+
"use strict";
|
|
658
|
+
var form = require_form();
|
|
659
|
+
var flag = require_flag();
|
|
660
|
+
module.exports = spell;
|
|
661
|
+
function spell(word) {
|
|
662
|
+
var self = this;
|
|
663
|
+
var value = form(self, word, true);
|
|
664
|
+
return {
|
|
665
|
+
correct: self.correct(word),
|
|
666
|
+
forbidden: Boolean(
|
|
667
|
+
value && flag(self.flags, "FORBIDDENWORD", self.data[value])
|
|
668
|
+
),
|
|
669
|
+
warn: Boolean(value && flag(self.flags, "WARN", self.data[value]))
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
// node_modules/nspell/lib/util/apply.js
|
|
676
|
+
var require_apply = __commonJS({
|
|
677
|
+
"node_modules/nspell/lib/util/apply.js"(exports, module) {
|
|
678
|
+
"use strict";
|
|
679
|
+
module.exports = apply;
|
|
680
|
+
function apply(value, rule, rules, words) {
|
|
681
|
+
var index = -1;
|
|
682
|
+
var entry;
|
|
683
|
+
var next;
|
|
684
|
+
var continuationRule;
|
|
685
|
+
var continuation;
|
|
686
|
+
var position;
|
|
687
|
+
while (++index < rule.entries.length) {
|
|
688
|
+
entry = rule.entries[index];
|
|
689
|
+
continuation = entry.continuation;
|
|
690
|
+
position = -1;
|
|
691
|
+
if (!entry.match || entry.match.test(value)) {
|
|
692
|
+
next = entry.remove ? value.replace(entry.remove, "") : value;
|
|
693
|
+
next = rule.type === "SFX" ? next + entry.add : entry.add + next;
|
|
694
|
+
words.push(next);
|
|
695
|
+
if (continuation && continuation.length) {
|
|
696
|
+
while (++position < continuation.length) {
|
|
697
|
+
continuationRule = rules[continuation[position]];
|
|
698
|
+
if (continuationRule) {
|
|
699
|
+
apply(next, continuationRule, rules, words);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return words;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
// node_modules/nspell/lib/util/add.js
|
|
711
|
+
var require_add = __commonJS({
|
|
712
|
+
"node_modules/nspell/lib/util/add.js"(exports, module) {
|
|
713
|
+
"use strict";
|
|
714
|
+
var apply = require_apply();
|
|
715
|
+
module.exports = add2;
|
|
716
|
+
var push = [].push;
|
|
717
|
+
var NO_RULES = [];
|
|
718
|
+
function addRules(dict, word, rules) {
|
|
719
|
+
var curr = dict[word];
|
|
720
|
+
if (word in dict) {
|
|
721
|
+
if (curr === NO_RULES) {
|
|
722
|
+
dict[word] = rules.concat();
|
|
723
|
+
} else {
|
|
724
|
+
push.apply(curr, rules);
|
|
725
|
+
}
|
|
726
|
+
} else {
|
|
727
|
+
dict[word] = rules.concat();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function add2(dict, word, codes, options) {
|
|
731
|
+
var position = -1;
|
|
732
|
+
var rule;
|
|
733
|
+
var offset;
|
|
734
|
+
var subposition;
|
|
735
|
+
var suboffset;
|
|
736
|
+
var combined;
|
|
737
|
+
var newWords;
|
|
738
|
+
var otherNewWords;
|
|
739
|
+
if (!("NEEDAFFIX" in options.flags) || codes.indexOf(options.flags.NEEDAFFIX) < 0) {
|
|
740
|
+
addRules(dict, word, codes);
|
|
741
|
+
}
|
|
742
|
+
while (++position < codes.length) {
|
|
743
|
+
rule = options.rules[codes[position]];
|
|
744
|
+
if (codes[position] in options.compoundRuleCodes) {
|
|
745
|
+
options.compoundRuleCodes[codes[position]].push(word);
|
|
746
|
+
}
|
|
747
|
+
if (rule) {
|
|
748
|
+
newWords = apply(word, rule, options.rules, []);
|
|
749
|
+
offset = -1;
|
|
750
|
+
while (++offset < newWords.length) {
|
|
751
|
+
if (!(newWords[offset] in dict)) {
|
|
752
|
+
dict[newWords[offset]] = NO_RULES;
|
|
753
|
+
}
|
|
754
|
+
if (rule.combineable) {
|
|
755
|
+
subposition = position;
|
|
756
|
+
while (++subposition < codes.length) {
|
|
757
|
+
combined = options.rules[codes[subposition]];
|
|
758
|
+
if (combined && combined.combineable && rule.type !== combined.type) {
|
|
759
|
+
otherNewWords = apply(
|
|
760
|
+
newWords[offset],
|
|
761
|
+
combined,
|
|
762
|
+
options.rules,
|
|
763
|
+
[]
|
|
764
|
+
);
|
|
765
|
+
suboffset = -1;
|
|
766
|
+
while (++suboffset < otherNewWords.length) {
|
|
767
|
+
if (!(otherNewWords[suboffset] in dict)) {
|
|
768
|
+
dict[otherNewWords[suboffset]] = NO_RULES;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
// node_modules/nspell/lib/add.js
|
|
782
|
+
var require_add2 = __commonJS({
|
|
783
|
+
"node_modules/nspell/lib/add.js"(exports, module) {
|
|
784
|
+
"use strict";
|
|
785
|
+
var push = require_add();
|
|
786
|
+
module.exports = add2;
|
|
787
|
+
var NO_CODES = [];
|
|
788
|
+
function add2(value, model) {
|
|
789
|
+
var self = this;
|
|
790
|
+
push(self.data, value, self.data[model] || NO_CODES, self);
|
|
791
|
+
return self;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
// node_modules/nspell/lib/remove.js
|
|
797
|
+
var require_remove = __commonJS({
|
|
798
|
+
"node_modules/nspell/lib/remove.js"(exports, module) {
|
|
799
|
+
"use strict";
|
|
800
|
+
module.exports = remove2;
|
|
801
|
+
function remove2(value) {
|
|
802
|
+
var self = this;
|
|
803
|
+
delete self.data[value];
|
|
804
|
+
return self;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
// node_modules/nspell/lib/word-characters.js
|
|
810
|
+
var require_word_characters = __commonJS({
|
|
811
|
+
"node_modules/nspell/lib/word-characters.js"(exports, module) {
|
|
812
|
+
"use strict";
|
|
813
|
+
module.exports = wordCharacters;
|
|
814
|
+
function wordCharacters() {
|
|
815
|
+
return this.flags.WORDCHARS || null;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
// node_modules/nspell/lib/util/dictionary.js
|
|
821
|
+
var require_dictionary = __commonJS({
|
|
822
|
+
"node_modules/nspell/lib/util/dictionary.js"(exports, module) {
|
|
823
|
+
"use strict";
|
|
824
|
+
var parseCodes = require_rule_codes();
|
|
825
|
+
var add2 = require_add();
|
|
826
|
+
module.exports = parse;
|
|
827
|
+
var whiteSpaceExpression = /\s/g;
|
|
828
|
+
function parse(buf, options, dict) {
|
|
829
|
+
var value = buf.toString("utf8");
|
|
830
|
+
var last = value.indexOf("\n") + 1;
|
|
831
|
+
var index = value.indexOf("\n", last);
|
|
832
|
+
while (index > -1) {
|
|
833
|
+
if (value.charCodeAt(last) !== 9) {
|
|
834
|
+
parseLine(value.slice(last, index), options, dict);
|
|
835
|
+
}
|
|
836
|
+
last = index + 1;
|
|
837
|
+
index = value.indexOf("\n", last);
|
|
838
|
+
}
|
|
839
|
+
parseLine(value.slice(last), options, dict);
|
|
840
|
+
}
|
|
841
|
+
function parseLine(line, options, dict) {
|
|
842
|
+
var slashOffset = line.indexOf("/");
|
|
843
|
+
var hashOffset = line.indexOf("#");
|
|
844
|
+
var codes = "";
|
|
845
|
+
var word;
|
|
846
|
+
var result;
|
|
847
|
+
while (slashOffset > -1 && line.charCodeAt(slashOffset - 1) === 92) {
|
|
848
|
+
line = line.slice(0, slashOffset - 1) + line.slice(slashOffset);
|
|
849
|
+
slashOffset = line.indexOf("/", slashOffset);
|
|
850
|
+
}
|
|
851
|
+
if (hashOffset > -1) {
|
|
852
|
+
if (slashOffset > -1 && slashOffset < hashOffset) {
|
|
853
|
+
word = line.slice(0, slashOffset);
|
|
854
|
+
whiteSpaceExpression.lastIndex = slashOffset + 1;
|
|
855
|
+
result = whiteSpaceExpression.exec(line);
|
|
856
|
+
codes = line.slice(slashOffset + 1, result ? result.index : void 0);
|
|
857
|
+
} else {
|
|
858
|
+
word = line.slice(0, hashOffset);
|
|
859
|
+
}
|
|
860
|
+
} else if (slashOffset > -1) {
|
|
861
|
+
word = line.slice(0, slashOffset);
|
|
862
|
+
codes = line.slice(slashOffset + 1);
|
|
863
|
+
} else {
|
|
864
|
+
word = line;
|
|
865
|
+
}
|
|
866
|
+
word = word.trim();
|
|
867
|
+
if (word) {
|
|
868
|
+
add2(dict, word, parseCodes(options.flags, codes.trim()), options);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
// node_modules/nspell/lib/dictionary.js
|
|
875
|
+
var require_dictionary2 = __commonJS({
|
|
876
|
+
"node_modules/nspell/lib/dictionary.js"(exports, module) {
|
|
877
|
+
"use strict";
|
|
878
|
+
var parse = require_dictionary();
|
|
879
|
+
module.exports = add2;
|
|
880
|
+
function add2(buf) {
|
|
881
|
+
var self = this;
|
|
882
|
+
var index = -1;
|
|
883
|
+
var rule;
|
|
884
|
+
var source;
|
|
885
|
+
var character;
|
|
886
|
+
var offset;
|
|
887
|
+
parse(buf, self, self.data);
|
|
888
|
+
while (++index < self.compoundRules.length) {
|
|
889
|
+
rule = self.compoundRules[index];
|
|
890
|
+
source = "";
|
|
891
|
+
offset = -1;
|
|
892
|
+
while (++offset < rule.length) {
|
|
893
|
+
character = rule.charAt(offset);
|
|
894
|
+
source += self.compoundRuleCodes[character].length ? "(?:" + self.compoundRuleCodes[character].join("|") + ")" : character;
|
|
895
|
+
}
|
|
896
|
+
self.compoundRules[index] = new RegExp(source, "i");
|
|
897
|
+
}
|
|
898
|
+
return self;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
// node_modules/nspell/lib/personal.js
|
|
904
|
+
var require_personal = __commonJS({
|
|
905
|
+
"node_modules/nspell/lib/personal.js"(exports, module) {
|
|
906
|
+
"use strict";
|
|
907
|
+
module.exports = add2;
|
|
908
|
+
function add2(buf) {
|
|
909
|
+
var self = this;
|
|
910
|
+
var lines = buf.toString("utf8").split("\n");
|
|
911
|
+
var index = -1;
|
|
912
|
+
var line;
|
|
913
|
+
var forbidden;
|
|
914
|
+
var word;
|
|
915
|
+
var flag;
|
|
916
|
+
if (self.flags.FORBIDDENWORD === void 0) self.flags.FORBIDDENWORD = false;
|
|
917
|
+
flag = self.flags.FORBIDDENWORD;
|
|
918
|
+
while (++index < lines.length) {
|
|
919
|
+
line = lines[index].trim();
|
|
920
|
+
if (!line) {
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
line = line.split("/");
|
|
924
|
+
word = line[0];
|
|
925
|
+
forbidden = word.charAt(0) === "*";
|
|
926
|
+
if (forbidden) {
|
|
927
|
+
word = word.slice(1);
|
|
928
|
+
}
|
|
929
|
+
self.add(word, line[1]);
|
|
930
|
+
if (forbidden) {
|
|
931
|
+
self.data[word].push(flag);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
return self;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
|
|
939
|
+
// node_modules/nspell/lib/index.js
|
|
940
|
+
var require_lib = __commonJS({
|
|
941
|
+
"node_modules/nspell/lib/index.js"(exports, module) {
|
|
942
|
+
"use strict";
|
|
943
|
+
var buffer = require_is_buffer();
|
|
944
|
+
var affix = require_affix();
|
|
945
|
+
module.exports = NSpell;
|
|
946
|
+
var proto = NSpell.prototype;
|
|
947
|
+
proto.correct = require_correct();
|
|
948
|
+
proto.suggest = require_suggest();
|
|
949
|
+
proto.spell = require_spell();
|
|
950
|
+
proto.add = require_add2();
|
|
951
|
+
proto.remove = require_remove();
|
|
952
|
+
proto.wordCharacters = require_word_characters();
|
|
953
|
+
proto.dictionary = require_dictionary2();
|
|
954
|
+
proto.personal = require_personal();
|
|
955
|
+
function NSpell(aff, dic) {
|
|
956
|
+
var index = -1;
|
|
957
|
+
var dictionaries;
|
|
958
|
+
if (!(this instanceof NSpell)) {
|
|
959
|
+
return new NSpell(aff, dic);
|
|
960
|
+
}
|
|
961
|
+
if (typeof aff === "string" || buffer(aff)) {
|
|
962
|
+
if (typeof dic === "string" || buffer(dic)) {
|
|
963
|
+
dictionaries = [{ dic }];
|
|
964
|
+
}
|
|
965
|
+
} else if (aff) {
|
|
966
|
+
if ("length" in aff) {
|
|
967
|
+
dictionaries = aff;
|
|
968
|
+
aff = aff[0] && aff[0].aff;
|
|
969
|
+
} else {
|
|
970
|
+
if (aff.dic) {
|
|
971
|
+
dictionaries = [aff];
|
|
972
|
+
}
|
|
973
|
+
aff = aff.aff;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (!aff) {
|
|
977
|
+
throw new Error("Missing `aff` in dictionary");
|
|
978
|
+
}
|
|
979
|
+
aff = affix(aff);
|
|
980
|
+
this.data = /* @__PURE__ */ Object.create(null);
|
|
981
|
+
this.compoundRuleCodes = aff.compoundRuleCodes;
|
|
982
|
+
this.replacementTable = aff.replacementTable;
|
|
983
|
+
this.conversion = aff.conversion;
|
|
984
|
+
this.compoundRules = aff.compoundRules;
|
|
985
|
+
this.rules = aff.rules;
|
|
986
|
+
this.flags = aff.flags;
|
|
987
|
+
if (dictionaries) {
|
|
988
|
+
while (++index < dictionaries.length) {
|
|
989
|
+
if (dictionaries[index].dic) {
|
|
990
|
+
this.dictionary(dictionaries[index].dic);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
});
|
|
997
|
+
|
|
2
998
|
// node_modules/@marijn/find-cluster-break/src/index.js
|
|
3
999
|
var rangeFrom = [];
|
|
4
1000
|
var rangeTo = [];
|
|
@@ -16935,6 +17931,20 @@
|
|
|
16935
17931
|
return ["pending", "applied", "kept"].includes(edit.state) && Number.isInteger(edit.from) && Number.isInteger(edit.to) && edit.from >= 0 && edit.to >= edit.from && edit.to <= document2.length && document2.slice(edit.from, edit.to) === expected;
|
|
16936
17932
|
}
|
|
16937
17933
|
|
|
17934
|
+
// spellcheck.js
|
|
17935
|
+
var import_nspell = __toESM(require_lib(), 1);
|
|
17936
|
+
var cached = null;
|
|
17937
|
+
function loadSpellDictionary() {
|
|
17938
|
+
return cached ??= Promise.all([
|
|
17939
|
+
fetch("/dictionary/en.aff").then((res) => res.text()),
|
|
17940
|
+
fetch("/dictionary/en.dic").then((res) => res.text())
|
|
17941
|
+
]).then(([aff, dic]) => (0, import_nspell.default)(aff, dic));
|
|
17942
|
+
}
|
|
17943
|
+
function spellingMarkers(text, spell) {
|
|
17944
|
+
if (!spell || !isLatinScript(text)) return [];
|
|
17945
|
+
return [...text.matchAll(WORD_RE)].filter((match) => match[0].length > 1 && !/^[A-Z]+$/.test(match[0]) && !spell.correct(match[0])).map((match) => ({ from: match.index, to: match.index + match[0].length, quote: match[0] }));
|
|
17946
|
+
}
|
|
17947
|
+
|
|
16938
17948
|
// node_modules/@codemirror/search/dist/index.js
|
|
16939
17949
|
var basicNormalize = typeof String.prototype.normalize == "function" ? (x) => x.normalize("NFKD") : (x) => x;
|
|
16940
17950
|
var SearchCursor = class {
|
|
@@ -17127,21 +18137,21 @@
|
|
|
17127
18137
|
return this.from + this.text.length;
|
|
17128
18138
|
}
|
|
17129
18139
|
static get(doc2, from, to) {
|
|
17130
|
-
let
|
|
17131
|
-
if (!
|
|
18140
|
+
let cached2 = flattened.get(doc2);
|
|
18141
|
+
if (!cached2 || cached2.from >= to || cached2.to <= from) {
|
|
17132
18142
|
let flat = new _FlattenedDoc(from, doc2.sliceString(from, to));
|
|
17133
18143
|
flattened.set(doc2, flat);
|
|
17134
18144
|
return flat;
|
|
17135
18145
|
}
|
|
17136
|
-
if (
|
|
17137
|
-
return
|
|
17138
|
-
let { text, from: cachedFrom } =
|
|
18146
|
+
if (cached2.from == from && cached2.to == to)
|
|
18147
|
+
return cached2;
|
|
18148
|
+
let { text, from: cachedFrom } = cached2;
|
|
17139
18149
|
if (cachedFrom > from) {
|
|
17140
18150
|
text = doc2.sliceString(from, cachedFrom) + text;
|
|
17141
18151
|
cachedFrom = from;
|
|
17142
18152
|
}
|
|
17143
|
-
if (
|
|
17144
|
-
text += doc2.sliceString(
|
|
18153
|
+
if (cached2.to < to)
|
|
18154
|
+
text += doc2.sliceString(cached2.to, to);
|
|
17145
18155
|
flattened.set(doc2, new _FlattenedDoc(cachedFrom, text));
|
|
17146
18156
|
return new _FlattenedDoc(from, text.slice(from - cachedFrom, to - cachedFrom));
|
|
17147
18157
|
}
|
|
@@ -18165,8 +19175,8 @@
|
|
|
18165
19175
|
empty2.hidden = matched.length > 0;
|
|
18166
19176
|
if (count) count.textContent = !state.options.length ? "" : matched.length > shown.length ? `Showing ${shown.length} of ${matched.length}` : "";
|
|
18167
19177
|
}
|
|
18168
|
-
function reposition() {
|
|
18169
|
-
if (!popover.matches(":popover-open")) return;
|
|
19178
|
+
function reposition(force) {
|
|
19179
|
+
if (!force && !popover.matches(":popover-open")) return;
|
|
18170
19180
|
const box = trigger.getBoundingClientRect();
|
|
18171
19181
|
const width = Math.max(box.width, 260);
|
|
18172
19182
|
popover.style.left = `${Math.min(box.left, window.innerWidth - width - 8)}px`;
|
|
@@ -18174,7 +19184,9 @@
|
|
|
18174
19184
|
popover.style.width = `${width}px`;
|
|
18175
19185
|
}
|
|
18176
19186
|
state.reposition = reposition;
|
|
18177
|
-
|
|
19187
|
+
popover.addEventListener("beforetoggle", (event) => {
|
|
19188
|
+
if (event.newState === "open") reposition(true);
|
|
19189
|
+
});
|
|
18178
19190
|
popover.addEventListener("toggle", (event) => {
|
|
18179
19191
|
if (event.newState !== "open") return;
|
|
18180
19192
|
search.value = "";
|
|
@@ -18486,6 +19498,24 @@
|
|
|
18486
19498
|
attributes: { "data-style-from": String(marker.from), title: "Possible stock wording \u2014 click to explore" }
|
|
18487
19499
|
}).range(marker.from, marker.to)), true))
|
|
18488
19500
|
});
|
|
19501
|
+
var spellChecker = null;
|
|
19502
|
+
var refreshSpellFx = StateEffect.define();
|
|
19503
|
+
function visibleSpellMarkers(text) {
|
|
19504
|
+
return spellingMarkers(text, spellChecker);
|
|
19505
|
+
}
|
|
19506
|
+
var spellMarkerField = StateField.define({
|
|
19507
|
+
create: (state) => visibleSpellMarkers(state.doc.toString()),
|
|
19508
|
+
update: (markers, tr) => {
|
|
19509
|
+
for (const effect of tr.effects) {
|
|
19510
|
+
if (effect.is(refreshSpellFx)) return visibleSpellMarkers(tr.newDoc.toString());
|
|
19511
|
+
}
|
|
19512
|
+
return tr.docChanged ? visibleSpellMarkers(tr.newDoc.toString()) : markers;
|
|
19513
|
+
},
|
|
19514
|
+
provide: (field) => EditorView.decorations.from(field, (markers) => Decoration.set(markers.map((marker) => Decoration.mark({
|
|
19515
|
+
class: "cm-spell-marker",
|
|
19516
|
+
attributes: { "data-spell-from": String(marker.from), title: "Possible misspelling \u2014 click for suggestions" }
|
|
19517
|
+
}).range(marker.from, marker.to)), true))
|
|
19518
|
+
});
|
|
18489
19519
|
var setReviewFx = StateEffect.define();
|
|
18490
19520
|
var addReviewFx = StateEffect.define();
|
|
18491
19521
|
var dropReviewFx = StateEffect.define();
|
|
@@ -18536,6 +19566,33 @@
|
|
|
18536
19566
|
},
|
|
18537
19567
|
provide: (field) => EditorView.decorations.from(field)
|
|
18538
19568
|
});
|
|
19569
|
+
var setVariantTargetFx = StateEffect.define();
|
|
19570
|
+
var variantTargetField = StateField.define({
|
|
19571
|
+
create: () => Decoration.none,
|
|
19572
|
+
update(decorations2, tr) {
|
|
19573
|
+
for (const effect of tr.effects) {
|
|
19574
|
+
if (effect.is(setVariantTargetFx)) {
|
|
19575
|
+
return effect.value ? Decoration.set([Decoration.mark({ class: "cm-variant-target" }).range(effect.value.from, effect.value.to)]) : Decoration.none;
|
|
19576
|
+
}
|
|
19577
|
+
}
|
|
19578
|
+
if (!tr.docChanged) return decorations2;
|
|
19579
|
+
const edited = [];
|
|
19580
|
+
tr.changes.iterChangedRanges((_fromA, _toA, fromB, toB) => edited.push([fromB, toB]));
|
|
19581
|
+
return decorations2.map(tr.changes).update({
|
|
19582
|
+
filter: (from, to) => !edited.some(([a, b]) => a < to && b > from)
|
|
19583
|
+
});
|
|
19584
|
+
},
|
|
19585
|
+
provide: (field) => EditorView.decorations.from(field)
|
|
19586
|
+
});
|
|
19587
|
+
function markVariantTarget(target) {
|
|
19588
|
+
try {
|
|
19589
|
+
workView.dispatch({ effects: setVariantTargetFx.of(target ? { from: target.from, to: target.to } : null) });
|
|
19590
|
+
} catch {
|
|
19591
|
+
}
|
|
19592
|
+
}
|
|
19593
|
+
function syncVariantTarget() {
|
|
19594
|
+
if (!document.querySelector(".chat-variants:not(.is-spent):not(.is-loading)")) markVariantTarget(null);
|
|
19595
|
+
}
|
|
18539
19596
|
function findingRange(id) {
|
|
18540
19597
|
if (id === -1) return localFinding && chatEditMatches(localFinding, workView.state.doc.toString()) ? { from: localFinding.from, to: localFinding.to } : null;
|
|
18541
19598
|
let found = null;
|
|
@@ -18594,8 +19651,6 @@
|
|
|
18594
19651
|
if (localFinding) keepStyleMarker(localFinding);
|
|
18595
19652
|
return;
|
|
18596
19653
|
}
|
|
18597
|
-
clearTimeout(appliedHideTimers.get(id));
|
|
18598
|
-
appliedHideTimers.delete(id);
|
|
18599
19654
|
const finding = reviewFindings.find((item) => item.id === id);
|
|
18600
19655
|
const document2 = workView.state.doc.toString();
|
|
18601
19656
|
const range = findingRange(id);
|
|
@@ -18608,7 +19663,7 @@
|
|
|
18608
19663
|
if (card) {
|
|
18609
19664
|
railAnchors.delete(card);
|
|
18610
19665
|
railHomes.delete(card);
|
|
18611
|
-
card
|
|
19666
|
+
fadeRemove(card);
|
|
18612
19667
|
}
|
|
18613
19668
|
findingCards.delete(id);
|
|
18614
19669
|
workView.dispatch({ effects: dropReviewFx.of(id) });
|
|
@@ -18617,6 +19672,7 @@
|
|
|
18617
19672
|
else clearPlainPreview();
|
|
18618
19673
|
refocusAfterRemoval(id);
|
|
18619
19674
|
saveFindings();
|
|
19675
|
+
syncVariantTarget();
|
|
18620
19676
|
syncReviewLabel();
|
|
18621
19677
|
workView.focus();
|
|
18622
19678
|
if (decision) showEditFeedback("Kept as is", () => {
|
|
@@ -18649,6 +19705,7 @@
|
|
|
18649
19705
|
reviewFindings = [];
|
|
18650
19706
|
checkedSentences.clear();
|
|
18651
19707
|
workView.dispatch({ effects: setReviewFx.of([]) });
|
|
19708
|
+
markVariantTarget(null);
|
|
18652
19709
|
docStorage.removeItem("wa-findings");
|
|
18653
19710
|
syncReviewLabel();
|
|
18654
19711
|
}
|
|
@@ -18765,16 +19822,16 @@
|
|
|
18765
19822
|
updateBadge.title = command2;
|
|
18766
19823
|
});
|
|
18767
19824
|
async function refreshUpdate({ force = false } = {}) {
|
|
18768
|
-
let
|
|
19825
|
+
let cached2 = null;
|
|
18769
19826
|
try {
|
|
18770
|
-
|
|
19827
|
+
cached2 = JSON.parse(localStorage.getItem("wa-update") || "null");
|
|
18771
19828
|
} catch {
|
|
18772
19829
|
}
|
|
18773
|
-
const check = updateCheckOn && (force || !(
|
|
19830
|
+
const check = updateCheckOn && (force || !(cached2 && Date.now() - cached2.at < UPDATE_INTERVAL));
|
|
18774
19831
|
try {
|
|
18775
19832
|
const info = await api(`/api/version${check ? "?check=1" : ""}`);
|
|
18776
19833
|
if (info.latest) localStorage.setItem("wa-update", JSON.stringify({ latest: info.latest, at: Date.now() }));
|
|
18777
|
-
renderUpdate({ ...info, latest: info.latest ?? (updateCheckOn ?
|
|
19834
|
+
renderUpdate({ ...info, latest: info.latest ?? (updateCheckOn ? cached2?.latest : void 0) });
|
|
18778
19835
|
} catch {
|
|
18779
19836
|
}
|
|
18780
19837
|
}
|
|
@@ -18885,7 +19942,7 @@
|
|
|
18885
19942
|
if (card) {
|
|
18886
19943
|
railAnchors.delete(card);
|
|
18887
19944
|
railHomes.delete(card);
|
|
18888
|
-
card
|
|
19945
|
+
fadeRemove(card);
|
|
18889
19946
|
findingCards.delete(-1);
|
|
18890
19947
|
}
|
|
18891
19948
|
localFinding = null;
|
|
@@ -18987,7 +20044,7 @@
|
|
|
18987
20044
|
suggestTimer = null;
|
|
18988
20045
|
const view = workView;
|
|
18989
20046
|
const state = view.state;
|
|
18990
|
-
if (state.readOnly || loadingDocument || savePaused || !view.hasFocus || document.hidden || view.composing) return;
|
|
20047
|
+
if (state.readOnly || loadingDocument || savePaused || !manual && !view.hasFocus || document.hidden || view.composing) return;
|
|
18991
20048
|
if (!manual && !autoSuggestOn) return;
|
|
18992
20049
|
if (!atParagraphEnd(state)) {
|
|
18993
20050
|
if (manual) setReviewStatus("Place the caret at the end of a paragraph to request a continuation.", void 0, "suggest");
|
|
@@ -19003,11 +20060,11 @@
|
|
|
19003
20060
|
if (/^\s*\/idea(?:\s|$)/i.test(line.text)) return;
|
|
19004
20061
|
const version = suggestVersion;
|
|
19005
20062
|
if (manual && !await ensureAgent()) return;
|
|
19006
|
-
if (version !== suggestVersion || !view.hasFocus || !currentAgent()) return;
|
|
20063
|
+
if (version !== suggestVersion || !manual && !view.hasFocus || !currentAgent()) return;
|
|
19007
20064
|
const agent = currentAgent();
|
|
19008
20065
|
const job = startJob({ background: !manual });
|
|
19009
20066
|
suggestAbort = job;
|
|
19010
|
-
const isCurrent = () => suggestAbort === job && !job.signal.aborted && version === suggestVersion && !loadingDocument && !savePaused && !document.hidden && view.hasFocus && !view.composing && !view.state.readOnly && (manual || autoSuggestOn) && view.state.doc === state.doc && view.state.selection.eq(state.selection) && JSON.stringify(currentAgent()) === JSON.stringify(agent);
|
|
20067
|
+
const isCurrent = () => suggestAbort === job && !job.signal.aborted && version === suggestVersion && !loadingDocument && !savePaused && !document.hidden && (manual || view.hasFocus) && !view.composing && !view.state.readOnly && (manual || autoSuggestOn) && view.state.doc === state.doc && view.state.selection.eq(state.selection) && JSON.stringify(currentAgent()) === JSON.stringify(agent);
|
|
19011
20068
|
if (manual) setReviewStatus("Suggesting\u2026", void 0, "suggest");
|
|
19012
20069
|
try {
|
|
19013
20070
|
const res = await fetch("/suggest", {
|
|
@@ -19016,7 +20073,8 @@
|
|
|
19016
20073
|
body: JSON.stringify({
|
|
19017
20074
|
document: doc2,
|
|
19018
20075
|
cursor: pos,
|
|
19019
|
-
agent
|
|
20076
|
+
agent,
|
|
20077
|
+
manual
|
|
19020
20078
|
}),
|
|
19021
20079
|
signal: job.signal
|
|
19022
20080
|
});
|
|
@@ -19098,9 +20156,38 @@
|
|
|
19098
20156
|
return node;
|
|
19099
20157
|
}
|
|
19100
20158
|
var chatAtBottom = () => chatStream.scrollHeight - chatStream.scrollTop - chatStream.clientHeight < 48;
|
|
19101
|
-
|
|
19102
|
-
|
|
20159
|
+
var reduceMotion = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
20160
|
+
function chatScroll(stick, smooth = false) {
|
|
19103
20161
|
void stick;
|
|
20162
|
+
const top2 = chatStream.scrollHeight;
|
|
20163
|
+
if (smooth && !reduceMotion()) {
|
|
20164
|
+
try {
|
|
20165
|
+
chatStream.scrollTo({ top: top2, behavior: "smooth" });
|
|
20166
|
+
return;
|
|
20167
|
+
} catch {
|
|
20168
|
+
}
|
|
20169
|
+
}
|
|
20170
|
+
chatStream.scrollTop = top2;
|
|
20171
|
+
}
|
|
20172
|
+
function scrollToNode(node, block2 = "nearest") {
|
|
20173
|
+
if (!node?.isConnected) return;
|
|
20174
|
+
try {
|
|
20175
|
+
node.scrollIntoView({ block: block2, behavior: reduceMotion() ? "auto" : "smooth" });
|
|
20176
|
+
} catch {
|
|
20177
|
+
try {
|
|
20178
|
+
node.scrollIntoView();
|
|
20179
|
+
} catch {
|
|
20180
|
+
}
|
|
20181
|
+
}
|
|
20182
|
+
}
|
|
20183
|
+
function fadeRemove(node, ms = 160) {
|
|
20184
|
+
if (!node?.isConnected) return;
|
|
20185
|
+
if (reduceMotion()) {
|
|
20186
|
+
node.remove();
|
|
20187
|
+
return;
|
|
20188
|
+
}
|
|
20189
|
+
node.classList.add("is-leaving");
|
|
20190
|
+
setTimeout(() => node.remove(), ms);
|
|
19104
20191
|
}
|
|
19105
20192
|
function saveChat() {
|
|
19106
20193
|
docStorage.setItem("wa-chat", JSON.stringify({ document: workView.state.doc.toString(), messages: chatHistory.slice(-20) }));
|
|
@@ -19176,7 +20263,12 @@ ${message.content}`;
|
|
|
19176
20263
|
syncChatEditCards();
|
|
19177
20264
|
undo2.focus();
|
|
19178
20265
|
});
|
|
19179
|
-
const
|
|
20266
|
+
const undoFoot = chatEl("div", "variant-undo-row");
|
|
20267
|
+
undoFoot.hidden = true;
|
|
20268
|
+
const undo2 = chatEl("button", "chat-again", "Undo");
|
|
20269
|
+
undo2.type = "button";
|
|
20270
|
+
undo2.title = "Put the passage back as it was";
|
|
20271
|
+
undo2.addEventListener("click", () => {
|
|
19180
20272
|
if (edit.state === "kept") {
|
|
19181
20273
|
edit.state = "pending";
|
|
19182
20274
|
saveChat();
|
|
@@ -19184,6 +20276,7 @@ ${message.content}`;
|
|
|
19184
20276
|
apply.focus();
|
|
19185
20277
|
} else changeChatEdit(edit, true);
|
|
19186
20278
|
});
|
|
20279
|
+
undoFoot.append(undo2);
|
|
19187
20280
|
const refresh = button("Request new edit", () => {
|
|
19188
20281
|
if (edit.state === "unlocated") {
|
|
19189
20282
|
chatInput.value = `Prepare an edit for the passage I select. Previous suggestion: ${edit.label}`;
|
|
@@ -19196,24 +20289,28 @@ ${message.content}`;
|
|
|
19196
20289
|
const status = chatEl("p", "chat-edit-status");
|
|
19197
20290
|
status.setAttribute("role", "status");
|
|
19198
20291
|
actions.prepend(status);
|
|
19199
|
-
card.append(actions);
|
|
19200
|
-
chatEditCards.set(edit, { card, preview, apply, keep, undo: undo2, refresh, status });
|
|
20292
|
+
card.append(actions, undoFoot);
|
|
20293
|
+
chatEditCards.set(edit, { card, actions, preview, apply, keep, undo: undo2, undoFoot, refresh, status });
|
|
19201
20294
|
syncChatEditCard(edit, chatEditCards.get(edit));
|
|
19202
20295
|
return card;
|
|
19203
20296
|
}
|
|
19204
20297
|
function syncChatEditCard(edit, ui) {
|
|
19205
20298
|
const valid = chatEditMatches(edit, workView.state.doc.toString());
|
|
19206
20299
|
const pending = edit.state === "pending" && valid;
|
|
20300
|
+
const showUndo = valid && ["applied", "kept"].includes(edit.state);
|
|
20301
|
+
const appliedNow = valid && edit.state === "applied";
|
|
19207
20302
|
ui.preview.hidden = ui.apply.hidden = ui.keep.hidden = !pending;
|
|
19208
|
-
ui.undo.hidden = !
|
|
20303
|
+
ui.undo.hidden = !showUndo;
|
|
20304
|
+
ui.undoFoot.hidden = !showUndo;
|
|
20305
|
+
ui.card.classList.toggle("is-applied", appliedNow);
|
|
20306
|
+
ui.actions.hidden = appliedNow;
|
|
19209
20307
|
ui.refresh.hidden = valid;
|
|
19210
20308
|
ui.refresh.textContent = edit.state === "unlocated" ? "Choose passage" : "Request new edit";
|
|
19211
20309
|
ui.preview.textContent = plainPreview?.edit === edit ? "End preview" : "Preview";
|
|
19212
20310
|
ui.preview.setAttribute("aria-pressed", String(plainPreview?.edit === edit));
|
|
19213
20311
|
ui.apply.disabled = ui.undo.disabled = workView.state.readOnly || loadingDocument || savePaused;
|
|
19214
|
-
ui.status.textContent = !valid ? edit.state === "unlocated" ? "Select the intended passage and request this edit again." : "" : edit.state === "
|
|
20312
|
+
ui.status.textContent = !valid ? edit.state === "unlocated" ? "Select the intended passage and request this edit again." : "" : edit.state === "kept" ? "Original kept" : "";
|
|
19215
20313
|
ui.status.hidden = !ui.status.textContent;
|
|
19216
|
-
ui.status.classList.toggle("is-ok", valid && edit.state === "applied");
|
|
19217
20314
|
}
|
|
19218
20315
|
function syncChatEditCards() {
|
|
19219
20316
|
for (const [edit, ui] of chatEditCards) {
|
|
@@ -19249,35 +20346,11 @@ ${message.content}`;
|
|
|
19249
20346
|
var rail = document.getElementById("rail");
|
|
19250
20347
|
var railAnchors = /* @__PURE__ */ new Map();
|
|
19251
20348
|
var railHomes = /* @__PURE__ */ new Map();
|
|
19252
|
-
var RAIL_WIDTH = 300;
|
|
19253
|
-
var RAIL_GUTTER = 24;
|
|
19254
20349
|
var railOn = false;
|
|
19255
20350
|
function syncRail() {
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
const box = workView.contentDOM.getBoundingClientRect();
|
|
19260
|
-
const pane = document.getElementById("pane-work").getBoundingClientRect();
|
|
19261
|
-
rail.style.left = `${box.right - margin - pane.left + RAIL_GUTTER}px`;
|
|
19262
|
-
}
|
|
19263
|
-
if (fits === railOn) return;
|
|
19264
|
-
railOn = fits;
|
|
19265
|
-
rail.hidden = !fits;
|
|
19266
|
-
const focused = focusedFindingId;
|
|
19267
|
-
for (const node of railAnchors.keys()) {
|
|
19268
|
-
if (!node.isConnected) continue;
|
|
19269
|
-
node.style.top = "";
|
|
19270
|
-
node.style.visibility = "";
|
|
19271
|
-
if (fits) {
|
|
19272
|
-
node.style.display = "";
|
|
19273
|
-
rail.append(node);
|
|
19274
|
-
} else {
|
|
19275
|
-
placeHome(node);
|
|
19276
|
-
const nodeId = Number(node.dataset?.findingId);
|
|
19277
|
-
node.style.display = focused === null || nodeId === focused ? "" : "none";
|
|
19278
|
-
}
|
|
19279
|
-
}
|
|
19280
|
-
if (!fits) chatScroll(true);
|
|
20351
|
+
railOn = false;
|
|
20352
|
+
if (!rail.hidden) rail.hidden = true;
|
|
20353
|
+
return;
|
|
19281
20354
|
}
|
|
19282
20355
|
function placeHome(node) {
|
|
19283
20356
|
const home = railHomes.get(node) ?? chatStream;
|
|
@@ -19287,9 +20360,7 @@ ${message.content}`;
|
|
|
19287
20360
|
function railAdd(node, anchor, home = chatStream) {
|
|
19288
20361
|
railAnchors.set(node, anchor);
|
|
19289
20362
|
railHomes.set(node, home);
|
|
19290
|
-
|
|
19291
|
-
if (railOn) rail.append(node);
|
|
19292
|
-
else placeHome(node);
|
|
20363
|
+
placeHome(node);
|
|
19293
20364
|
layoutRail();
|
|
19294
20365
|
return node;
|
|
19295
20366
|
}
|
|
@@ -19320,19 +20391,11 @@ ${message.content}`;
|
|
|
19320
20391
|
chatClear.title = open ? "Close \u2014 nothing is discarded" : "Show the conversation";
|
|
19321
20392
|
if (open) {
|
|
19322
20393
|
chatClear.hidden = false;
|
|
19323
|
-
chatScroll(true);
|
|
20394
|
+
chatScroll(true, true);
|
|
19324
20395
|
return;
|
|
19325
20396
|
}
|
|
19326
20397
|
chatStream.hidden = true;
|
|
19327
|
-
|
|
19328
|
-
for (const card of findingCards.values()) {
|
|
19329
|
-
const kept = card.querySelector(".chat-variants:has(.variant-card.is-applied)");
|
|
19330
|
-
if (kept) streamAppend(kept);
|
|
19331
|
-
}
|
|
19332
|
-
discardFindingCards();
|
|
19333
|
-
for (const stale of document.querySelectorAll(".chat-variants")) {
|
|
19334
|
-
if (!stale.querySelector(".variant-card.is-applied")) stale.remove();
|
|
19335
|
-
}
|
|
20398
|
+
clearPlainPreview();
|
|
19336
20399
|
chatClear.hidden = chatStream.children.length === 0;
|
|
19337
20400
|
layoutRail();
|
|
19338
20401
|
}
|
|
@@ -19458,6 +20521,35 @@ ${message.content}`;
|
|
|
19458
20521
|
markBubble.replaceChildren(actions);
|
|
19459
20522
|
placeBubble(x, y);
|
|
19460
20523
|
}
|
|
20524
|
+
function showContinueBubble(x, y) {
|
|
20525
|
+
bubbleMode = "continue";
|
|
20526
|
+
const actions = chatEl("div", "mark-bubble-actions");
|
|
20527
|
+
actions.append(bubbleButton("Continue", () => {
|
|
20528
|
+
workView.focus();
|
|
20529
|
+
cancelSuggestion();
|
|
20530
|
+
ghostClear(workView);
|
|
20531
|
+
void suggestFetch(true);
|
|
20532
|
+
}));
|
|
20533
|
+
markBubble.replaceChildren(actions);
|
|
20534
|
+
placeBubble(x, y);
|
|
20535
|
+
}
|
|
20536
|
+
function showSpellBubble(marker, x, y) {
|
|
20537
|
+
bubbleMode = "spell";
|
|
20538
|
+
const actions = chatEl("div", "mark-bubble-actions");
|
|
20539
|
+
const replace2 = (suggestion) => {
|
|
20540
|
+
if (workView.state.sliceDoc(marker.from, marker.to) !== marker.quote) return;
|
|
20541
|
+
workView.dispatch({ changes: { from: marker.from, to: marker.to, insert: suggestion }, userEvent: "input.spellfix" });
|
|
20542
|
+
};
|
|
20543
|
+
for (const suggestion of (spellChecker?.suggest(marker.quote) ?? []).slice(0, 5)) {
|
|
20544
|
+
actions.append(bubbleButton(suggestion, () => replace2(suggestion)));
|
|
20545
|
+
}
|
|
20546
|
+
actions.append(bubbleButton("Ignore", () => {
|
|
20547
|
+
spellChecker?.add(marker.quote);
|
|
20548
|
+
workView.dispatch({ effects: refreshSpellFx.of(null) });
|
|
20549
|
+
}));
|
|
20550
|
+
markBubble.replaceChildren(actions);
|
|
20551
|
+
placeBubble(x, y);
|
|
20552
|
+
}
|
|
19461
20553
|
var PlainVariantWidget = class extends WidgetType {
|
|
19462
20554
|
constructor(text, block2) {
|
|
19463
20555
|
super();
|
|
@@ -19533,6 +20625,7 @@ ${message.content}`;
|
|
|
19533
20625
|
}
|
|
19534
20626
|
function applyText(text, target, wrap = null, card = null) {
|
|
19535
20627
|
if (!replacementTarget(workView.state.doc.toString(), target) || workView.state.readOnly) {
|
|
20628
|
+
markVariantTarget(null);
|
|
19536
20629
|
chatAdd(chatEl("div", "chat-error", "The draft changed since this answer. Select the passage and request new options."));
|
|
19537
20630
|
return;
|
|
19538
20631
|
}
|
|
@@ -19544,6 +20637,7 @@ ${message.content}`;
|
|
|
19544
20637
|
selection: { anchor: range.from + text.length },
|
|
19545
20638
|
effects: [
|
|
19546
20639
|
setPlainVariantFx.of(null),
|
|
20640
|
+
setVariantTargetFx.of(null),
|
|
19547
20641
|
setFlashFx.of({ from: range.from, to: range.from + text.length })
|
|
19548
20642
|
]
|
|
19549
20643
|
});
|
|
@@ -19564,77 +20658,41 @@ ${message.content}`;
|
|
|
19564
20658
|
if (card) card.classList.add("is-applied");
|
|
19565
20659
|
if (wrap) {
|
|
19566
20660
|
wrap.classList.add("is-spent");
|
|
19567
|
-
for (const sibling of wrap.querySelectorAll(".variant-card")) {
|
|
19568
|
-
if (sibling !== card) sibling.hidden = true;
|
|
19569
|
-
}
|
|
19570
|
-
const foot = wrap.querySelector(".variant-foot");
|
|
19571
|
-
if (foot) foot.hidden = true;
|
|
19572
|
-
const soloHint = wrap.querySelector(":scope > .variant-hint");
|
|
19573
|
-
if (soloHint) soloHint.hidden = true;
|
|
19574
20661
|
attachUndo(card, text, target);
|
|
19575
20662
|
const hostCard = wrap.closest(".chat-card");
|
|
19576
20663
|
if (hostCard && findingCards.has(Number(hostCard.dataset.findingId))) {
|
|
19577
|
-
|
|
20664
|
+
const findingId = Number(hostCard.dataset.findingId);
|
|
20665
|
+
for (const sibling of wrap.querySelectorAll(".variant-card")) {
|
|
20666
|
+
if (sibling !== card) sibling.hidden = true;
|
|
20667
|
+
}
|
|
20668
|
+
const foot = wrap.querySelector(".variant-foot");
|
|
20669
|
+
if (foot) foot.hidden = true;
|
|
20670
|
+
const soloHint = wrap.querySelector(":scope > .variant-hint");
|
|
20671
|
+
if (soloHint) soloHint.hidden = true;
|
|
20672
|
+
hostCard.querySelector(".finding-actions")?.remove();
|
|
20673
|
+
railAnchors.delete(hostCard);
|
|
20674
|
+
railHomes.delete(hostCard);
|
|
20675
|
+
if (findingId === -1) localFinding = null;
|
|
20676
|
+
else {
|
|
20677
|
+
reviewFindings = reviewFindings.filter((finding) => finding.id !== findingId);
|
|
20678
|
+
try {
|
|
20679
|
+
workView.dispatch({ effects: dropReviewFx.of(findingId) });
|
|
20680
|
+
} catch {
|
|
20681
|
+
}
|
|
20682
|
+
if (focusedFindingId === findingId) {
|
|
20683
|
+
focusedFindingId = null;
|
|
20684
|
+
syncActiveCard();
|
|
20685
|
+
}
|
|
20686
|
+
}
|
|
20687
|
+
saveFindings();
|
|
20688
|
+
syncReviewLabel();
|
|
20689
|
+
syncStyleScore();
|
|
19578
20690
|
layoutRail();
|
|
19579
|
-
scheduleAppliedHide(hostCard, Number(hostCard.dataset.findingId));
|
|
19580
20691
|
} else {
|
|
19581
20692
|
setChatOpen(true);
|
|
19582
20693
|
}
|
|
19583
20694
|
}
|
|
19584
20695
|
}
|
|
19585
|
-
var APPLIED_HIDE_MS = 6e3;
|
|
19586
|
-
var appliedHideTimers = /* @__PURE__ */ new Map();
|
|
19587
|
-
function scheduleAppliedHide(hostCard, id) {
|
|
19588
|
-
clearTimeout(appliedHideTimers.get(id));
|
|
19589
|
-
appliedHideTimers.set(id, setTimeout(() => {
|
|
19590
|
-
const card = findingCards.get(id);
|
|
19591
|
-
if (!card || !card.isConnected) {
|
|
19592
|
-
appliedHideTimers.delete(id);
|
|
19593
|
-
return;
|
|
19594
|
-
}
|
|
19595
|
-
if (card.matches(":hover") || card.contains(document.activeElement)) {
|
|
19596
|
-
scheduleAppliedHide(card, id);
|
|
19597
|
-
return;
|
|
19598
|
-
}
|
|
19599
|
-
appliedHideTimers.delete(id);
|
|
19600
|
-
resolveFinding(id);
|
|
19601
|
-
}, APPLIED_HIDE_MS));
|
|
19602
|
-
}
|
|
19603
|
-
function resolveFinding(id) {
|
|
19604
|
-
clearTimeout(appliedHideTimers.get(id));
|
|
19605
|
-
appliedHideTimers.delete(id);
|
|
19606
|
-
if (id === -1) {
|
|
19607
|
-
removeLocalFinding();
|
|
19608
|
-
saveFindings();
|
|
19609
|
-
syncReviewLabel();
|
|
19610
|
-
syncStyleScore();
|
|
19611
|
-
updateFindingNav();
|
|
19612
|
-
layoutRail();
|
|
19613
|
-
return;
|
|
19614
|
-
}
|
|
19615
|
-
reviewFindings = reviewFindings.filter((finding) => finding.id !== id);
|
|
19616
|
-
const card = findingCards.get(id);
|
|
19617
|
-
if (card) {
|
|
19618
|
-
railAnchors.delete(card);
|
|
19619
|
-
railHomes.delete(card);
|
|
19620
|
-
card.remove();
|
|
19621
|
-
}
|
|
19622
|
-
findingCards.delete(id);
|
|
19623
|
-
try {
|
|
19624
|
-
workView.dispatch({ effects: dropReviewFx.of(id) });
|
|
19625
|
-
} catch {
|
|
19626
|
-
}
|
|
19627
|
-
if (focusedFindingId === id) {
|
|
19628
|
-
focusedFindingId = null;
|
|
19629
|
-
syncActiveCard();
|
|
19630
|
-
}
|
|
19631
|
-
saveFindings();
|
|
19632
|
-
syncReviewLabel();
|
|
19633
|
-
syncStyleScore();
|
|
19634
|
-
updateFindingNav();
|
|
19635
|
-
layoutRail();
|
|
19636
|
-
if (chatStream.children.length === 0) setChatOpen(false);
|
|
19637
|
-
}
|
|
19638
20696
|
function attachUndo(card, text, target) {
|
|
19639
20697
|
if (!card) return;
|
|
19640
20698
|
let row = card.querySelector(".variant-undo-row");
|
|
@@ -19644,11 +20702,6 @@ ${message.content}`;
|
|
|
19644
20702
|
undo3.type = "button";
|
|
19645
20703
|
undo3.title = "Put the passage back as it was";
|
|
19646
20704
|
undo3.addEventListener("click", () => {
|
|
19647
|
-
const host = undo3.closest(".chat-card");
|
|
19648
|
-
if (host?.dataset.findingId !== void 0 && host.dataset.findingId !== "") {
|
|
19649
|
-
clearTimeout(appliedHideTimers.get(Number(host.dataset.findingId)));
|
|
19650
|
-
appliedHideTimers.delete(Number(host.dataset.findingId));
|
|
19651
|
-
}
|
|
19652
20705
|
const at = Number(undo3.dataset.from);
|
|
19653
20706
|
const { applied, previous } = undo3.dataset;
|
|
19654
20707
|
if (!undo3.isConnected || undo3.dataset.stale || workView.state.sliceDoc(at, at + applied.length) !== applied) {
|
|
@@ -19660,13 +20713,14 @@ ${message.content}`;
|
|
|
19660
20713
|
save();
|
|
19661
20714
|
const spentWrap = undo3.closest(".chat-variants");
|
|
19662
20715
|
const hostCard = undo3.closest(".chat-card");
|
|
19663
|
-
spentWrap
|
|
19664
|
-
|
|
20716
|
+
fadeRemove(spentWrap);
|
|
20717
|
+
syncVariantTarget();
|
|
20718
|
+
if (hostCard && hostCard.dataset.findingId && !hostCard.querySelector(".chat-variants:not(.is-leaving)")) {
|
|
19665
20719
|
const hostId = Number(hostCard.dataset.findingId);
|
|
19666
20720
|
railAnchors.delete(hostCard);
|
|
19667
20721
|
railHomes.delete(hostCard);
|
|
19668
20722
|
findingCards.delete(hostId);
|
|
19669
|
-
hostCard
|
|
20723
|
+
fadeRemove(hostCard);
|
|
19670
20724
|
refocusAfterRemoval(hostId);
|
|
19671
20725
|
}
|
|
19672
20726
|
layoutRail();
|
|
@@ -19698,13 +20752,8 @@ ${message.content}`;
|
|
|
19698
20752
|
return findingRange(id)?.from ?? null;
|
|
19699
20753
|
});
|
|
19700
20754
|
}
|
|
19701
|
-
|
|
19702
|
-
card.style.display = focused === null || isFocused ? "" : "none";
|
|
19703
|
-
} else {
|
|
19704
|
-
card.style.display = "";
|
|
19705
|
-
}
|
|
20755
|
+
card.style.display = "";
|
|
19706
20756
|
}
|
|
19707
|
-
updateFindingNav();
|
|
19708
20757
|
layoutRail();
|
|
19709
20758
|
}
|
|
19710
20759
|
function refocusAfterRemoval(removedId) {
|
|
@@ -19719,19 +20768,6 @@ ${message.content}`;
|
|
|
19719
20768
|
card.dataset.findingId = String(finding.id);
|
|
19720
20769
|
card.addEventListener("mouseenter", () => markFor(finding.id)?.classList.add("is-hot"));
|
|
19721
20770
|
card.addEventListener("mouseleave", () => markFor(finding.id)?.classList.remove("is-hot"));
|
|
19722
|
-
const nav2 = chatEl("div", "finding-nav");
|
|
19723
|
-
const prev = chatEl("button", "finding-nav-btn", "\u2039");
|
|
19724
|
-
prev.type = "button";
|
|
19725
|
-
prev.title = "Previous finding (Shift+F8)";
|
|
19726
|
-
prev.setAttribute("aria-label", "Previous finding");
|
|
19727
|
-
prev.addEventListener("click", () => jumpToNextFinding(-1));
|
|
19728
|
-
const count = chatEl("span", "finding-nav-count", "");
|
|
19729
|
-
const next = chatEl("button", "finding-nav-btn", "\u203A");
|
|
19730
|
-
next.type = "button";
|
|
19731
|
-
next.title = "Next finding (F8)";
|
|
19732
|
-
next.setAttribute("aria-label", "Next finding");
|
|
19733
|
-
next.addEventListener("click", () => jumpToNextFinding(1));
|
|
19734
|
-
nav2.append(prev, count, next);
|
|
19735
20771
|
const dismiss = chatEl("button", "chat-card-dismiss", "Keep as is");
|
|
19736
20772
|
dismiss.type = "button";
|
|
19737
20773
|
dismiss.title = "Keep this wording and dismiss the finding";
|
|
@@ -19741,12 +20777,10 @@ ${message.content}`;
|
|
|
19741
20777
|
dismissFinding(finding.id);
|
|
19742
20778
|
});
|
|
19743
20779
|
card.append(
|
|
19744
|
-
nav2,
|
|
19745
20780
|
chatEl("strong", "", finding.pattern),
|
|
19746
20781
|
chatEl("span", "", finding.reason),
|
|
19747
20782
|
chatEl("small", "", finding.fix)
|
|
19748
20783
|
);
|
|
19749
|
-
if (finding.id === -1) nav2.hidden = true;
|
|
19750
20784
|
const offer = chatEl("button", "chat-offer", "Options");
|
|
19751
20785
|
offer.type = "button";
|
|
19752
20786
|
offer.addEventListener("click", () => {
|
|
@@ -19775,18 +20809,8 @@ ${message.content}`;
|
|
|
19775
20809
|
if (finding.id === -1) dismiss.textContent = "Keep here";
|
|
19776
20810
|
const variantsBox = chatEl("div", "finding-variants");
|
|
19777
20811
|
card.append(actions, variantsBox);
|
|
19778
|
-
updateFindingNav();
|
|
19779
20812
|
return card;
|
|
19780
20813
|
}
|
|
19781
|
-
function updateFindingNav() {
|
|
19782
|
-
const live = reviewFindings.map((finding) => ({ finding, range: findingRange(finding.id) })).filter((item) => item.range).sort((a, b) => a.range.from - b.range.from || a.finding.id - b.finding.id);
|
|
19783
|
-
for (const [id, card] of findingCards) {
|
|
19784
|
-
const count = card.querySelector(".finding-nav-count");
|
|
19785
|
-
if (!count) continue;
|
|
19786
|
-
const index = live.findIndex((item) => item.finding.id === id);
|
|
19787
|
-
count.textContent = live.length ? `${index >= 0 ? index + 1 : "\u2013"} of ${live.length}` : "";
|
|
19788
|
-
}
|
|
19789
|
-
}
|
|
19790
20814
|
function variantCards(variants, instruction, target, card = null) {
|
|
19791
20815
|
const doc2 = workView.state.doc.toString();
|
|
19792
20816
|
const ordered = isLatinScript(doc2) ? variants.map((text) => ({ text, score: styleScore(doc2.slice(0, target.from) + text + doc2.slice(target.to)).score })).sort((a, b) => a.score - b.score).map((item) => item.text) : variants.slice();
|
|
@@ -19799,9 +20823,8 @@ ${message.content}`;
|
|
|
19799
20823
|
item.tabIndex = 0;
|
|
19800
20824
|
item.setAttribute("role", "button");
|
|
19801
20825
|
item.setAttribute("aria-label", `Apply option ${index + 1}`);
|
|
19802
|
-
const label = chatEl("div", "variant-label", `Option ${index + 1}`);
|
|
19803
20826
|
const body = chatEl("div", "variant-text", text);
|
|
19804
|
-
item.append(
|
|
20827
|
+
item.append(body);
|
|
19805
20828
|
const previewIt = () => {
|
|
19806
20829
|
if (wrap.classList.contains("is-spent")) return;
|
|
19807
20830
|
if (!replacementTarget(workView.state.doc.toString(), target)) return;
|
|
@@ -19892,8 +20915,8 @@ ${message.content}`;
|
|
|
19892
20915
|
layoutRail();
|
|
19893
20916
|
}
|
|
19894
20917
|
function retireStaleVariants(except) {
|
|
19895
|
-
for (const stale of document.querySelectorAll(".chat-variants:not(.is-spent):not(.is-loading)")) {
|
|
19896
|
-
if (stale !== except) stale
|
|
20918
|
+
for (const stale of document.querySelectorAll(".chat-variants:not(.is-spent):not(.is-loading):not(.is-leaving)")) {
|
|
20919
|
+
if (stale !== except) fadeRemove(stale);
|
|
19897
20920
|
}
|
|
19898
20921
|
layoutRail();
|
|
19899
20922
|
}
|
|
@@ -19901,6 +20924,7 @@ ${message.content}`;
|
|
|
19901
20924
|
const wrap = variantCards(variants, instruction, target);
|
|
19902
20925
|
retireStaleVariants(wrap);
|
|
19903
20926
|
chatAdd(wrap);
|
|
20927
|
+
markVariantTarget(target);
|
|
19904
20928
|
try {
|
|
19905
20929
|
workView.dispatch({ effects: EditorView.scrollIntoView(target.from, { y: "center" }) });
|
|
19906
20930
|
} catch {
|
|
@@ -19916,6 +20940,7 @@ ${message.content}`;
|
|
|
19916
20940
|
if (!await ensureAgent()) return;
|
|
19917
20941
|
if (!replacementTarget(workView.state.doc.toString(), target)) return;
|
|
19918
20942
|
clearPlainPreview();
|
|
20943
|
+
markVariantTarget(null);
|
|
19919
20944
|
const inCard = !!(card && card.isConnected && card.querySelector(".finding-variants"));
|
|
19920
20945
|
const box = inCard ? card.querySelector(".finding-variants") : null;
|
|
19921
20946
|
if (inCard) {
|
|
@@ -19955,6 +20980,8 @@ ${message.content}`;
|
|
|
19955
20980
|
done.textContent = "Options";
|
|
19956
20981
|
}
|
|
19957
20982
|
layoutRail();
|
|
20983
|
+
markVariantTarget(target);
|
|
20984
|
+
scrollToNode(wrap);
|
|
19958
20985
|
try {
|
|
19959
20986
|
workView.dispatch({ effects: EditorView.scrollIntoView(target.from, { y: "center" }) });
|
|
19960
20987
|
} catch {
|
|
@@ -19967,21 +20994,25 @@ ${message.content}`;
|
|
|
19967
20994
|
placeholder2.remove();
|
|
19968
20995
|
chatAdd(wrap);
|
|
19969
20996
|
}
|
|
20997
|
+
markVariantTarget(target);
|
|
19970
20998
|
}
|
|
19971
20999
|
} catch (error) {
|
|
19972
21000
|
if (error.name === "AbortError") {
|
|
19973
21001
|
placeholder2.remove();
|
|
19974
21002
|
if (card) restoreFindingCard(card);
|
|
19975
21003
|
else layoutRail();
|
|
21004
|
+
syncVariantTarget();
|
|
19976
21005
|
return;
|
|
19977
21006
|
}
|
|
19978
21007
|
console.error("[/rewrite]", error);
|
|
19979
21008
|
placeholder2.remove();
|
|
21009
|
+
syncVariantTarget();
|
|
19980
21010
|
if (!inCard) restoreFindingCard(card);
|
|
19981
21011
|
const err = errorCard(modelError(error), () => requestVariants(instruction, target, card));
|
|
19982
21012
|
if (inCard) {
|
|
19983
21013
|
box.append(err);
|
|
19984
21014
|
restoreFindingCard(card);
|
|
21015
|
+
scrollToNode(err);
|
|
19985
21016
|
} else chatAdd(err);
|
|
19986
21017
|
} finally {
|
|
19987
21018
|
finishJob(job);
|
|
@@ -20136,10 +21167,6 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20136
21167
|
chatInput.closest(".chat-composer")?.classList.toggle("is-busy", busy);
|
|
20137
21168
|
chatInput.placeholder = busy ? "Working\u2026" : basePlaceholder();
|
|
20138
21169
|
}
|
|
20139
|
-
document.getElementById("chat-rewrite").addEventListener("click", () => {
|
|
20140
|
-
const range = attachedRange();
|
|
20141
|
-
if (range) requestVariants(chatInput.value.trim() || "Make this passage clearer. Preserve meaning, facts and voice.");
|
|
20142
|
-
});
|
|
20143
21170
|
chatSendButton.addEventListener("click", () => {
|
|
20144
21171
|
if ([...jobs].some((job) => !job.background)) {
|
|
20145
21172
|
stopJobs();
|
|
@@ -20255,27 +21282,24 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20255
21282
|
},
|
|
20256
21283
|
// The attached passage. Survives losing focus, unlike a native selection —
|
|
20257
21284
|
// that is the only job this mark has for a plain selection, which carries
|
|
20258
|
-
// no marking of its own.
|
|
21285
|
+
// no marking of its own. A background wash: underlines belong to errors
|
|
21286
|
+
// (dictionary, typos) and are never used for working states.
|
|
20259
21287
|
".cm-attached": {
|
|
20260
21288
|
background: "var(--attached-tint)",
|
|
20261
21289
|
borderRadius: "3px",
|
|
20262
21290
|
boxShadow: "0 0 0 2px var(--attached-tint)"
|
|
20263
21291
|
},
|
|
20264
|
-
//
|
|
20265
|
-
//
|
|
20266
|
-
//
|
|
20267
|
-
//
|
|
20268
|
-
// what lets an edit end the attachment.
|
|
21292
|
+
// Over a finding two washes would merge into one unreadable stain, so the
|
|
21293
|
+
// attachment keeps a thin accent edge here on top of its wash — the single
|
|
21294
|
+
// outlined exception, and only over findings. Tracking the live position
|
|
21295
|
+
// is unchanged: that is what lets an edit end the attachment.
|
|
20269
21296
|
".cm-attached.cm-attached-finding": {
|
|
20270
|
-
background: "
|
|
20271
|
-
borderRadius: "
|
|
20272
|
-
boxShadow: "
|
|
21297
|
+
background: "var(--attached-tint)",
|
|
21298
|
+
borderRadius: "3px",
|
|
21299
|
+
boxShadow: "0 0 0 2px var(--attached-tint), 0 0 0 3.5px var(--accent)"
|
|
20273
21300
|
},
|
|
20274
|
-
//
|
|
20275
|
-
//
|
|
20276
|
-
// lines of prose reads as an error the writer must clear rather than a
|
|
20277
|
-
// remark they may weigh. Blue stays reserved for what the writer does:
|
|
20278
|
-
// selection, attachment, suggestion.
|
|
21301
|
+
// Model findings read as a background band. The wavy underline is reserved
|
|
21302
|
+
// for errors (local dictionary, typos) — findings never underline.
|
|
20279
21303
|
".cm-slop": {
|
|
20280
21304
|
background: "var(--remark-tint)",
|
|
20281
21305
|
borderRadius: "2px",
|
|
@@ -20284,14 +21308,23 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20284
21308
|
transition: "background .12s ease"
|
|
20285
21309
|
},
|
|
20286
21310
|
".cm-slop:hover": { background: "var(--remark-tint-hover)" },
|
|
20287
|
-
//
|
|
20288
|
-
//
|
|
20289
|
-
//
|
|
21311
|
+
// The passage whose variants are currently open: a dashed accent outline
|
|
21312
|
+
// with a faint wash — the only dashed mark in the draft, reading as
|
|
21313
|
+
// "deciding here". Paints over the attachment wash when they coincide;
|
|
21314
|
+
// hover previews paint over everything while they last.
|
|
21315
|
+
".cm-variant-target": {
|
|
21316
|
+
background: "color-mix(in srgb, var(--accent) 8%, transparent)",
|
|
21317
|
+
borderRadius: "3px",
|
|
21318
|
+
outline: "1.5px dashed var(--accent)",
|
|
21319
|
+
outlineOffset: "3px"
|
|
21320
|
+
},
|
|
21321
|
+
// Hover preview of a variant: the same white sheet, but dashed — a sketch
|
|
21322
|
+
// of the text, not the text. Only shows while a card is hovered or focused.
|
|
20290
21323
|
".cm-variant-plain": {
|
|
20291
21324
|
background: "var(--overlay)",
|
|
20292
21325
|
borderRadius: "2px",
|
|
20293
21326
|
boxShadow: "0 0 0 2px var(--overlay)",
|
|
20294
|
-
|
|
21327
|
+
border: "1px dashed var(--accent)"
|
|
20295
21328
|
},
|
|
20296
21329
|
// Slightly dim the content while /idea is streaming
|
|
20297
21330
|
"&.streaming .cm-content": { opacity: "0.8" },
|
|
@@ -20354,12 +21387,23 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20354
21387
|
])),
|
|
20355
21388
|
// Standard text-editing and history keymaps
|
|
20356
21389
|
keymap.of([...searchKeymap, ...historyKeymap, ...defaultKeymap]),
|
|
20357
|
-
|
|
21390
|
+
// Native spellcheck: free red squiggly + right-click suggestions from
|
|
21391
|
+
// the OS/browser dictionary. Autocorrect/autocapitalize stay off — a
|
|
21392
|
+
// silent rewrite is not what "quick fix" means here.
|
|
21393
|
+
EditorView.contentAttributes.of({
|
|
21394
|
+
"aria-label": "Draft editor",
|
|
21395
|
+
"aria-describedby": "suggest-shortcut",
|
|
21396
|
+
spellcheck: "true",
|
|
21397
|
+
autocorrect: "off",
|
|
21398
|
+
autocapitalize: "off"
|
|
21399
|
+
}),
|
|
20358
21400
|
// Ghost text state + decoration provider
|
|
20359
21401
|
ghostField,
|
|
20360
21402
|
reviewField,
|
|
20361
21403
|
styleMarkerField,
|
|
21404
|
+
spellMarkerField,
|
|
20362
21405
|
attachField,
|
|
21406
|
+
variantTargetField,
|
|
20363
21407
|
variantPlainField,
|
|
20364
21408
|
flashField,
|
|
20365
21409
|
// Read-only compartment — toggled during /idea streaming
|
|
@@ -20389,9 +21433,16 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20389
21433
|
const at = { x: event.clientX, y: event.clientY };
|
|
20390
21434
|
const mark = event.target.closest?.(".cm-slop");
|
|
20391
21435
|
if (!mark) {
|
|
21436
|
+
const spellLocal = event.target.closest?.(".cm-spell-marker");
|
|
21437
|
+
const spellMarker = spellLocal && view.state.field(spellMarkerField).find((item) => item.from === Number(spellLocal.dataset.spellFrom));
|
|
21438
|
+
if (spellMarker) {
|
|
21439
|
+
showSpellBubble(spellMarker, at.x, at.y);
|
|
21440
|
+
return false;
|
|
21441
|
+
}
|
|
20392
21442
|
const local = event.target.closest?.(".cm-style-marker");
|
|
20393
21443
|
const marker = local && view.state.field(styleMarkerField).find((item) => item.from === Number(local.dataset.styleFrom));
|
|
20394
21444
|
if (marker) selectStyleMarker(marker);
|
|
21445
|
+
else if (atParagraphEnd(view.state)) showContinueBubble(at.x, at.y);
|
|
20395
21446
|
return false;
|
|
20396
21447
|
}
|
|
20397
21448
|
const finding = reviewFindings.find((item) => item.id === Number(mark.dataset.slopId));
|
|
@@ -20471,6 +21522,11 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20471
21522
|
}),
|
|
20472
21523
|
parent: editorWrap
|
|
20473
21524
|
});
|
|
21525
|
+
loadSpellDictionary().then((spell) => {
|
|
21526
|
+
spellChecker = spell;
|
|
21527
|
+
workView.dispatch({ effects: refreshSpellFx.of(null) });
|
|
21528
|
+
}).catch(() => {
|
|
21529
|
+
});
|
|
20474
21530
|
new ResizeObserver(() => {
|
|
20475
21531
|
chatHeight = Math.round(chatPanel.getBoundingClientRect().height) + 48;
|
|
20476
21532
|
document.documentElement.style.setProperty("--chat-height", `${chatHeight}px`);
|
|
@@ -20675,8 +21731,8 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20675
21731
|
documentName = current.path.split(/[\\/]/).pop();
|
|
20676
21732
|
diskText = current.text;
|
|
20677
21733
|
diskRevision = current.revision;
|
|
20678
|
-
const
|
|
20679
|
-
workView.dispatch({ changes: { from: 0, to: workView.state.doc.length, insert:
|
|
21734
|
+
const cached2 = docStorage.getItem("wa-working");
|
|
21735
|
+
workView.dispatch({ changes: { from: 0, to: workView.state.doc.length, insert: cached2 ?? current.text } });
|
|
20680
21736
|
loadingDocument = false;
|
|
20681
21737
|
editorSetReadonly(workView, false);
|
|
20682
21738
|
for (const paragraph of reviewParagraphs(workView.state.doc.toString())) checkedSentences.add(paragraph.key);
|
|
@@ -20691,7 +21747,7 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20691
21747
|
restoreFindings();
|
|
20692
21748
|
restoreChat();
|
|
20693
21749
|
syncStyleScore();
|
|
20694
|
-
if (
|
|
21750
|
+
if (cached2 !== null && cached2 !== current.text) promptDiskDrift(current);
|
|
20695
21751
|
else {
|
|
20696
21752
|
saveStatus.textContent = "";
|
|
20697
21753
|
saveStatus.title = "";
|
|
@@ -20916,3 +21972,13 @@ Editing direction: ${activeFinding.fix}`,
|
|
|
20916
21972
|
workView.focus();
|
|
20917
21973
|
syncStyleScore();
|
|
20918
21974
|
})();
|
|
21975
|
+
/*! Bundled license information:
|
|
21976
|
+
|
|
21977
|
+
is-buffer/index.js:
|
|
21978
|
+
(*!
|
|
21979
|
+
* Determine if an object is a Buffer
|
|
21980
|
+
*
|
|
21981
|
+
* @author Feross Aboukhadijeh <https://feross.org>
|
|
21982
|
+
* @license MIT
|
|
21983
|
+
*)
|
|
21984
|
+
*/
|