@wcstack/lint 1.30.0 → 1.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +2327 -95
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
|
-
var __toCommonJS = (
|
|
19
|
+
var __toCommonJS = (mod3) => __copyProps(__defProp({}, "__esModule", { value: true }), mod3);
|
|
20
20
|
|
|
21
21
|
// src/cli.ts
|
|
22
22
|
var cli_exports = {};
|
|
@@ -27,8 +27,34 @@ __export(cli_exports, {
|
|
|
27
27
|
resolveCliLocale: () => resolveCliLocale
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(cli_exports);
|
|
30
|
+
var import_node_fs2 = require("node:fs");
|
|
31
|
+
|
|
32
|
+
// src/fileReader.ts
|
|
30
33
|
var import_node_fs = require("node:fs");
|
|
31
34
|
var import_node_path = require("node:path");
|
|
35
|
+
function createFileReader(htmlPath, read = (p) => (0, import_node_fs.readFileSync)(p, "utf8")) {
|
|
36
|
+
const base = (0, import_node_path.dirname)(htmlPath);
|
|
37
|
+
const cache = /* @__PURE__ */ new Map();
|
|
38
|
+
return (relativePath) => {
|
|
39
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(relativePath) || relativePath.startsWith("/")) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
if (cache.has(relativePath)) {
|
|
43
|
+
return cache.get(relativePath);
|
|
44
|
+
}
|
|
45
|
+
let content;
|
|
46
|
+
try {
|
|
47
|
+
content = read((0, import_node_path.resolve)(base, relativePath));
|
|
48
|
+
if (content.charCodeAt(0) === 65279) {
|
|
49
|
+
content = content.slice(1);
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
content = void 0;
|
|
53
|
+
}
|
|
54
|
+
cache.set(relativePath, content);
|
|
55
|
+
return content;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
32
58
|
|
|
33
59
|
// src/core/offsetToPosition.ts
|
|
34
60
|
function createPositionMapper(text) {
|
|
@@ -91,6 +117,20 @@ var WcsDiagnosticCode = {
|
|
|
91
117
|
TokenUndeclared: "wcs/token-undeclared",
|
|
92
118
|
TokenMisconfigured: "wcs/token-misconfigured",
|
|
93
119
|
NestedAssign: "wcs/nested-assign",
|
|
120
|
+
// --- 意味論(構文・存在検査では捕まらない取り違え。service/semanticValidator.ts) ---
|
|
121
|
+
// `$getAll` / `$resolve` の添字の本数がパスの `*` の本数と噛み合わない。
|
|
122
|
+
// ランタイムは同じ code で raiseError する(超過は以前は黙って無視されていた)。
|
|
123
|
+
IndexArity: "wcs/index-arity",
|
|
124
|
+
// ワイルドカードの階数がスコープの段数を超える(`matrix.*.*` を 1 段の for で読む、
|
|
125
|
+
// `$2` を 1 段のループで読む)。既存の「for の外」検査の深さ方向の一般化。
|
|
126
|
+
WildcardRank: "wcs/wildcard-rank",
|
|
127
|
+
// パス getter どうしの循環参照。ランタイムはアドレススタック上限まで再帰してから落ちる。
|
|
128
|
+
GetterCycle: "wcs/getter-cycle",
|
|
129
|
+
// `$updatedCallback` が、どのバインディングにも現れないパスを判定に使っている。
|
|
130
|
+
// 同コールバックは **binding 駆動**(live binding が適用された path しか報告しない)
|
|
131
|
+
// なので、その分岐は一度も実行されない。表示要素が購読の実体になる事故
|
|
132
|
+
// (examples/state-intersect-scroll の README に記録)の静的検出。
|
|
133
|
+
UpdatedCallbackUnbound: "wcs/updated-callback-unbound",
|
|
94
134
|
// --- <wcs-state> script: $watch declaration ---
|
|
95
135
|
// ランタイム(watch/processWatchDeclaration.ts)が raiseError で落とす宣言。
|
|
96
136
|
// 越境 `@` / `$` 始まり / 空キー・空セグメント / 明らかな非関数ハンドラ。
|
|
@@ -131,6 +171,545 @@ function sortDiagnostics(diagnostics) {
|
|
|
131
171
|
}
|
|
132
172
|
|
|
133
173
|
// ../state/dist/manifest.esm.js
|
|
174
|
+
var _config = {
|
|
175
|
+
bindAttributeName: "data-wcs",
|
|
176
|
+
tagNames: {
|
|
177
|
+
state: "wcs-state"
|
|
178
|
+
},
|
|
179
|
+
locale: "en"
|
|
180
|
+
};
|
|
181
|
+
var config = _config;
|
|
182
|
+
function raiseError(message) {
|
|
183
|
+
throw new Error(`[@wcstack/state] ${message}`);
|
|
184
|
+
}
|
|
185
|
+
function optionsRequired(fnName) {
|
|
186
|
+
raiseError(`filter ${fnName} requires at least one option`);
|
|
187
|
+
}
|
|
188
|
+
function optionMustBeNumber(fnName) {
|
|
189
|
+
raiseError(`filter ${fnName} requires a number as option`);
|
|
190
|
+
}
|
|
191
|
+
function valueMustBeNumber(fnName) {
|
|
192
|
+
raiseError(`filter ${fnName} requires a number value`);
|
|
193
|
+
}
|
|
194
|
+
function valueMustBeBoolean(fnName) {
|
|
195
|
+
raiseError(`filter ${fnName} requires a boolean value`);
|
|
196
|
+
}
|
|
197
|
+
function valueMustBeDate(fnName) {
|
|
198
|
+
raiseError(`filter ${fnName} requires a date value`);
|
|
199
|
+
}
|
|
200
|
+
function valueMustBeArray(fnName) {
|
|
201
|
+
raiseError(`filter ${fnName} requires an array value`);
|
|
202
|
+
}
|
|
203
|
+
function validateNumberString(value) {
|
|
204
|
+
if (!value || isNaN(Number(value))) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
var eq = (options) => {
|
|
210
|
+
const opt = options?.[0] ?? optionsRequired("eq");
|
|
211
|
+
return (value) => {
|
|
212
|
+
if (typeof value === "number") {
|
|
213
|
+
if (!validateNumberString(opt)) {
|
|
214
|
+
optionMustBeNumber("eq");
|
|
215
|
+
}
|
|
216
|
+
return value === Number(opt);
|
|
217
|
+
}
|
|
218
|
+
if (typeof value === "string") {
|
|
219
|
+
return value === opt;
|
|
220
|
+
}
|
|
221
|
+
return value === opt;
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
var ne = (options) => {
|
|
225
|
+
const opt = options?.[0] ?? optionsRequired("ne");
|
|
226
|
+
return (value) => {
|
|
227
|
+
if (typeof value === "number") {
|
|
228
|
+
if (!validateNumberString(opt)) {
|
|
229
|
+
optionMustBeNumber("ne");
|
|
230
|
+
}
|
|
231
|
+
return value !== Number(opt);
|
|
232
|
+
}
|
|
233
|
+
if (typeof value === "string") {
|
|
234
|
+
return value !== opt;
|
|
235
|
+
}
|
|
236
|
+
return value !== opt;
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
var not = (_options) => {
|
|
240
|
+
return (value) => {
|
|
241
|
+
if (typeof value !== "boolean") {
|
|
242
|
+
valueMustBeBoolean("not");
|
|
243
|
+
}
|
|
244
|
+
return !value;
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
var lt = (options) => {
|
|
248
|
+
const opt = options?.[0] ?? optionsRequired("lt");
|
|
249
|
+
if (!validateNumberString(opt)) {
|
|
250
|
+
optionMustBeNumber("lt");
|
|
251
|
+
}
|
|
252
|
+
return (value) => {
|
|
253
|
+
if (typeof value !== "number") {
|
|
254
|
+
valueMustBeNumber("lt");
|
|
255
|
+
}
|
|
256
|
+
return value < Number(opt);
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
var le = (options) => {
|
|
260
|
+
const opt = options?.[0] ?? optionsRequired("le");
|
|
261
|
+
if (!validateNumberString(opt)) {
|
|
262
|
+
optionMustBeNumber("le");
|
|
263
|
+
}
|
|
264
|
+
return (value) => {
|
|
265
|
+
if (typeof value !== "number") {
|
|
266
|
+
valueMustBeNumber("le");
|
|
267
|
+
}
|
|
268
|
+
return value <= Number(opt);
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
var gt = (options) => {
|
|
272
|
+
const opt = options?.[0] ?? optionsRequired("gt");
|
|
273
|
+
if (!validateNumberString(opt)) {
|
|
274
|
+
optionMustBeNumber("gt");
|
|
275
|
+
}
|
|
276
|
+
return (value) => {
|
|
277
|
+
if (typeof value !== "number") {
|
|
278
|
+
valueMustBeNumber("gt");
|
|
279
|
+
}
|
|
280
|
+
return value > Number(opt);
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
var ge = (options) => {
|
|
284
|
+
const opt = options?.[0] ?? optionsRequired("ge");
|
|
285
|
+
if (!validateNumberString(opt)) {
|
|
286
|
+
optionMustBeNumber("ge");
|
|
287
|
+
}
|
|
288
|
+
return (value) => {
|
|
289
|
+
if (typeof value !== "number") {
|
|
290
|
+
valueMustBeNumber("ge");
|
|
291
|
+
}
|
|
292
|
+
return value >= Number(opt);
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
var inc = (options) => {
|
|
296
|
+
const opt = options?.[0] ?? optionsRequired("inc");
|
|
297
|
+
if (!validateNumberString(opt)) {
|
|
298
|
+
optionMustBeNumber("inc");
|
|
299
|
+
}
|
|
300
|
+
return (value) => {
|
|
301
|
+
if (typeof value !== "number") {
|
|
302
|
+
valueMustBeNumber("inc");
|
|
303
|
+
}
|
|
304
|
+
return value + Number(opt);
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
var dec = (options) => {
|
|
308
|
+
const opt = options?.[0] ?? optionsRequired("dec");
|
|
309
|
+
if (!validateNumberString(opt)) {
|
|
310
|
+
optionMustBeNumber("dec");
|
|
311
|
+
}
|
|
312
|
+
return (value) => {
|
|
313
|
+
if (typeof value !== "number") {
|
|
314
|
+
valueMustBeNumber("dec");
|
|
315
|
+
}
|
|
316
|
+
return value - Number(opt);
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
var mul = (options) => {
|
|
320
|
+
const opt = options?.[0] ?? optionsRequired("mul");
|
|
321
|
+
if (!validateNumberString(opt)) {
|
|
322
|
+
optionMustBeNumber("mul");
|
|
323
|
+
}
|
|
324
|
+
return (value) => {
|
|
325
|
+
if (typeof value !== "number") {
|
|
326
|
+
valueMustBeNumber("mul");
|
|
327
|
+
}
|
|
328
|
+
return value * Number(opt);
|
|
329
|
+
};
|
|
330
|
+
};
|
|
331
|
+
var div = (options) => {
|
|
332
|
+
const opt = options?.[0] ?? optionsRequired("div");
|
|
333
|
+
if (!validateNumberString(opt)) {
|
|
334
|
+
optionMustBeNumber("div");
|
|
335
|
+
}
|
|
336
|
+
return (value) => {
|
|
337
|
+
if (typeof value !== "number") {
|
|
338
|
+
valueMustBeNumber("div");
|
|
339
|
+
}
|
|
340
|
+
return value / Number(opt);
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
var mod = (options) => {
|
|
344
|
+
const opt = options?.[0] ?? optionsRequired("mod");
|
|
345
|
+
if (!validateNumberString(opt)) {
|
|
346
|
+
optionMustBeNumber("mod");
|
|
347
|
+
}
|
|
348
|
+
return (value) => {
|
|
349
|
+
if (typeof value !== "number") {
|
|
350
|
+
valueMustBeNumber("mod");
|
|
351
|
+
}
|
|
352
|
+
return value % Number(opt);
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
var abs = (_options) => {
|
|
356
|
+
return (value) => {
|
|
357
|
+
if (typeof value !== "number") {
|
|
358
|
+
valueMustBeNumber("abs");
|
|
359
|
+
}
|
|
360
|
+
return Math.abs(value);
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
var clamp = (options) => {
|
|
364
|
+
const opt1 = options?.[0] ?? optionsRequired("clamp");
|
|
365
|
+
if (!validateNumberString(opt1)) {
|
|
366
|
+
optionMustBeNumber("clamp");
|
|
367
|
+
}
|
|
368
|
+
const opt2 = options?.[1] ?? optionsRequired("clamp");
|
|
369
|
+
if (!validateNumberString(opt2)) {
|
|
370
|
+
optionMustBeNumber("clamp");
|
|
371
|
+
}
|
|
372
|
+
const min = Number(opt1);
|
|
373
|
+
const max = Number(opt2);
|
|
374
|
+
return (value) => {
|
|
375
|
+
if (typeof value !== "number") {
|
|
376
|
+
valueMustBeNumber("clamp");
|
|
377
|
+
}
|
|
378
|
+
return Math.min(Math.max(value, min), max);
|
|
379
|
+
};
|
|
380
|
+
};
|
|
381
|
+
var fix = (options) => {
|
|
382
|
+
const opt = options?.[0] ?? "0";
|
|
383
|
+
if (!validateNumberString(opt)) {
|
|
384
|
+
optionMustBeNumber("fix");
|
|
385
|
+
}
|
|
386
|
+
return (value) => {
|
|
387
|
+
if (typeof value !== "number") {
|
|
388
|
+
valueMustBeNumber("fix");
|
|
389
|
+
}
|
|
390
|
+
return value.toFixed(Number(opt));
|
|
391
|
+
};
|
|
392
|
+
};
|
|
393
|
+
var locale = (options) => {
|
|
394
|
+
const opt = options?.[0] ?? config.locale;
|
|
395
|
+
return (value) => {
|
|
396
|
+
if (typeof value !== "number") {
|
|
397
|
+
valueMustBeNumber("locale");
|
|
398
|
+
}
|
|
399
|
+
return value.toLocaleString(opt);
|
|
400
|
+
};
|
|
401
|
+
};
|
|
402
|
+
var uc = (_options) => {
|
|
403
|
+
return (value) => {
|
|
404
|
+
return String(value).toUpperCase();
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
var lc = (_options) => {
|
|
408
|
+
return (value) => {
|
|
409
|
+
return String(value).toLowerCase();
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
var cap = (_options) => {
|
|
413
|
+
return (value) => {
|
|
414
|
+
const v = String(value);
|
|
415
|
+
if (v.length === 0) {
|
|
416
|
+
return v;
|
|
417
|
+
}
|
|
418
|
+
if (v.length === 1) {
|
|
419
|
+
return v.toUpperCase();
|
|
420
|
+
}
|
|
421
|
+
return v.charAt(0).toUpperCase() + v.slice(1);
|
|
422
|
+
};
|
|
423
|
+
};
|
|
424
|
+
var trim = (_options) => {
|
|
425
|
+
return (value) => {
|
|
426
|
+
return String(value).trim();
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
var slice = (options) => {
|
|
430
|
+
const numberedOpts = [];
|
|
431
|
+
const opt1 = options?.[0] ?? optionsRequired("slice");
|
|
432
|
+
if (!validateNumberString(opt1)) {
|
|
433
|
+
optionMustBeNumber("slice");
|
|
434
|
+
}
|
|
435
|
+
numberedOpts.push(Number(opt1));
|
|
436
|
+
const opt2 = options?.[1];
|
|
437
|
+
if (typeof opt2 !== "undefined") {
|
|
438
|
+
if (!validateNumberString(opt2)) {
|
|
439
|
+
optionMustBeNumber("slice");
|
|
440
|
+
}
|
|
441
|
+
numberedOpts.push(Number(opt2));
|
|
442
|
+
}
|
|
443
|
+
return (value) => {
|
|
444
|
+
return String(value).slice(...numberedOpts);
|
|
445
|
+
};
|
|
446
|
+
};
|
|
447
|
+
var substr = (options) => {
|
|
448
|
+
const opt1 = options?.[0] ?? optionsRequired("substr");
|
|
449
|
+
if (!validateNumberString(opt1)) {
|
|
450
|
+
optionMustBeNumber("substr");
|
|
451
|
+
}
|
|
452
|
+
const opt2 = options?.[1] ?? optionsRequired("substr");
|
|
453
|
+
if (!validateNumberString(opt2)) {
|
|
454
|
+
optionMustBeNumber("substr");
|
|
455
|
+
}
|
|
456
|
+
return (value) => {
|
|
457
|
+
return String(value).substr(Number(opt1), Number(opt2));
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
var pad = (options) => {
|
|
461
|
+
const opt1 = options?.[0] ?? optionsRequired("pad");
|
|
462
|
+
if (!validateNumberString(opt1)) {
|
|
463
|
+
optionMustBeNumber("pad");
|
|
464
|
+
}
|
|
465
|
+
const opt2 = options?.[1] ?? "0";
|
|
466
|
+
return (value) => {
|
|
467
|
+
return String(value).padStart(Number(opt1), opt2);
|
|
468
|
+
};
|
|
469
|
+
};
|
|
470
|
+
var rep = (options) => {
|
|
471
|
+
const opt = options?.[0] ?? optionsRequired("rep");
|
|
472
|
+
if (!validateNumberString(opt)) {
|
|
473
|
+
optionMustBeNumber("rep");
|
|
474
|
+
}
|
|
475
|
+
return (value) => {
|
|
476
|
+
return String(value).repeat(Number(opt));
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
var rev = (_options) => {
|
|
480
|
+
return (value) => {
|
|
481
|
+
return String(value).split("").reverse().join("");
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
var int = (_options) => {
|
|
485
|
+
return (value) => {
|
|
486
|
+
return parseInt(String(value), 10);
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
var float = (_options) => {
|
|
490
|
+
return (value) => {
|
|
491
|
+
return parseFloat(String(value));
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
var round = (options) => {
|
|
495
|
+
const opt = options?.[0] ?? "0";
|
|
496
|
+
if (!validateNumberString(opt)) {
|
|
497
|
+
optionMustBeNumber("round");
|
|
498
|
+
}
|
|
499
|
+
return (value) => {
|
|
500
|
+
if (typeof value !== "number") {
|
|
501
|
+
valueMustBeNumber("round");
|
|
502
|
+
}
|
|
503
|
+
const optValue = Math.pow(10, Number(opt));
|
|
504
|
+
return Math.round(value * optValue) / optValue;
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
var floor = (options) => {
|
|
508
|
+
const opt = options?.[0] ?? "0";
|
|
509
|
+
if (!validateNumberString(opt)) {
|
|
510
|
+
optionMustBeNumber("floor");
|
|
511
|
+
}
|
|
512
|
+
return (value) => {
|
|
513
|
+
if (typeof value !== "number") {
|
|
514
|
+
valueMustBeNumber("floor");
|
|
515
|
+
}
|
|
516
|
+
const optValue = Math.pow(10, Number(opt));
|
|
517
|
+
return Math.floor(value * optValue) / optValue;
|
|
518
|
+
};
|
|
519
|
+
};
|
|
520
|
+
var ceil = (options) => {
|
|
521
|
+
const opt = options?.[0] ?? "0";
|
|
522
|
+
if (!validateNumberString(opt)) {
|
|
523
|
+
optionMustBeNumber("ceil");
|
|
524
|
+
}
|
|
525
|
+
return (value) => {
|
|
526
|
+
if (typeof value !== "number") {
|
|
527
|
+
valueMustBeNumber("ceil");
|
|
528
|
+
}
|
|
529
|
+
const optValue = Math.pow(10, Number(opt));
|
|
530
|
+
return Math.ceil(value * optValue) / optValue;
|
|
531
|
+
};
|
|
532
|
+
};
|
|
533
|
+
var percent = (options) => {
|
|
534
|
+
const opt = options?.[0] ?? "0";
|
|
535
|
+
if (!validateNumberString(opt)) {
|
|
536
|
+
optionMustBeNumber("percent");
|
|
537
|
+
}
|
|
538
|
+
return (value) => {
|
|
539
|
+
if (typeof value !== "number") {
|
|
540
|
+
valueMustBeNumber("percent");
|
|
541
|
+
}
|
|
542
|
+
return `${(value * 100).toFixed(Number(opt))}%`;
|
|
543
|
+
};
|
|
544
|
+
};
|
|
545
|
+
var unit = (options) => {
|
|
546
|
+
const opt = options?.[0] ?? optionsRequired("unit");
|
|
547
|
+
return (value) => {
|
|
548
|
+
if (value === null || typeof value === "undefined") {
|
|
549
|
+
return value;
|
|
550
|
+
}
|
|
551
|
+
return String(value) + opt;
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
var join = (options) => {
|
|
555
|
+
const opt = options?.[0] ?? ", ";
|
|
556
|
+
return (value) => {
|
|
557
|
+
if (!Array.isArray(value)) {
|
|
558
|
+
valueMustBeArray("join");
|
|
559
|
+
}
|
|
560
|
+
return value.join(opt);
|
|
561
|
+
};
|
|
562
|
+
};
|
|
563
|
+
var truncate = (options) => {
|
|
564
|
+
const opt1 = options?.[0] ?? optionsRequired("truncate");
|
|
565
|
+
if (!validateNumberString(opt1)) {
|
|
566
|
+
optionMustBeNumber("truncate");
|
|
567
|
+
}
|
|
568
|
+
const maxLength = Number(opt1);
|
|
569
|
+
const suffix = options?.[1] ?? "\u2026";
|
|
570
|
+
return (value) => {
|
|
571
|
+
const v = String(value);
|
|
572
|
+
if (v.length <= maxLength) {
|
|
573
|
+
return v;
|
|
574
|
+
}
|
|
575
|
+
return v.slice(0, maxLength) + suffix;
|
|
576
|
+
};
|
|
577
|
+
};
|
|
578
|
+
var date = (options) => {
|
|
579
|
+
const opt = options?.[0] ?? config.locale;
|
|
580
|
+
return (value) => {
|
|
581
|
+
if (!(value instanceof Date)) {
|
|
582
|
+
valueMustBeDate("date");
|
|
583
|
+
}
|
|
584
|
+
return value.toLocaleDateString(opt);
|
|
585
|
+
};
|
|
586
|
+
};
|
|
587
|
+
var time = (options) => {
|
|
588
|
+
const opt = options?.[0] ?? config.locale;
|
|
589
|
+
return (value) => {
|
|
590
|
+
if (!(value instanceof Date)) {
|
|
591
|
+
valueMustBeDate("time");
|
|
592
|
+
}
|
|
593
|
+
return value.toLocaleTimeString(opt);
|
|
594
|
+
};
|
|
595
|
+
};
|
|
596
|
+
var datetime = (options) => {
|
|
597
|
+
const opt = options?.[0] ?? config.locale;
|
|
598
|
+
return (value) => {
|
|
599
|
+
if (!(value instanceof Date)) {
|
|
600
|
+
valueMustBeDate("datetime");
|
|
601
|
+
}
|
|
602
|
+
return value.toLocaleString(opt);
|
|
603
|
+
};
|
|
604
|
+
};
|
|
605
|
+
var ymd = (options) => {
|
|
606
|
+
const opt = options?.[0] ?? "-";
|
|
607
|
+
return (value) => {
|
|
608
|
+
if (!(value instanceof Date)) {
|
|
609
|
+
valueMustBeDate("ymd");
|
|
610
|
+
}
|
|
611
|
+
const year = value.getFullYear().toString();
|
|
612
|
+
const month = (value.getMonth() + 1).toString().padStart(2, "0");
|
|
613
|
+
const day = value.getDate().toString().padStart(2, "0");
|
|
614
|
+
return `${year}${opt}${month}${opt}${day}`;
|
|
615
|
+
};
|
|
616
|
+
};
|
|
617
|
+
var hms = (options) => {
|
|
618
|
+
const opt = options?.[0] ?? ":";
|
|
619
|
+
return (value) => {
|
|
620
|
+
if (!(value instanceof Date)) {
|
|
621
|
+
valueMustBeDate("hms");
|
|
622
|
+
}
|
|
623
|
+
const hours = value.getHours().toString().padStart(2, "0");
|
|
624
|
+
const minutes = value.getMinutes().toString().padStart(2, "0");
|
|
625
|
+
const seconds = value.getSeconds().toString().padStart(2, "0");
|
|
626
|
+
return `${hours}${opt}${minutes}${opt}${seconds}`;
|
|
627
|
+
};
|
|
628
|
+
};
|
|
629
|
+
var falsy = (_options) => {
|
|
630
|
+
return (value) => value === false || value === null || value === void 0 || value === 0 || value === "" || Number.isNaN(value);
|
|
631
|
+
};
|
|
632
|
+
var truthy = (_options) => {
|
|
633
|
+
return (value) => value !== false && value !== null && value !== void 0 && value !== 0 && value !== "" && !Number.isNaN(value);
|
|
634
|
+
};
|
|
635
|
+
var defaults = (options) => {
|
|
636
|
+
const opt = options?.[0] ?? optionsRequired("defaults");
|
|
637
|
+
return (value) => {
|
|
638
|
+
if (value === false || value === null || value === void 0 || value === 0 || value === "" || Number.isNaN(value)) {
|
|
639
|
+
return opt;
|
|
640
|
+
}
|
|
641
|
+
return value;
|
|
642
|
+
};
|
|
643
|
+
};
|
|
644
|
+
var boolean = (_options) => {
|
|
645
|
+
return (value) => {
|
|
646
|
+
return Boolean(value);
|
|
647
|
+
};
|
|
648
|
+
};
|
|
649
|
+
var number = (_options) => {
|
|
650
|
+
return (value) => {
|
|
651
|
+
return Number(value);
|
|
652
|
+
};
|
|
653
|
+
};
|
|
654
|
+
var string = (_options) => {
|
|
655
|
+
return (value) => {
|
|
656
|
+
return String(value);
|
|
657
|
+
};
|
|
658
|
+
};
|
|
659
|
+
var _null = (_options) => {
|
|
660
|
+
return (value) => {
|
|
661
|
+
return value === "" ? null : value;
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
var builtinFilters = {
|
|
665
|
+
"eq": eq,
|
|
666
|
+
"ne": ne,
|
|
667
|
+
"not": not,
|
|
668
|
+
"lt": lt,
|
|
669
|
+
"le": le,
|
|
670
|
+
"gt": gt,
|
|
671
|
+
"ge": ge,
|
|
672
|
+
"inc": inc,
|
|
673
|
+
"dec": dec,
|
|
674
|
+
"mul": mul,
|
|
675
|
+
"div": div,
|
|
676
|
+
"mod": mod,
|
|
677
|
+
"abs": abs,
|
|
678
|
+
"clamp": clamp,
|
|
679
|
+
"fix": fix,
|
|
680
|
+
"locale": locale,
|
|
681
|
+
"uc": uc,
|
|
682
|
+
"lc": lc,
|
|
683
|
+
"cap": cap,
|
|
684
|
+
"trim": trim,
|
|
685
|
+
"slice": slice,
|
|
686
|
+
"substr": substr,
|
|
687
|
+
"pad": pad,
|
|
688
|
+
"rep": rep,
|
|
689
|
+
"rev": rev,
|
|
690
|
+
"truncate": truncate,
|
|
691
|
+
"join": join,
|
|
692
|
+
"int": int,
|
|
693
|
+
"float": float,
|
|
694
|
+
"round": round,
|
|
695
|
+
"floor": floor,
|
|
696
|
+
"ceil": ceil,
|
|
697
|
+
"percent": percent,
|
|
698
|
+
"unit": unit,
|
|
699
|
+
"date": date,
|
|
700
|
+
"time": time,
|
|
701
|
+
"datetime": datetime,
|
|
702
|
+
"ymd": ymd,
|
|
703
|
+
"hms": hms,
|
|
704
|
+
"falsy": falsy,
|
|
705
|
+
"truthy": truthy,
|
|
706
|
+
"defaults": defaults,
|
|
707
|
+
"boolean": boolean,
|
|
708
|
+
"number": number,
|
|
709
|
+
"string": string,
|
|
710
|
+
"null": _null
|
|
711
|
+
};
|
|
712
|
+
var outputBuiltinFilters = builtinFilters;
|
|
134
713
|
var builtinFilterMeta = {
|
|
135
714
|
// 比較・論理
|
|
136
715
|
eq: { description: "\u7B49\u3057\u3044\u304B\u6BD4\u8F03", hasArgs: true, resultType: "boolean", acceptTypes: "any", minArgs: 1, maxArgs: 1, argTypes: ["any"] },
|
|
@@ -194,7 +773,14 @@ var STRUCTURAL_BINDING_TYPE_SET = /* @__PURE__ */ new Set([
|
|
|
194
773
|
"else",
|
|
195
774
|
"for"
|
|
196
775
|
]);
|
|
776
|
+
var DELIMITER = ".";
|
|
777
|
+
var WILDCARD = "*";
|
|
197
778
|
var MAX_WILDCARD_DEPTH = 128;
|
|
779
|
+
var BINDING_SEPARATOR = ";";
|
|
780
|
+
var PROP_VALUE_SEPARATOR = ":";
|
|
781
|
+
var MODIFIER_SEPARATOR = "#";
|
|
782
|
+
var STATE_NAME_SEPARATOR = "@";
|
|
783
|
+
var FILTER_SEPARATOR = "|";
|
|
198
784
|
var MODIFIER_PREVENT = "prevent";
|
|
199
785
|
var MODIFIER_STOP = "stop";
|
|
200
786
|
var MODIFIER_READONLY = "ro";
|
|
@@ -209,12 +795,99 @@ var MODIFIER_KEYS = Object.freeze([
|
|
|
209
795
|
MODIFIER_KEY_INIT,
|
|
210
796
|
MODIFIER_KEY_SYNC
|
|
211
797
|
]);
|
|
798
|
+
var ELSE_KEYWORD = "else";
|
|
799
|
+
var SPREAD_PROP = "...";
|
|
800
|
+
var EVENT_PROP_PREFIX = "on";
|
|
801
|
+
var EVENT_TOKEN_NAMESPACE = "eventToken";
|
|
802
|
+
var COMMAND_NAMESPACE = "command";
|
|
803
|
+
var CLASS_NAMESPACE = "class";
|
|
804
|
+
var ATTR_NAMESPACE = "attr";
|
|
805
|
+
var STYLE_NAMESPACE = "style";
|
|
212
806
|
var INDEX_PARAM_PREFIX = "$";
|
|
213
807
|
var tmpIndexByIndexName = {};
|
|
214
808
|
for (let i = 0; i < MAX_WILDCARD_DEPTH; i++) {
|
|
215
809
|
tmpIndexByIndexName[`${INDEX_PARAM_PREFIX}${i + 1}`] = i;
|
|
216
810
|
}
|
|
217
811
|
Object.freeze(tmpIndexByIndexName);
|
|
812
|
+
var STATE_CONNECTED_CALLBACK_NAME = "$connectedCallback";
|
|
813
|
+
var STATE_DISCONNECTED_CALLBACK_NAME = "$disconnectedCallback";
|
|
814
|
+
var STATE_UPDATED_CALLBACK_NAME = "$updatedCallback";
|
|
815
|
+
var WEBCOMPONENT_STATE_READY_CALLBACK_NAME = "$stateReadyCallback";
|
|
816
|
+
var STATE_BINDABLES_NAME = "$bindables";
|
|
817
|
+
var STATE_COMMANDS_NAME = "$commands";
|
|
818
|
+
var STATE_COMMAND_TOKENS_NAME = "$commandTokens";
|
|
819
|
+
var STATE_COMMAND_NAMESPACE_NAME = "$command";
|
|
820
|
+
var STATE_EVENT_TOKENS_NAME = "$eventTokens";
|
|
821
|
+
var STATE_ON_NAME = "$on";
|
|
822
|
+
var STATE_STREAMS_NAME = "$streams";
|
|
823
|
+
var STATE_WATCH_NAME = "$watch";
|
|
824
|
+
var STATE_LIST_KEYS_NAME = "$listKeys";
|
|
825
|
+
var STATE_STREAM_STATUS_NAMESPACE_NAME = "$streamStatus";
|
|
826
|
+
var STATE_STREAM_ERROR_NAMESPACE_NAME = "$streamError";
|
|
827
|
+
var WCS_MANIFEST_VERSION = 1;
|
|
828
|
+
function getWcsManifest() {
|
|
829
|
+
return {
|
|
830
|
+
version: WCS_MANIFEST_VERSION,
|
|
831
|
+
syntax: {
|
|
832
|
+
bindAttribute: config.bindAttributeName,
|
|
833
|
+
tagName: config.tagNames.state,
|
|
834
|
+
pathDelimiter: DELIMITER,
|
|
835
|
+
wildcard: WILDCARD,
|
|
836
|
+
delimiters: {
|
|
837
|
+
binding: BINDING_SEPARATOR,
|
|
838
|
+
propValue: PROP_VALUE_SEPARATOR,
|
|
839
|
+
modifier: MODIFIER_SEPARATOR,
|
|
840
|
+
stateName: STATE_NAME_SEPARATOR,
|
|
841
|
+
filter: FILTER_SEPARATOR
|
|
842
|
+
},
|
|
843
|
+
// 正本 STRUCTURAL_BINDING_TYPE_SET から導出(手書きの二重定義を排除)。
|
|
844
|
+
structuralDirectives: Array.from(STRUCTURAL_BINDING_TYPE_SET),
|
|
845
|
+
modifiers: {
|
|
846
|
+
flags: MODIFIER_FLAGS,
|
|
847
|
+
keyValue: MODIFIER_KEYS,
|
|
848
|
+
eventNamePrefix: EVENT_PROP_PREFIX
|
|
849
|
+
},
|
|
850
|
+
indexParam: {
|
|
851
|
+
prefix: INDEX_PARAM_PREFIX,
|
|
852
|
+
maxDepth: MAX_WILDCARD_DEPTH
|
|
853
|
+
},
|
|
854
|
+
bindingTypes: {
|
|
855
|
+
elseKeyword: ELSE_KEYWORD,
|
|
856
|
+
spread: SPREAD_PROP,
|
|
857
|
+
eventPropertyPrefix: EVENT_PROP_PREFIX,
|
|
858
|
+
propNamespaces: {
|
|
859
|
+
eventToken: EVENT_TOKEN_NAMESPACE,
|
|
860
|
+
command: COMMAND_NAMESPACE,
|
|
861
|
+
class: CLASS_NAMESPACE,
|
|
862
|
+
attr: ATTR_NAMESPACE,
|
|
863
|
+
style: STYLE_NAMESPACE
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
// 実装(Record のキー)から自動導出。手リストを持たない=ドリフトの構造的排除。
|
|
868
|
+
filters: Object.keys(outputBuiltinFilters),
|
|
869
|
+
filterMeta: builtinFilterMeta,
|
|
870
|
+
reservedLifecycle: [
|
|
871
|
+
STATE_CONNECTED_CALLBACK_NAME,
|
|
872
|
+
STATE_DISCONNECTED_CALLBACK_NAME,
|
|
873
|
+
STATE_UPDATED_CALLBACK_NAME,
|
|
874
|
+
WEBCOMPONENT_STATE_READY_CALLBACK_NAME
|
|
875
|
+
],
|
|
876
|
+
reservedStateApi: [
|
|
877
|
+
STATE_BINDABLES_NAME,
|
|
878
|
+
STATE_COMMANDS_NAME,
|
|
879
|
+
STATE_COMMAND_TOKENS_NAME,
|
|
880
|
+
STATE_COMMAND_NAMESPACE_NAME,
|
|
881
|
+
STATE_EVENT_TOKENS_NAME,
|
|
882
|
+
STATE_ON_NAME,
|
|
883
|
+
STATE_STREAMS_NAME,
|
|
884
|
+
STATE_WATCH_NAME,
|
|
885
|
+
STATE_LIST_KEYS_NAME,
|
|
886
|
+
STATE_STREAM_STATUS_NAMESPACE_NAME,
|
|
887
|
+
STATE_STREAM_ERROR_NAMESPACE_NAME
|
|
888
|
+
]
|
|
889
|
+
};
|
|
890
|
+
}
|
|
218
891
|
|
|
219
892
|
// src/service/completionData.ts
|
|
220
893
|
var BUILTIN_FILTERS = Object.entries(builtinFilterMeta).map(
|
|
@@ -360,7 +1033,7 @@ function parseWcsStateElements(html, stateTagName = "wcs-state") {
|
|
|
360
1033
|
}
|
|
361
1034
|
return elements;
|
|
362
1035
|
}
|
|
363
|
-
function findScriptJsonById(html,
|
|
1036
|
+
function findScriptJsonById(html, id2) {
|
|
364
1037
|
let pos = 0;
|
|
365
1038
|
const len = html.length;
|
|
366
1039
|
while (pos < len) {
|
|
@@ -377,7 +1050,7 @@ function findScriptJsonById(html, id) {
|
|
|
377
1050
|
}
|
|
378
1051
|
const typeAttr = extractAttribute(scriptMatch.tagContent, "type");
|
|
379
1052
|
const idAttr = extractAttribute(scriptMatch.tagContent, "id");
|
|
380
|
-
if (typeAttr?.toLowerCase() === "application/json" && idAttr ===
|
|
1053
|
+
if (typeAttr?.toLowerCase() === "application/json" && idAttr === id2) {
|
|
381
1054
|
const contentStart = scriptMatch.end;
|
|
382
1055
|
const scriptCloseIdx = findCloseTag(html, contentStart, "script");
|
|
383
1056
|
if (scriptCloseIdx === -1) return null;
|
|
@@ -392,8 +1065,8 @@ function matchOpenTag(html, pos, tagName) {
|
|
|
392
1065
|
const nameStart = pos + 1;
|
|
393
1066
|
const nameEnd = nameStart + tagName.length;
|
|
394
1067
|
if (nameEnd > html.length) return null;
|
|
395
|
-
const
|
|
396
|
-
if (
|
|
1068
|
+
const slice3 = html.slice(nameStart, nameEnd);
|
|
1069
|
+
if (slice3.toLowerCase() !== tagName.toLowerCase()) return null;
|
|
397
1070
|
const charAfter = html[nameEnd];
|
|
398
1071
|
if (charAfter !== ">" && charAfter !== " " && charAfter !== " " && charAfter !== "\n" && charAfter !== "\r" && charAfter !== "/") {
|
|
399
1072
|
return null;
|
|
@@ -512,6 +1185,39 @@ function analyzeWatchEntries(scriptContent) {
|
|
|
512
1185
|
}
|
|
513
1186
|
return entries;
|
|
514
1187
|
}
|
|
1188
|
+
function analyzeDeclarationSpans(scriptContent) {
|
|
1189
|
+
const root = locateDefaultExportObject(scriptContent);
|
|
1190
|
+
if (!root) return [];
|
|
1191
|
+
const out = [];
|
|
1192
|
+
for (const prop of parseTopLevelProperties(root.content)) {
|
|
1193
|
+
if (prop.nameStart === void 0 || prop.nameEnd === void 0) continue;
|
|
1194
|
+
out.push({
|
|
1195
|
+
name: prop.name,
|
|
1196
|
+
kind: prop.kind,
|
|
1197
|
+
start: root.start + prop.nameStart,
|
|
1198
|
+
end: root.start + prop.nameEnd
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
return out;
|
|
1202
|
+
}
|
|
1203
|
+
function analyzeCallableBodies(scriptContent) {
|
|
1204
|
+
const root = locateDefaultExportObject(scriptContent);
|
|
1205
|
+
if (!root) return [];
|
|
1206
|
+
const out = [];
|
|
1207
|
+
for (const prop of parseTopLevelProperties(root.content)) {
|
|
1208
|
+
if (prop.kind !== "getter" && prop.kind !== "method") continue;
|
|
1209
|
+
if (prop.nameStart === void 0 || prop.nameEnd === void 0) continue;
|
|
1210
|
+
out.push({
|
|
1211
|
+
name: prop.name,
|
|
1212
|
+
kind: prop.kind,
|
|
1213
|
+
start: root.start + prop.nameStart,
|
|
1214
|
+
end: root.start + prop.nameEnd,
|
|
1215
|
+
body: prop.value ?? "",
|
|
1216
|
+
bodyStart: root.start + (prop.valueStart ?? 0)
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
return out;
|
|
1220
|
+
}
|
|
515
1221
|
function isNonFunctionLiteral(value) {
|
|
516
1222
|
if (value === void 0) return false;
|
|
517
1223
|
const trimmed = value.trim();
|
|
@@ -711,17 +1417,32 @@ function parseTopLevelProperties(objectContent) {
|
|
|
711
1417
|
const braceStart = match.index + match[0].length - 1;
|
|
712
1418
|
const body = extractBracedContent(objectContent, scan, braceStart);
|
|
713
1419
|
regex.lastIndex = braceStart + body.length + 2;
|
|
1420
|
+
return { body, bodyStart: braceStart + 1 };
|
|
714
1421
|
};
|
|
715
1422
|
const accessorName = nameAt(1) ?? nameAt(2) ?? nameAt(3);
|
|
716
1423
|
if (accessorName) {
|
|
717
|
-
|
|
718
|
-
|
|
1424
|
+
const { body, bodyStart } = skipBody();
|
|
1425
|
+
props.push({
|
|
1426
|
+
name: accessorName,
|
|
1427
|
+
kind: "getter",
|
|
1428
|
+
value: body,
|
|
1429
|
+
valueStart: bodyStart,
|
|
1430
|
+
nameStart: nameSpan[0],
|
|
1431
|
+
nameEnd: nameSpan[1]
|
|
1432
|
+
});
|
|
719
1433
|
continue;
|
|
720
1434
|
}
|
|
721
1435
|
const methodName = nameAt(4) ?? nameAt(5) ?? nameAt(6);
|
|
722
1436
|
if (methodName) {
|
|
723
|
-
|
|
724
|
-
|
|
1437
|
+
const { body, bodyStart } = skipBody();
|
|
1438
|
+
props.push({
|
|
1439
|
+
name: methodName,
|
|
1440
|
+
kind: "method",
|
|
1441
|
+
value: body,
|
|
1442
|
+
valueStart: bodyStart,
|
|
1443
|
+
nameStart: nameSpan[0],
|
|
1444
|
+
nameEnd: nameSpan[1]
|
|
1445
|
+
});
|
|
725
1446
|
continue;
|
|
726
1447
|
}
|
|
727
1448
|
const propName = nameAt(7) ?? nameAt(8) ?? nameAt(9);
|
|
@@ -1007,6 +1728,37 @@ function getEnclosingFors(html, offset, bindAttrName = "data-wcs") {
|
|
|
1007
1728
|
}
|
|
1008
1729
|
return enclosing;
|
|
1009
1730
|
}
|
|
1731
|
+
function countWildcardSegments(path) {
|
|
1732
|
+
let count = 0;
|
|
1733
|
+
for (const segment of path.split(".")) {
|
|
1734
|
+
if (segment === "*") count++;
|
|
1735
|
+
}
|
|
1736
|
+
return count;
|
|
1737
|
+
}
|
|
1738
|
+
function forPathOf(raw) {
|
|
1739
|
+
let path = raw.trim();
|
|
1740
|
+
const pipe = path.indexOf("|");
|
|
1741
|
+
if (pipe !== -1) path = path.slice(0, pipe).trim();
|
|
1742
|
+
const at = path.indexOf("@");
|
|
1743
|
+
if (at !== -1) path = path.slice(0, at).trim();
|
|
1744
|
+
return path;
|
|
1745
|
+
}
|
|
1746
|
+
function getAvailableWildcardRank(html, offset, bindAttrName = "data-wcs") {
|
|
1747
|
+
const chain = getEnclosingForPaths(html, offset, bindAttrName);
|
|
1748
|
+
if (chain.length === 0) return 0;
|
|
1749
|
+
let resolved = "";
|
|
1750
|
+
for (const raw of chain) {
|
|
1751
|
+
const path = forPathOf(raw);
|
|
1752
|
+
if (path === ".") {
|
|
1753
|
+
resolved = `${resolved}.*`;
|
|
1754
|
+
} else if (path.startsWith(".")) {
|
|
1755
|
+
resolved = `${resolved}.*.${path.slice(1)}`;
|
|
1756
|
+
} else {
|
|
1757
|
+
resolved = path;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return countWildcardSegments(resolved) + 1;
|
|
1761
|
+
}
|
|
1010
1762
|
function getForTemplateDepthAt(html, openPos, offset, bindAttrName) {
|
|
1011
1763
|
const tagEnd = html.indexOf(">", openPos);
|
|
1012
1764
|
if (tagEnd === -1 || tagEnd >= offset) return 0;
|
|
@@ -1037,8 +1789,8 @@ function getForTemplateDepthAt(html, openPos, offset, bindAttrName) {
|
|
|
1037
1789
|
}
|
|
1038
1790
|
|
|
1039
1791
|
// src/core/messages.ts
|
|
1040
|
-
function resolveLocale(
|
|
1041
|
-
if (
|
|
1792
|
+
function resolveLocale(locale3) {
|
|
1793
|
+
if (locale3 === void 0 || locale3 === "" || /^ja\b|^ja[-_]/i.test(locale3) || locale3.toLowerCase() === "ja") return "ja";
|
|
1042
1794
|
return "en";
|
|
1043
1795
|
}
|
|
1044
1796
|
var JA_EXPECTED_LABEL = {
|
|
@@ -1060,6 +1812,10 @@ var ja = {
|
|
|
1060
1812
|
omittedPathOutsideFor: (p) => `\u7701\u7565\u30D1\u30B9 "${p}" \u306F <template for> \u306E\u5916\u5074\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`,
|
|
1061
1813
|
loopIndexOutsideFor: (p) => `\u30EB\u30FC\u30D7\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 "${p}" \u306F <template for> \u306E\u5916\u5074\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`,
|
|
1062
1814
|
resolvedPathInUi: (p) => `\u89E3\u6C7A\u6E08\u307F\u30D1\u30B9 "${p}" \u306F UI \u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D1\u30BF\u30FC\u30F3\u30D1\u30B9\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
1815
|
+
indexArity: (api, p, req, wc, actual) => `${api}("${p}") \u306E\u6DFB\u5B57\u306F${req === "exact" ? `\u3061\u3087\u3046\u3069 ${wc} \u500B` : `${wc} \u500B\u4EE5\u4E0B`}\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u30D1\u30B9\u4E2D\u306E "*" \u306F ${wc} \u500B\uFF09\u3002${actual} \u500B\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059`,
|
|
1816
|
+
wildcardRank: (subject, needed, available) => `${subject} \u306F ${needed} \u6BB5\u306E\u30EB\u30FC\u30D7\u304C\u5FC5\u8981\u3067\u3059\u304C\u3001\u73FE\u5728\u306E\u30B9\u30B3\u30FC\u30D7\u306F ${available} \u6BB5\u3067\u3059`,
|
|
1817
|
+
getterCycle: (cycle) => `\u30D1\u30B9 getter \u304C\u5FAA\u74B0\u53C2\u7167\u3057\u3066\u3044\u307E\u3059: ${cycle}`,
|
|
1818
|
+
updatedCallbackUnbound: (p) => `$updatedCallback \u306F binding \u99C6\u52D5\u3067\u3059\u3002"${p}" \u306F\u3053\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u3069\u306E\u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0\u306B\u3082\u73FE\u308C\u306A\u3044\u305F\u3081\u3001\u3053\u306E\u5206\u5C90\u306F\u4E00\u5EA6\u3082\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002\u63CF\u753B\u306B\u4F9D\u5B58\u305B\u305A\u53CD\u5FDC\u3059\u308B\u306A\u3089 $watch \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044`,
|
|
1063
1819
|
handlerFilterNotAllowed: (prop) => `\u30A4\u30D9\u30F3\u30C8\u30CF\u30F3\u30C9\u30E9 "${prop}" \u306B\u30D5\u30A3\u30EB\u30BF\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`,
|
|
1064
1820
|
typeExpectation: (label, expected, resultType) => `"${label}" \u306B\u306F${JA_EXPECTED_LABEL[expected]}\u304C\u5FC5\u8981\u3067\u3059\uFF08\u73FE\u5728\u306E\u578B: ${resultType}\uFF09`,
|
|
1065
1821
|
filterUnknown: (n) => `\u30D5\u30A3\u30EB\u30BF "${n}" \u306F\u7D44\u307F\u8FBC\u307F\u30D5\u30A3\u30EB\u30BF\u306B\u5B58\u5728\u3057\u307E\u305B\u3093`,
|
|
@@ -1110,6 +1866,10 @@ var en = {
|
|
|
1110
1866
|
omittedPathOutsideFor: (p) => `Shorthand path "${p}" cannot be used outside a <template for>`,
|
|
1111
1867
|
loopIndexOutsideFor: (p) => `Loop index "${p}" cannot be used outside a <template for>`,
|
|
1112
1868
|
resolvedPathInUi: (p) => `Resolved path "${p}" cannot be used in a UI binding. Use a pattern path instead`,
|
|
1869
|
+
indexArity: (api, p, req, wc, actual) => `${api}("${p}") requires ${req === "exact" ? "exactly" : "at most"} ${wc} index(es) ("*" appears ${wc} time(s) in the path) but got ${actual}`,
|
|
1870
|
+
wildcardRank: (subject, needed, available) => `${subject} needs ${needed} enclosing loop level(s) but the current scope provides ${available}`,
|
|
1871
|
+
getterCycle: (cycle) => `Path getters form a dependency cycle: ${cycle}`,
|
|
1872
|
+
updatedCallbackUnbound: (p) => `$updatedCallback is binding-driven. "${p}" is not bound anywhere in this document, so this branch never runs. Use $watch to react without depending on what is rendered`,
|
|
1113
1873
|
handlerFilterNotAllowed: (prop) => `Filters cannot be applied to event handler "${prop}"`,
|
|
1114
1874
|
typeExpectation: (label, expected, resultType) => `"${label}" requires ${EN_EXPECTED_LABEL[expected]} (current type: ${resultType})`,
|
|
1115
1875
|
filterUnknown: (n) => `Filter "${n}" is not a built-in filter`,
|
|
@@ -1142,15 +1902,15 @@ var en = {
|
|
|
1142
1902
|
signalsDualEntry: () => `Both @wcstack/signals and @wcstack/signals/dom are imported on this page. On a CDN each entry is a self-contained bundle, so the reactive core is duplicated and reactivity breaks at the seam \u2014 import everything from the single /dom entry`
|
|
1143
1903
|
};
|
|
1144
1904
|
var CATALOGS = { ja, en };
|
|
1145
|
-
function getMessages(
|
|
1146
|
-
return CATALOGS[resolveLocale(
|
|
1905
|
+
function getMessages(locale3) {
|
|
1906
|
+
return CATALOGS[resolveLocale(locale3)];
|
|
1147
1907
|
}
|
|
1148
1908
|
|
|
1149
1909
|
// src/service/bindingValidator.ts
|
|
1150
1910
|
var filterMap = new Map(BUILTIN_FILTERS.map((f) => [f.name, f]));
|
|
1151
|
-
function validateBindings(html, attrName, stateTagName = "wcs-state",
|
|
1911
|
+
function validateBindings(html, attrName, stateTagName = "wcs-state", locale3, fileReader) {
|
|
1152
1912
|
const diagnostics = [];
|
|
1153
|
-
const msgs = getMessages(
|
|
1913
|
+
const msgs = getMessages(locale3);
|
|
1154
1914
|
const statePaths = getStatePathsFromHtml(html, stateTagName, fileReader);
|
|
1155
1915
|
const pathsByState = /* @__PURE__ */ new Map();
|
|
1156
1916
|
for (const p of statePaths) {
|
|
@@ -1327,6 +2087,24 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale, fi
|
|
|
1327
2087
|
severity: "warning"
|
|
1328
2088
|
});
|
|
1329
2089
|
}
|
|
2090
|
+
if (insideFor && !pathTrimmed.startsWith(".") && !binding.includes("@")) {
|
|
2091
|
+
const indexMatch = /^\$(\d+)$/.exec(pathTrimmed);
|
|
2092
|
+
const needed = indexMatch !== null ? Number(indexMatch[1]) : pathTrimmed.includes("*") ? countWildcardSegments(pathTrimmed) : 0;
|
|
2093
|
+
if (needed > 0) {
|
|
2094
|
+
const available = getAvailableWildcardRank(html, attr.valueStart, attrName);
|
|
2095
|
+
if (available > 0 && needed > available) {
|
|
2096
|
+
const pathOffset = binding.indexOf(parsed.path);
|
|
2097
|
+
const pathStart = bindingStart + pathOffset;
|
|
2098
|
+
diagnostics.push({
|
|
2099
|
+
code: WcsDiagnosticCode.WildcardRank,
|
|
2100
|
+
start: pathStart,
|
|
2101
|
+
end: pathStart + pathTrimmed.length,
|
|
2102
|
+
message: msgs.wildcardRank(`"${pathTrimmed}"`, needed, available),
|
|
2103
|
+
severity: "warning"
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
1330
2108
|
if (/\.\d+\.|\.\d+$/.test(pathTrimmed)) {
|
|
1331
2109
|
const pathOffset = binding.indexOf(parsed.path);
|
|
1332
2110
|
const pathStart = bindingStart + pathOffset;
|
|
@@ -1670,8 +2448,8 @@ function isLiteral(value) {
|
|
|
1670
2448
|
}
|
|
1671
2449
|
|
|
1672
2450
|
// src/service/stateTypeValidator.ts
|
|
1673
|
-
function validateStateTypes(html, stateTagName = "wcs-state",
|
|
1674
|
-
const msgs = getMessages(
|
|
2451
|
+
function validateStateTypes(html, stateTagName = "wcs-state", locale3) {
|
|
2452
|
+
const msgs = getMessages(locale3);
|
|
1675
2453
|
const blocks = parseWcsScriptBlocks(html, stateTagName);
|
|
1676
2454
|
const diagnostics = [];
|
|
1677
2455
|
for (const block of blocks) {
|
|
@@ -1798,8 +2576,8 @@ function isApiRoot(root) {
|
|
|
1798
2576
|
// src/service/nestedAssignValidator.ts
|
|
1799
2577
|
var NESTED_ASSIGN = new RegExp(`${ROOT_DOT}(${CHAIN_ONE_PLUS})${ASSIGN_TAIL}`, "g");
|
|
1800
2578
|
var PRE_NESTED_INCDEC = new RegExp(`${PRE_INCDEC}${ROOT_DOT}(${CHAIN_ONE_PLUS})`, "g");
|
|
1801
|
-
function validateNestedAssigns(html, stateTagName = "wcs-state",
|
|
1802
|
-
const msgs = getMessages(
|
|
2579
|
+
function validateNestedAssigns(html, stateTagName = "wcs-state", locale3) {
|
|
2580
|
+
const msgs = getMessages(locale3);
|
|
1803
2581
|
const blocks = parseWcsScriptBlocks(html, stateTagName);
|
|
1804
2582
|
const diagnostics = [];
|
|
1805
2583
|
for (const block of blocks) {
|
|
@@ -1821,7 +2599,7 @@ function findNestedAssigns(script, baseOffset, msgs, out) {
|
|
|
1821
2599
|
start,
|
|
1822
2600
|
end: start + full.length,
|
|
1823
2601
|
message: msgs.nestedAssign(suggestedPath),
|
|
1824
|
-
severity: "
|
|
2602
|
+
severity: "error"
|
|
1825
2603
|
});
|
|
1826
2604
|
}
|
|
1827
2605
|
}
|
|
@@ -1850,8 +2628,8 @@ var PRE_BRACKET_INDEX = new RegExp(`${PRE_INCDEC}${ROOT_BRACKET}(${BRACKETS_ONLY
|
|
|
1850
2628
|
function toAccessor(path) {
|
|
1851
2629
|
return /^[A-Za-z_]\w*$/.test(path) ? `this.${path}` : `this["${path}"]`;
|
|
1852
2630
|
}
|
|
1853
|
-
function validateArrayMutations(html, stateTagName = "wcs-state",
|
|
1854
|
-
const msgs = getMessages(
|
|
2631
|
+
function validateArrayMutations(html, stateTagName = "wcs-state", locale3) {
|
|
2632
|
+
const msgs = getMessages(locale3);
|
|
1855
2633
|
const blocks = parseWcsScriptBlocks(html, stateTagName);
|
|
1856
2634
|
const diagnostics = [];
|
|
1857
2635
|
for (const block of blocks) {
|
|
@@ -1874,7 +2652,7 @@ function findDestructiveCalls(script, baseOffset, msgs, out) {
|
|
|
1874
2652
|
start,
|
|
1875
2653
|
end: start + full.length,
|
|
1876
2654
|
message: msgs.arrayMutation(method, ALTERNATIVES[method](toAccessor(statePath))),
|
|
1877
|
-
severity: "
|
|
2655
|
+
severity: "error",
|
|
1878
2656
|
statePath
|
|
1879
2657
|
});
|
|
1880
2658
|
}
|
|
@@ -1894,7 +2672,7 @@ function findIndexAssigns(script, baseOffset, msgs, out) {
|
|
|
1894
2672
|
start,
|
|
1895
2673
|
end: start + full.length,
|
|
1896
2674
|
message: msgs.arrayIndexAssign(suggestedPath),
|
|
1897
|
-
severity: "
|
|
2675
|
+
severity: "error",
|
|
1898
2676
|
statePath: suggestedPath
|
|
1899
2677
|
});
|
|
1900
2678
|
}
|
|
@@ -1961,9 +2739,9 @@ function isInsideTag(html, offset, tagName) {
|
|
|
1961
2739
|
}
|
|
1962
2740
|
|
|
1963
2741
|
// src/service/templateSyntaxValidator.ts
|
|
1964
|
-
function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs",
|
|
2742
|
+
function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", locale3, fileReader) {
|
|
1965
2743
|
const diagnostics = [];
|
|
1966
|
-
const msgs = getMessages(
|
|
2744
|
+
const msgs = getMessages(locale3);
|
|
1967
2745
|
const allPaths = getStatePathsFromHtml(html, stateTagName, fileReader);
|
|
1968
2746
|
if (allPaths.length === 0) return diagnostics;
|
|
1969
2747
|
const defaultPaths = allPaths.filter((p) => p.stateName === "default");
|
|
@@ -2015,6 +2793,22 @@ function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", l
|
|
|
2015
2793
|
severity: "warning"
|
|
2016
2794
|
});
|
|
2017
2795
|
}
|
|
2796
|
+
if (insideFor && !pathPart.startsWith(".") && !pathPart.includes("@")) {
|
|
2797
|
+
const indexMatch = /^\$(\d+)$/.exec(pathPart);
|
|
2798
|
+
const needed = indexMatch !== null ? Number(indexMatch[1]) : pathPart.includes("*") ? countWildcardSegments(pathPart) : 0;
|
|
2799
|
+
if (needed > 0) {
|
|
2800
|
+
const available = getAvailableWildcardRank(html, item.matchStart, bindAttrName);
|
|
2801
|
+
if (available > 0 && needed > available) {
|
|
2802
|
+
diagnostics.push({
|
|
2803
|
+
code: WcsDiagnosticCode.WildcardRank,
|
|
2804
|
+
start: item.exprStart,
|
|
2805
|
+
end: item.exprStart + pathPart.length,
|
|
2806
|
+
message: msgs.wildcardRank(`"${pathPart}"`, needed, available),
|
|
2807
|
+
severity: "warning"
|
|
2808
|
+
});
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2018
2812
|
if (/\.\d+\.|\.\d+$/.test(pathPart)) {
|
|
2019
2813
|
diagnostics.push({
|
|
2020
2814
|
code: WcsDiagnosticCode.TemplateSyntax,
|
|
@@ -3314,9 +4108,9 @@ var DOM_COMMON_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
3314
4108
|
]);
|
|
3315
4109
|
var STRUCTURAL_DIRECTIVES2 = /* @__PURE__ */ new Set(["for", "if", "elseif", "else"]);
|
|
3316
4110
|
var EMPTYISH_SEEDS = /* @__PURE__ */ new Set(["''", '""', "``", "null", "[]", "{}"]);
|
|
3317
|
-
function validateIoNodes(html, bindAttribute = "data-wcs", stateTagName = "wcs-state",
|
|
4111
|
+
function validateIoNodes(html, bindAttribute = "data-wcs", stateTagName = "wcs-state", locale3, fileReader) {
|
|
3318
4112
|
const diagnostics = [];
|
|
3319
|
-
const msgs = getMessages(
|
|
4113
|
+
const msgs = getMessages(locale3);
|
|
3320
4114
|
const occurrences = findBuiltinTagOccurrences(html);
|
|
3321
4115
|
if (occurrences.length === 0) return diagnostics;
|
|
3322
4116
|
let statePaths = null;
|
|
@@ -3525,9 +4319,9 @@ function hasBooleanAttribute(attrsText, attrName) {
|
|
|
3525
4319
|
}
|
|
3526
4320
|
|
|
3527
4321
|
// src/service/documentEnvValidator.ts
|
|
3528
|
-
function validateDocumentEnv(html,
|
|
4322
|
+
function validateDocumentEnv(html, locale3) {
|
|
3529
4323
|
const diagnostics = [];
|
|
3530
|
-
const msgs = getMessages(
|
|
4324
|
+
const msgs = getMessages(locale3);
|
|
3531
4325
|
const scanText = blankHtmlComments(html);
|
|
3532
4326
|
const autos = findWcstackAutoScripts(scanText);
|
|
3533
4327
|
const stateIndex = autos.findIndex((a) => a.pkg === "state");
|
|
@@ -3637,9 +4431,9 @@ function blankJsComments(code) {
|
|
|
3637
4431
|
}
|
|
3638
4432
|
|
|
3639
4433
|
// src/service/watchDeclarationValidator.ts
|
|
3640
|
-
var
|
|
3641
|
-
function validateWatchDeclarations(html, stateTagName = "wcs-state",
|
|
3642
|
-
const msgs = getMessages(
|
|
4434
|
+
var STATE_NAME_SEPARATOR2 = "@";
|
|
4435
|
+
function validateWatchDeclarations(html, stateTagName = "wcs-state", locale3) {
|
|
4436
|
+
const msgs = getMessages(locale3);
|
|
3643
4437
|
const out = [];
|
|
3644
4438
|
for (const block of parseWcsScriptBlocks(html, stateTagName)) {
|
|
3645
4439
|
const nonObject = findNonObjectWatch(block.content);
|
|
@@ -3673,7 +4467,7 @@ function validateWatchDeclarations(html, stateTagName = "wcs-state", locale) {
|
|
|
3673
4467
|
function validateEntry(entry, pathSet, msgs) {
|
|
3674
4468
|
const { key } = entry;
|
|
3675
4469
|
const invalid = (message) => ({ code: WcsDiagnosticCode.WatchDeclarationInvalid, message, severity: "error" });
|
|
3676
|
-
if (key.includes(
|
|
4470
|
+
if (key.includes(STATE_NAME_SEPARATOR2)) {
|
|
3677
4471
|
return invalid(msgs.watchKeyCrossState(key));
|
|
3678
4472
|
}
|
|
3679
4473
|
if (key.startsWith("$")) {
|
|
@@ -3695,43 +4489,1504 @@ function validateEntry(entry, pathSet, msgs) {
|
|
|
3695
4489
|
return null;
|
|
3696
4490
|
}
|
|
3697
4491
|
|
|
3698
|
-
//
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
4492
|
+
// ../state/dist/parser.esm.js
|
|
4493
|
+
var DELIMITER2 = ".";
|
|
4494
|
+
var WILDCARD2 = "*";
|
|
4495
|
+
var MAX_WILDCARD_DEPTH2 = 128;
|
|
4496
|
+
var BINDING_SEPARATOR2 = ";";
|
|
4497
|
+
var PROP_VALUE_SEPARATOR2 = ":";
|
|
4498
|
+
var MODIFIER_SEPARATOR2 = "#";
|
|
4499
|
+
var STATE_NAME_SEPARATOR3 = "@";
|
|
4500
|
+
var FILTER_SEPARATOR2 = "|";
|
|
4501
|
+
var ELSE_KEYWORD2 = "else";
|
|
4502
|
+
var SPREAD_PROP2 = "...";
|
|
4503
|
+
var EVENT_PROP_PREFIX2 = "on";
|
|
4504
|
+
var EVENT_TOKEN_NAMESPACE2 = "eventToken";
|
|
4505
|
+
var INDEX_PARAM_PREFIX2 = "$";
|
|
4506
|
+
var tmpIndexByIndexName2 = {};
|
|
4507
|
+
for (let i = 0; i < MAX_WILDCARD_DEPTH2; i++) {
|
|
4508
|
+
tmpIndexByIndexName2[`${INDEX_PARAM_PREFIX2}${i + 1}`] = i;
|
|
4509
|
+
}
|
|
4510
|
+
Object.freeze(tmpIndexByIndexName2);
|
|
4511
|
+
var _cache = /* @__PURE__ */ new Map();
|
|
4512
|
+
function clearPathInfoCacheForTooling() {
|
|
4513
|
+
_cache.clear();
|
|
4514
|
+
}
|
|
4515
|
+
var id = 0;
|
|
4516
|
+
function getPathInfo(path) {
|
|
4517
|
+
let pathInfo = _cache.get(path);
|
|
4518
|
+
if (typeof pathInfo !== "undefined") {
|
|
4519
|
+
return pathInfo;
|
|
4520
|
+
}
|
|
4521
|
+
pathInfo = Object.freeze(new PathInfo(path));
|
|
4522
|
+
_cache.set(path, pathInfo);
|
|
4523
|
+
return pathInfo;
|
|
4524
|
+
}
|
|
4525
|
+
var PathInfo = class {
|
|
4526
|
+
id = ++id;
|
|
4527
|
+
path;
|
|
4528
|
+
segments;
|
|
4529
|
+
lastSegment;
|
|
4530
|
+
cumulativePaths;
|
|
4531
|
+
cumulativePathSet;
|
|
4532
|
+
cumulativePathInfos;
|
|
4533
|
+
cumulativePathInfoSet;
|
|
4534
|
+
parentPath;
|
|
4535
|
+
wildcardPaths;
|
|
4536
|
+
wildcardPathSet;
|
|
4537
|
+
indexByWildcardPath;
|
|
4538
|
+
wildcardPathInfos;
|
|
4539
|
+
wildcardPathInfoSet;
|
|
4540
|
+
wildcardParentPaths;
|
|
4541
|
+
wildcardParentPathSet;
|
|
4542
|
+
wildcardParentPathInfos;
|
|
4543
|
+
wildcardParentPathInfoSet;
|
|
4544
|
+
wildcardPositions;
|
|
4545
|
+
lastWildcardPath;
|
|
4546
|
+
lastWildcardInfo;
|
|
4547
|
+
wildcardCount;
|
|
4548
|
+
parentPathInfo;
|
|
4549
|
+
constructor(path) {
|
|
4550
|
+
const getPattern = (_path) => {
|
|
4551
|
+
return path === _path ? this : getPathInfo(_path);
|
|
4552
|
+
};
|
|
4553
|
+
const segments = path.split(".");
|
|
4554
|
+
const cumulativePaths = [];
|
|
4555
|
+
const cumulativePathInfos = [];
|
|
4556
|
+
const wildcardPaths = [];
|
|
4557
|
+
const indexByWildcardPath = {};
|
|
4558
|
+
const wildcardPathInfos = [];
|
|
4559
|
+
const wildcardParentPaths = [];
|
|
4560
|
+
const wildcardParentPathInfos = [];
|
|
4561
|
+
const wildcardPositions = [];
|
|
4562
|
+
let currentPatternPath = "", prevPatternPath = "";
|
|
4563
|
+
let wildcardCount = 0;
|
|
4564
|
+
for (let i = 0; i < segments.length; i++) {
|
|
4565
|
+
currentPatternPath += segments[i];
|
|
4566
|
+
if (segments[i] === WILDCARD2) {
|
|
4567
|
+
wildcardPaths.push(currentPatternPath);
|
|
4568
|
+
indexByWildcardPath[currentPatternPath] = wildcardCount;
|
|
4569
|
+
wildcardPathInfos.push(getPattern(currentPatternPath));
|
|
4570
|
+
wildcardParentPaths.push(prevPatternPath);
|
|
4571
|
+
wildcardParentPathInfos.push(getPattern(prevPatternPath));
|
|
4572
|
+
wildcardPositions.push(i);
|
|
4573
|
+
wildcardCount++;
|
|
4574
|
+
}
|
|
4575
|
+
cumulativePaths.push(currentPatternPath);
|
|
4576
|
+
cumulativePathInfos.push(getPattern(currentPatternPath));
|
|
4577
|
+
prevPatternPath = currentPatternPath;
|
|
4578
|
+
currentPatternPath += ".";
|
|
4579
|
+
}
|
|
4580
|
+
const lastWildcardPath = wildcardPaths.length > 0 ? wildcardPaths[wildcardPaths.length - 1] : null;
|
|
4581
|
+
const parentPath = cumulativePaths.length > 1 ? cumulativePaths[cumulativePaths.length - 2] : null;
|
|
4582
|
+
this.path = path;
|
|
4583
|
+
this.segments = segments;
|
|
4584
|
+
this.lastSegment = segments[segments.length - 1];
|
|
4585
|
+
this.cumulativePaths = cumulativePaths;
|
|
4586
|
+
this.cumulativePathSet = new Set(cumulativePaths);
|
|
4587
|
+
this.cumulativePathInfos = cumulativePathInfos;
|
|
4588
|
+
this.cumulativePathInfoSet = new Set(cumulativePathInfos);
|
|
4589
|
+
this.wildcardPaths = wildcardPaths;
|
|
4590
|
+
this.wildcardPathSet = new Set(wildcardPaths);
|
|
4591
|
+
this.indexByWildcardPath = indexByWildcardPath;
|
|
4592
|
+
this.wildcardPathInfos = wildcardPathInfos;
|
|
4593
|
+
this.wildcardPathInfoSet = new Set(wildcardPathInfos);
|
|
4594
|
+
this.wildcardParentPaths = wildcardParentPaths;
|
|
4595
|
+
this.wildcardParentPathSet = new Set(wildcardParentPaths);
|
|
4596
|
+
this.wildcardParentPathInfos = wildcardParentPathInfos;
|
|
4597
|
+
this.wildcardParentPathInfoSet = new Set(wildcardParentPathInfos);
|
|
4598
|
+
this.wildcardPositions = wildcardPositions;
|
|
4599
|
+
this.lastWildcardPath = lastWildcardPath;
|
|
4600
|
+
this.lastWildcardInfo = lastWildcardPath ? getPattern(lastWildcardPath) : null;
|
|
4601
|
+
this.parentPath = parentPath;
|
|
4602
|
+
this.parentPathInfo = parentPath ? getPattern(parentPath) : null;
|
|
4603
|
+
this.wildcardCount = wildcardCount;
|
|
3713
4604
|
}
|
|
3714
|
-
|
|
3715
|
-
|
|
4605
|
+
};
|
|
4606
|
+
function editDistance2(a, b, max) {
|
|
4607
|
+
if (Math.abs(a.length - b.length) > max) {
|
|
4608
|
+
return max + 1;
|
|
3716
4609
|
}
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
4610
|
+
const prev = new Array(b.length + 1);
|
|
4611
|
+
const curr = new Array(b.length + 1);
|
|
4612
|
+
for (let j = 0; j <= b.length; j++) {
|
|
4613
|
+
prev[j] = j;
|
|
4614
|
+
}
|
|
4615
|
+
for (let i = 1; i <= a.length; i++) {
|
|
4616
|
+
curr[0] = i;
|
|
4617
|
+
for (let j = 1; j <= b.length; j++) {
|
|
4618
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
4619
|
+
curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
|
|
4620
|
+
}
|
|
4621
|
+
for (let j = 0; j <= b.length; j++) {
|
|
4622
|
+
prev[j] = curr[j];
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
return prev[b.length];
|
|
4626
|
+
}
|
|
4627
|
+
function didYouMean(input, candidates) {
|
|
4628
|
+
if (input.length === 0) {
|
|
4629
|
+
return "";
|
|
4630
|
+
}
|
|
4631
|
+
const folded = input.toLowerCase();
|
|
4632
|
+
let best = null;
|
|
4633
|
+
let bestDistance = 3;
|
|
4634
|
+
for (const candidate of candidates) {
|
|
4635
|
+
const distance = editDistance2(folded, candidate.toLowerCase(), 2);
|
|
4636
|
+
if (distance < bestDistance) {
|
|
4637
|
+
best = candidate;
|
|
4638
|
+
bestDistance = distance;
|
|
4639
|
+
}
|
|
4640
|
+
}
|
|
4641
|
+
return best !== null ? ` Did you mean "${best}"?` : "";
|
|
4642
|
+
}
|
|
4643
|
+
var LINT_HINT = " Validate statically: npx @wcstack/lint <file>.";
|
|
4644
|
+
function raiseError2(message) {
|
|
4645
|
+
throw new Error(`[@wcstack/state] ${message}`);
|
|
4646
|
+
}
|
|
4647
|
+
var STRUCTURAL_BINDING_TYPE_SET2 = /* @__PURE__ */ new Set([
|
|
4648
|
+
"if",
|
|
4649
|
+
"elseif",
|
|
4650
|
+
"else",
|
|
4651
|
+
"for"
|
|
4652
|
+
]);
|
|
4653
|
+
var _config2 = {
|
|
4654
|
+
locale: "en"
|
|
4655
|
+
};
|
|
4656
|
+
var config2 = _config2;
|
|
4657
|
+
function optionsRequired2(fnName) {
|
|
4658
|
+
raiseError2(`filter ${fnName} requires at least one option`);
|
|
4659
|
+
}
|
|
4660
|
+
function optionMustBeNumber2(fnName) {
|
|
4661
|
+
raiseError2(`filter ${fnName} requires a number as option`);
|
|
4662
|
+
}
|
|
4663
|
+
function valueMustBeNumber2(fnName) {
|
|
4664
|
+
raiseError2(`filter ${fnName} requires a number value`);
|
|
4665
|
+
}
|
|
4666
|
+
function valueMustBeBoolean2(fnName) {
|
|
4667
|
+
raiseError2(`filter ${fnName} requires a boolean value`);
|
|
4668
|
+
}
|
|
4669
|
+
function valueMustBeDate2(fnName) {
|
|
4670
|
+
raiseError2(`filter ${fnName} requires a date value`);
|
|
4671
|
+
}
|
|
4672
|
+
function valueMustBeArray2(fnName) {
|
|
4673
|
+
raiseError2(`filter ${fnName} requires an array value`);
|
|
4674
|
+
}
|
|
4675
|
+
function validateNumberString2(value) {
|
|
4676
|
+
if (!value || isNaN(Number(value))) {
|
|
4677
|
+
return false;
|
|
4678
|
+
}
|
|
4679
|
+
return true;
|
|
4680
|
+
}
|
|
4681
|
+
var eq2 = (options) => {
|
|
4682
|
+
const opt = options?.[0] ?? optionsRequired2("eq");
|
|
4683
|
+
return (value) => {
|
|
4684
|
+
if (typeof value === "number") {
|
|
4685
|
+
if (!validateNumberString2(opt)) {
|
|
4686
|
+
optionMustBeNumber2("eq");
|
|
4687
|
+
}
|
|
4688
|
+
return value === Number(opt);
|
|
4689
|
+
}
|
|
4690
|
+
if (typeof value === "string") {
|
|
4691
|
+
return value === opt;
|
|
4692
|
+
}
|
|
4693
|
+
return value === opt;
|
|
4694
|
+
};
|
|
4695
|
+
};
|
|
4696
|
+
var ne2 = (options) => {
|
|
4697
|
+
const opt = options?.[0] ?? optionsRequired2("ne");
|
|
4698
|
+
return (value) => {
|
|
4699
|
+
if (typeof value === "number") {
|
|
4700
|
+
if (!validateNumberString2(opt)) {
|
|
4701
|
+
optionMustBeNumber2("ne");
|
|
4702
|
+
}
|
|
4703
|
+
return value !== Number(opt);
|
|
4704
|
+
}
|
|
4705
|
+
if (typeof value === "string") {
|
|
4706
|
+
return value !== opt;
|
|
4707
|
+
}
|
|
4708
|
+
return value !== opt;
|
|
4709
|
+
};
|
|
4710
|
+
};
|
|
4711
|
+
var not2 = (_options) => {
|
|
4712
|
+
return (value) => {
|
|
4713
|
+
if (typeof value !== "boolean") {
|
|
4714
|
+
valueMustBeBoolean2("not");
|
|
4715
|
+
}
|
|
4716
|
+
return !value;
|
|
4717
|
+
};
|
|
4718
|
+
};
|
|
4719
|
+
var lt2 = (options) => {
|
|
4720
|
+
const opt = options?.[0] ?? optionsRequired2("lt");
|
|
4721
|
+
if (!validateNumberString2(opt)) {
|
|
4722
|
+
optionMustBeNumber2("lt");
|
|
4723
|
+
}
|
|
4724
|
+
return (value) => {
|
|
4725
|
+
if (typeof value !== "number") {
|
|
4726
|
+
valueMustBeNumber2("lt");
|
|
4727
|
+
}
|
|
4728
|
+
return value < Number(opt);
|
|
4729
|
+
};
|
|
4730
|
+
};
|
|
4731
|
+
var le2 = (options) => {
|
|
4732
|
+
const opt = options?.[0] ?? optionsRequired2("le");
|
|
4733
|
+
if (!validateNumberString2(opt)) {
|
|
4734
|
+
optionMustBeNumber2("le");
|
|
4735
|
+
}
|
|
4736
|
+
return (value) => {
|
|
4737
|
+
if (typeof value !== "number") {
|
|
4738
|
+
valueMustBeNumber2("le");
|
|
4739
|
+
}
|
|
4740
|
+
return value <= Number(opt);
|
|
4741
|
+
};
|
|
4742
|
+
};
|
|
4743
|
+
var gt2 = (options) => {
|
|
4744
|
+
const opt = options?.[0] ?? optionsRequired2("gt");
|
|
4745
|
+
if (!validateNumberString2(opt)) {
|
|
4746
|
+
optionMustBeNumber2("gt");
|
|
4747
|
+
}
|
|
4748
|
+
return (value) => {
|
|
4749
|
+
if (typeof value !== "number") {
|
|
4750
|
+
valueMustBeNumber2("gt");
|
|
4751
|
+
}
|
|
4752
|
+
return value > Number(opt);
|
|
4753
|
+
};
|
|
4754
|
+
};
|
|
4755
|
+
var ge2 = (options) => {
|
|
4756
|
+
const opt = options?.[0] ?? optionsRequired2("ge");
|
|
4757
|
+
if (!validateNumberString2(opt)) {
|
|
4758
|
+
optionMustBeNumber2("ge");
|
|
4759
|
+
}
|
|
4760
|
+
return (value) => {
|
|
4761
|
+
if (typeof value !== "number") {
|
|
4762
|
+
valueMustBeNumber2("ge");
|
|
4763
|
+
}
|
|
4764
|
+
return value >= Number(opt);
|
|
4765
|
+
};
|
|
4766
|
+
};
|
|
4767
|
+
var inc2 = (options) => {
|
|
4768
|
+
const opt = options?.[0] ?? optionsRequired2("inc");
|
|
4769
|
+
if (!validateNumberString2(opt)) {
|
|
4770
|
+
optionMustBeNumber2("inc");
|
|
4771
|
+
}
|
|
4772
|
+
return (value) => {
|
|
4773
|
+
if (typeof value !== "number") {
|
|
4774
|
+
valueMustBeNumber2("inc");
|
|
4775
|
+
}
|
|
4776
|
+
return value + Number(opt);
|
|
4777
|
+
};
|
|
4778
|
+
};
|
|
4779
|
+
var dec2 = (options) => {
|
|
4780
|
+
const opt = options?.[0] ?? optionsRequired2("dec");
|
|
4781
|
+
if (!validateNumberString2(opt)) {
|
|
4782
|
+
optionMustBeNumber2("dec");
|
|
4783
|
+
}
|
|
4784
|
+
return (value) => {
|
|
4785
|
+
if (typeof value !== "number") {
|
|
4786
|
+
valueMustBeNumber2("dec");
|
|
4787
|
+
}
|
|
4788
|
+
return value - Number(opt);
|
|
4789
|
+
};
|
|
4790
|
+
};
|
|
4791
|
+
var mul2 = (options) => {
|
|
4792
|
+
const opt = options?.[0] ?? optionsRequired2("mul");
|
|
4793
|
+
if (!validateNumberString2(opt)) {
|
|
4794
|
+
optionMustBeNumber2("mul");
|
|
4795
|
+
}
|
|
4796
|
+
return (value) => {
|
|
4797
|
+
if (typeof value !== "number") {
|
|
4798
|
+
valueMustBeNumber2("mul");
|
|
4799
|
+
}
|
|
4800
|
+
return value * Number(opt);
|
|
4801
|
+
};
|
|
4802
|
+
};
|
|
4803
|
+
var div2 = (options) => {
|
|
4804
|
+
const opt = options?.[0] ?? optionsRequired2("div");
|
|
4805
|
+
if (!validateNumberString2(opt)) {
|
|
4806
|
+
optionMustBeNumber2("div");
|
|
4807
|
+
}
|
|
4808
|
+
return (value) => {
|
|
4809
|
+
if (typeof value !== "number") {
|
|
4810
|
+
valueMustBeNumber2("div");
|
|
4811
|
+
}
|
|
4812
|
+
return value / Number(opt);
|
|
4813
|
+
};
|
|
4814
|
+
};
|
|
4815
|
+
var mod2 = (options) => {
|
|
4816
|
+
const opt = options?.[0] ?? optionsRequired2("mod");
|
|
4817
|
+
if (!validateNumberString2(opt)) {
|
|
4818
|
+
optionMustBeNumber2("mod");
|
|
4819
|
+
}
|
|
4820
|
+
return (value) => {
|
|
4821
|
+
if (typeof value !== "number") {
|
|
4822
|
+
valueMustBeNumber2("mod");
|
|
4823
|
+
}
|
|
4824
|
+
return value % Number(opt);
|
|
4825
|
+
};
|
|
4826
|
+
};
|
|
4827
|
+
var abs2 = (_options) => {
|
|
4828
|
+
return (value) => {
|
|
4829
|
+
if (typeof value !== "number") {
|
|
4830
|
+
valueMustBeNumber2("abs");
|
|
4831
|
+
}
|
|
4832
|
+
return Math.abs(value);
|
|
4833
|
+
};
|
|
4834
|
+
};
|
|
4835
|
+
var clamp2 = (options) => {
|
|
4836
|
+
const opt1 = options?.[0] ?? optionsRequired2("clamp");
|
|
4837
|
+
if (!validateNumberString2(opt1)) {
|
|
4838
|
+
optionMustBeNumber2("clamp");
|
|
4839
|
+
}
|
|
4840
|
+
const opt2 = options?.[1] ?? optionsRequired2("clamp");
|
|
4841
|
+
if (!validateNumberString2(opt2)) {
|
|
4842
|
+
optionMustBeNumber2("clamp");
|
|
4843
|
+
}
|
|
4844
|
+
const min = Number(opt1);
|
|
4845
|
+
const max = Number(opt2);
|
|
4846
|
+
return (value) => {
|
|
4847
|
+
if (typeof value !== "number") {
|
|
4848
|
+
valueMustBeNumber2("clamp");
|
|
4849
|
+
}
|
|
4850
|
+
return Math.min(Math.max(value, min), max);
|
|
4851
|
+
};
|
|
4852
|
+
};
|
|
4853
|
+
var fix2 = (options) => {
|
|
4854
|
+
const opt = options?.[0] ?? "0";
|
|
4855
|
+
if (!validateNumberString2(opt)) {
|
|
4856
|
+
optionMustBeNumber2("fix");
|
|
4857
|
+
}
|
|
4858
|
+
return (value) => {
|
|
4859
|
+
if (typeof value !== "number") {
|
|
4860
|
+
valueMustBeNumber2("fix");
|
|
4861
|
+
}
|
|
4862
|
+
return value.toFixed(Number(opt));
|
|
4863
|
+
};
|
|
4864
|
+
};
|
|
4865
|
+
var locale2 = (options) => {
|
|
4866
|
+
const opt = options?.[0] ?? config2.locale;
|
|
4867
|
+
return (value) => {
|
|
4868
|
+
if (typeof value !== "number") {
|
|
4869
|
+
valueMustBeNumber2("locale");
|
|
4870
|
+
}
|
|
4871
|
+
return value.toLocaleString(opt);
|
|
4872
|
+
};
|
|
4873
|
+
};
|
|
4874
|
+
var uc2 = (_options) => {
|
|
4875
|
+
return (value) => {
|
|
4876
|
+
return String(value).toUpperCase();
|
|
4877
|
+
};
|
|
4878
|
+
};
|
|
4879
|
+
var lc2 = (_options) => {
|
|
4880
|
+
return (value) => {
|
|
4881
|
+
return String(value).toLowerCase();
|
|
4882
|
+
};
|
|
4883
|
+
};
|
|
4884
|
+
var cap2 = (_options) => {
|
|
4885
|
+
return (value) => {
|
|
4886
|
+
const v = String(value);
|
|
4887
|
+
if (v.length === 0) {
|
|
4888
|
+
return v;
|
|
4889
|
+
}
|
|
4890
|
+
if (v.length === 1) {
|
|
4891
|
+
return v.toUpperCase();
|
|
4892
|
+
}
|
|
4893
|
+
return v.charAt(0).toUpperCase() + v.slice(1);
|
|
4894
|
+
};
|
|
4895
|
+
};
|
|
4896
|
+
var trim2 = (_options) => {
|
|
4897
|
+
return (value) => {
|
|
4898
|
+
return String(value).trim();
|
|
4899
|
+
};
|
|
4900
|
+
};
|
|
4901
|
+
var slice2 = (options) => {
|
|
4902
|
+
const numberedOpts = [];
|
|
4903
|
+
const opt1 = options?.[0] ?? optionsRequired2("slice");
|
|
4904
|
+
if (!validateNumberString2(opt1)) {
|
|
4905
|
+
optionMustBeNumber2("slice");
|
|
4906
|
+
}
|
|
4907
|
+
numberedOpts.push(Number(opt1));
|
|
4908
|
+
const opt2 = options?.[1];
|
|
4909
|
+
if (typeof opt2 !== "undefined") {
|
|
4910
|
+
if (!validateNumberString2(opt2)) {
|
|
4911
|
+
optionMustBeNumber2("slice");
|
|
4912
|
+
}
|
|
4913
|
+
numberedOpts.push(Number(opt2));
|
|
4914
|
+
}
|
|
4915
|
+
return (value) => {
|
|
4916
|
+
return String(value).slice(...numberedOpts);
|
|
4917
|
+
};
|
|
4918
|
+
};
|
|
4919
|
+
var substr2 = (options) => {
|
|
4920
|
+
const opt1 = options?.[0] ?? optionsRequired2("substr");
|
|
4921
|
+
if (!validateNumberString2(opt1)) {
|
|
4922
|
+
optionMustBeNumber2("substr");
|
|
4923
|
+
}
|
|
4924
|
+
const opt2 = options?.[1] ?? optionsRequired2("substr");
|
|
4925
|
+
if (!validateNumberString2(opt2)) {
|
|
4926
|
+
optionMustBeNumber2("substr");
|
|
4927
|
+
}
|
|
4928
|
+
return (value) => {
|
|
4929
|
+
return String(value).substr(Number(opt1), Number(opt2));
|
|
4930
|
+
};
|
|
4931
|
+
};
|
|
4932
|
+
var pad2 = (options) => {
|
|
4933
|
+
const opt1 = options?.[0] ?? optionsRequired2("pad");
|
|
4934
|
+
if (!validateNumberString2(opt1)) {
|
|
4935
|
+
optionMustBeNumber2("pad");
|
|
4936
|
+
}
|
|
4937
|
+
const opt2 = options?.[1] ?? "0";
|
|
4938
|
+
return (value) => {
|
|
4939
|
+
return String(value).padStart(Number(opt1), opt2);
|
|
4940
|
+
};
|
|
4941
|
+
};
|
|
4942
|
+
var rep2 = (options) => {
|
|
4943
|
+
const opt = options?.[0] ?? optionsRequired2("rep");
|
|
4944
|
+
if (!validateNumberString2(opt)) {
|
|
4945
|
+
optionMustBeNumber2("rep");
|
|
4946
|
+
}
|
|
4947
|
+
return (value) => {
|
|
4948
|
+
return String(value).repeat(Number(opt));
|
|
4949
|
+
};
|
|
4950
|
+
};
|
|
4951
|
+
var rev2 = (_options) => {
|
|
4952
|
+
return (value) => {
|
|
4953
|
+
return String(value).split("").reverse().join("");
|
|
4954
|
+
};
|
|
4955
|
+
};
|
|
4956
|
+
var int2 = (_options) => {
|
|
4957
|
+
return (value) => {
|
|
4958
|
+
return parseInt(String(value), 10);
|
|
4959
|
+
};
|
|
4960
|
+
};
|
|
4961
|
+
var float2 = (_options) => {
|
|
4962
|
+
return (value) => {
|
|
4963
|
+
return parseFloat(String(value));
|
|
4964
|
+
};
|
|
4965
|
+
};
|
|
4966
|
+
var round2 = (options) => {
|
|
4967
|
+
const opt = options?.[0] ?? "0";
|
|
4968
|
+
if (!validateNumberString2(opt)) {
|
|
4969
|
+
optionMustBeNumber2("round");
|
|
4970
|
+
}
|
|
4971
|
+
return (value) => {
|
|
4972
|
+
if (typeof value !== "number") {
|
|
4973
|
+
valueMustBeNumber2("round");
|
|
4974
|
+
}
|
|
4975
|
+
const optValue = Math.pow(10, Number(opt));
|
|
4976
|
+
return Math.round(value * optValue) / optValue;
|
|
4977
|
+
};
|
|
4978
|
+
};
|
|
4979
|
+
var floor2 = (options) => {
|
|
4980
|
+
const opt = options?.[0] ?? "0";
|
|
4981
|
+
if (!validateNumberString2(opt)) {
|
|
4982
|
+
optionMustBeNumber2("floor");
|
|
4983
|
+
}
|
|
4984
|
+
return (value) => {
|
|
4985
|
+
if (typeof value !== "number") {
|
|
4986
|
+
valueMustBeNumber2("floor");
|
|
4987
|
+
}
|
|
4988
|
+
const optValue = Math.pow(10, Number(opt));
|
|
4989
|
+
return Math.floor(value * optValue) / optValue;
|
|
4990
|
+
};
|
|
4991
|
+
};
|
|
4992
|
+
var ceil2 = (options) => {
|
|
4993
|
+
const opt = options?.[0] ?? "0";
|
|
4994
|
+
if (!validateNumberString2(opt)) {
|
|
4995
|
+
optionMustBeNumber2("ceil");
|
|
4996
|
+
}
|
|
4997
|
+
return (value) => {
|
|
4998
|
+
if (typeof value !== "number") {
|
|
4999
|
+
valueMustBeNumber2("ceil");
|
|
5000
|
+
}
|
|
5001
|
+
const optValue = Math.pow(10, Number(opt));
|
|
5002
|
+
return Math.ceil(value * optValue) / optValue;
|
|
5003
|
+
};
|
|
5004
|
+
};
|
|
5005
|
+
var percent2 = (options) => {
|
|
5006
|
+
const opt = options?.[0] ?? "0";
|
|
5007
|
+
if (!validateNumberString2(opt)) {
|
|
5008
|
+
optionMustBeNumber2("percent");
|
|
5009
|
+
}
|
|
5010
|
+
return (value) => {
|
|
5011
|
+
if (typeof value !== "number") {
|
|
5012
|
+
valueMustBeNumber2("percent");
|
|
5013
|
+
}
|
|
5014
|
+
return `${(value * 100).toFixed(Number(opt))}%`;
|
|
5015
|
+
};
|
|
5016
|
+
};
|
|
5017
|
+
var unit2 = (options) => {
|
|
5018
|
+
const opt = options?.[0] ?? optionsRequired2("unit");
|
|
5019
|
+
return (value) => {
|
|
5020
|
+
if (value === null || typeof value === "undefined") {
|
|
5021
|
+
return value;
|
|
5022
|
+
}
|
|
5023
|
+
return String(value) + opt;
|
|
5024
|
+
};
|
|
5025
|
+
};
|
|
5026
|
+
var join2 = (options) => {
|
|
5027
|
+
const opt = options?.[0] ?? ", ";
|
|
5028
|
+
return (value) => {
|
|
5029
|
+
if (!Array.isArray(value)) {
|
|
5030
|
+
valueMustBeArray2("join");
|
|
5031
|
+
}
|
|
5032
|
+
return value.join(opt);
|
|
5033
|
+
};
|
|
5034
|
+
};
|
|
5035
|
+
var truncate2 = (options) => {
|
|
5036
|
+
const opt1 = options?.[0] ?? optionsRequired2("truncate");
|
|
5037
|
+
if (!validateNumberString2(opt1)) {
|
|
5038
|
+
optionMustBeNumber2("truncate");
|
|
5039
|
+
}
|
|
5040
|
+
const maxLength = Number(opt1);
|
|
5041
|
+
const suffix = options?.[1] ?? "\u2026";
|
|
5042
|
+
return (value) => {
|
|
5043
|
+
const v = String(value);
|
|
5044
|
+
if (v.length <= maxLength) {
|
|
5045
|
+
return v;
|
|
5046
|
+
}
|
|
5047
|
+
return v.slice(0, maxLength) + suffix;
|
|
5048
|
+
};
|
|
5049
|
+
};
|
|
5050
|
+
var date2 = (options) => {
|
|
5051
|
+
const opt = options?.[0] ?? config2.locale;
|
|
5052
|
+
return (value) => {
|
|
5053
|
+
if (!(value instanceof Date)) {
|
|
5054
|
+
valueMustBeDate2("date");
|
|
5055
|
+
}
|
|
5056
|
+
return value.toLocaleDateString(opt);
|
|
5057
|
+
};
|
|
5058
|
+
};
|
|
5059
|
+
var time2 = (options) => {
|
|
5060
|
+
const opt = options?.[0] ?? config2.locale;
|
|
5061
|
+
return (value) => {
|
|
5062
|
+
if (!(value instanceof Date)) {
|
|
5063
|
+
valueMustBeDate2("time");
|
|
5064
|
+
}
|
|
5065
|
+
return value.toLocaleTimeString(opt);
|
|
5066
|
+
};
|
|
5067
|
+
};
|
|
5068
|
+
var datetime2 = (options) => {
|
|
5069
|
+
const opt = options?.[0] ?? config2.locale;
|
|
5070
|
+
return (value) => {
|
|
5071
|
+
if (!(value instanceof Date)) {
|
|
5072
|
+
valueMustBeDate2("datetime");
|
|
5073
|
+
}
|
|
5074
|
+
return value.toLocaleString(opt);
|
|
5075
|
+
};
|
|
5076
|
+
};
|
|
5077
|
+
var ymd2 = (options) => {
|
|
5078
|
+
const opt = options?.[0] ?? "-";
|
|
5079
|
+
return (value) => {
|
|
5080
|
+
if (!(value instanceof Date)) {
|
|
5081
|
+
valueMustBeDate2("ymd");
|
|
5082
|
+
}
|
|
5083
|
+
const year = value.getFullYear().toString();
|
|
5084
|
+
const month = (value.getMonth() + 1).toString().padStart(2, "0");
|
|
5085
|
+
const day = value.getDate().toString().padStart(2, "0");
|
|
5086
|
+
return `${year}${opt}${month}${opt}${day}`;
|
|
5087
|
+
};
|
|
5088
|
+
};
|
|
5089
|
+
var hms2 = (options) => {
|
|
5090
|
+
const opt = options?.[0] ?? ":";
|
|
5091
|
+
return (value) => {
|
|
5092
|
+
if (!(value instanceof Date)) {
|
|
5093
|
+
valueMustBeDate2("hms");
|
|
5094
|
+
}
|
|
5095
|
+
const hours = value.getHours().toString().padStart(2, "0");
|
|
5096
|
+
const minutes = value.getMinutes().toString().padStart(2, "0");
|
|
5097
|
+
const seconds = value.getSeconds().toString().padStart(2, "0");
|
|
5098
|
+
return `${hours}${opt}${minutes}${opt}${seconds}`;
|
|
5099
|
+
};
|
|
5100
|
+
};
|
|
5101
|
+
var falsy2 = (_options) => {
|
|
5102
|
+
return (value) => value === false || value === null || value === void 0 || value === 0 || value === "" || Number.isNaN(value);
|
|
5103
|
+
};
|
|
5104
|
+
var truthy2 = (_options) => {
|
|
5105
|
+
return (value) => value !== false && value !== null && value !== void 0 && value !== 0 && value !== "" && !Number.isNaN(value);
|
|
5106
|
+
};
|
|
5107
|
+
var defaults2 = (options) => {
|
|
5108
|
+
const opt = options?.[0] ?? optionsRequired2("defaults");
|
|
5109
|
+
return (value) => {
|
|
5110
|
+
if (value === false || value === null || value === void 0 || value === 0 || value === "" || Number.isNaN(value)) {
|
|
5111
|
+
return opt;
|
|
5112
|
+
}
|
|
5113
|
+
return value;
|
|
5114
|
+
};
|
|
5115
|
+
};
|
|
5116
|
+
var boolean2 = (_options) => {
|
|
5117
|
+
return (value) => {
|
|
5118
|
+
return Boolean(value);
|
|
5119
|
+
};
|
|
5120
|
+
};
|
|
5121
|
+
var number2 = (_options) => {
|
|
5122
|
+
return (value) => {
|
|
5123
|
+
return Number(value);
|
|
5124
|
+
};
|
|
5125
|
+
};
|
|
5126
|
+
var string2 = (_options) => {
|
|
5127
|
+
return (value) => {
|
|
5128
|
+
return String(value);
|
|
5129
|
+
};
|
|
5130
|
+
};
|
|
5131
|
+
var _null2 = (_options) => {
|
|
5132
|
+
return (value) => {
|
|
5133
|
+
return value === "" ? null : value;
|
|
5134
|
+
};
|
|
5135
|
+
};
|
|
5136
|
+
var builtinFilters2 = {
|
|
5137
|
+
"eq": eq2,
|
|
5138
|
+
"ne": ne2,
|
|
5139
|
+
"not": not2,
|
|
5140
|
+
"lt": lt2,
|
|
5141
|
+
"le": le2,
|
|
5142
|
+
"gt": gt2,
|
|
5143
|
+
"ge": ge2,
|
|
5144
|
+
"inc": inc2,
|
|
5145
|
+
"dec": dec2,
|
|
5146
|
+
"mul": mul2,
|
|
5147
|
+
"div": div2,
|
|
5148
|
+
"mod": mod2,
|
|
5149
|
+
"abs": abs2,
|
|
5150
|
+
"clamp": clamp2,
|
|
5151
|
+
"fix": fix2,
|
|
5152
|
+
"locale": locale2,
|
|
5153
|
+
"uc": uc2,
|
|
5154
|
+
"lc": lc2,
|
|
5155
|
+
"cap": cap2,
|
|
5156
|
+
"trim": trim2,
|
|
5157
|
+
"slice": slice2,
|
|
5158
|
+
"substr": substr2,
|
|
5159
|
+
"pad": pad2,
|
|
5160
|
+
"rep": rep2,
|
|
5161
|
+
"rev": rev2,
|
|
5162
|
+
"truncate": truncate2,
|
|
5163
|
+
"join": join2,
|
|
5164
|
+
"int": int2,
|
|
5165
|
+
"float": float2,
|
|
5166
|
+
"round": round2,
|
|
5167
|
+
"floor": floor2,
|
|
5168
|
+
"ceil": ceil2,
|
|
5169
|
+
"percent": percent2,
|
|
5170
|
+
"unit": unit2,
|
|
5171
|
+
"date": date2,
|
|
5172
|
+
"time": time2,
|
|
5173
|
+
"datetime": datetime2,
|
|
5174
|
+
"ymd": ymd2,
|
|
5175
|
+
"hms": hms2,
|
|
5176
|
+
"falsy": falsy2,
|
|
5177
|
+
"truthy": truthy2,
|
|
5178
|
+
"defaults": defaults2,
|
|
5179
|
+
"boolean": boolean2,
|
|
5180
|
+
"number": number2,
|
|
5181
|
+
"string": string2,
|
|
5182
|
+
"null": _null2
|
|
5183
|
+
};
|
|
5184
|
+
var outputBuiltinFilters2 = builtinFilters2;
|
|
5185
|
+
var inputBuiltinFilters = builtinFilters2;
|
|
5186
|
+
var builtinFiltersByFilterIOType = {
|
|
5187
|
+
"input": inputBuiltinFilters,
|
|
5188
|
+
"output": outputBuiltinFilters2
|
|
5189
|
+
};
|
|
5190
|
+
var builtinFilterFn = (name, options) => (filters) => {
|
|
5191
|
+
const filter = filters[name];
|
|
5192
|
+
if (!filter) {
|
|
5193
|
+
raiseError2(`[wcs/filter-unknown] filter not found: ${name}.${didYouMean(name, Object.keys(filters))}${LINT_HINT}`);
|
|
5194
|
+
}
|
|
5195
|
+
return filter(options);
|
|
5196
|
+
};
|
|
5197
|
+
function finalizeArg(text, firstQuoteStart, lastQuoteEnd) {
|
|
5198
|
+
const startLimit = firstQuoteStart === -1 ? text.length : firstQuoteStart;
|
|
5199
|
+
let start = 0;
|
|
5200
|
+
while (start < startLimit && /\s/.test(text[start])) {
|
|
5201
|
+
start++;
|
|
5202
|
+
}
|
|
5203
|
+
const endLimit = lastQuoteEnd === -1 ? 0 : lastQuoteEnd;
|
|
5204
|
+
let end = text.length;
|
|
5205
|
+
while (end > endLimit && /\s/.test(text[end - 1])) {
|
|
5206
|
+
end--;
|
|
5207
|
+
}
|
|
5208
|
+
return text.slice(start, end);
|
|
5209
|
+
}
|
|
5210
|
+
function parseFilterArgs(argsText) {
|
|
5211
|
+
const args = [];
|
|
5212
|
+
let current = "";
|
|
5213
|
+
let inQuote = null;
|
|
5214
|
+
let hasQuote = false;
|
|
5215
|
+
let firstQuoteStart = -1;
|
|
5216
|
+
let lastQuoteEnd = -1;
|
|
5217
|
+
const flush = () => {
|
|
5218
|
+
args.push(finalizeArg(current, firstQuoteStart, lastQuoteEnd));
|
|
5219
|
+
current = "";
|
|
5220
|
+
hasQuote = false;
|
|
5221
|
+
firstQuoteStart = -1;
|
|
5222
|
+
lastQuoteEnd = -1;
|
|
5223
|
+
};
|
|
5224
|
+
for (let i = 0; i < argsText.length; i++) {
|
|
5225
|
+
const char = argsText[i];
|
|
5226
|
+
if (inQuote) {
|
|
5227
|
+
if (char === inQuote) {
|
|
5228
|
+
inQuote = null;
|
|
5229
|
+
} else {
|
|
5230
|
+
if (firstQuoteStart === -1) {
|
|
5231
|
+
firstQuoteStart = current.length;
|
|
5232
|
+
}
|
|
5233
|
+
current += char;
|
|
5234
|
+
lastQuoteEnd = current.length;
|
|
5235
|
+
}
|
|
5236
|
+
} else if (char === '"' || char === "'") {
|
|
5237
|
+
inQuote = char;
|
|
5238
|
+
hasQuote = true;
|
|
5239
|
+
} else if (char === ",") {
|
|
5240
|
+
flush();
|
|
5241
|
+
} else {
|
|
5242
|
+
current += char;
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
const last = finalizeArg(current, firstQuoteStart, lastQuoteEnd);
|
|
5246
|
+
if (last || hasQuote) {
|
|
5247
|
+
args.push(last);
|
|
5248
|
+
}
|
|
5249
|
+
return args;
|
|
5250
|
+
}
|
|
5251
|
+
var filterFnByKey = /* @__PURE__ */ new Map();
|
|
5252
|
+
function clearFilterFnCacheForTooling() {
|
|
5253
|
+
filterFnByKey.clear();
|
|
5254
|
+
}
|
|
5255
|
+
function parseFilters(filterTextList, filterIOType) {
|
|
5256
|
+
const builtinFilters3 = builtinFiltersByFilterIOType[filterIOType];
|
|
5257
|
+
const filters = filterTextList.map((filterText) => {
|
|
5258
|
+
const openParenIndex = filterText.indexOf("(");
|
|
5259
|
+
const closeParenIndex = filterText.lastIndexOf(")");
|
|
5260
|
+
if (openParenIndex !== -1 && closeParenIndex === -1) {
|
|
5261
|
+
raiseError2(`Invalid filter format: missing closing parenthesis in "${filterText}"`);
|
|
5262
|
+
}
|
|
5263
|
+
if (closeParenIndex !== -1 && openParenIndex === -1) {
|
|
5264
|
+
raiseError2(`Invalid filter format: missing opening parenthesis in "${filterText}"`);
|
|
5265
|
+
}
|
|
5266
|
+
if (openParenIndex === -1) {
|
|
5267
|
+
const filterName = filterText.trim();
|
|
5268
|
+
const filterKey = `${filterName}():${filterIOType}`;
|
|
5269
|
+
let filterFn = filterFnByKey.get(filterKey);
|
|
5270
|
+
if (typeof filterFn === "undefined") {
|
|
5271
|
+
filterFn = builtinFilterFn(filterName, [])(builtinFilters3);
|
|
5272
|
+
filterFnByKey.set(filterKey, filterFn);
|
|
5273
|
+
}
|
|
5274
|
+
return {
|
|
5275
|
+
filterName,
|
|
5276
|
+
args: [],
|
|
5277
|
+
filterFn
|
|
5278
|
+
};
|
|
5279
|
+
} else {
|
|
5280
|
+
const argsText = filterText.substring(openParenIndex + 1, closeParenIndex);
|
|
5281
|
+
const filterName = filterText.substring(0, openParenIndex).trim();
|
|
5282
|
+
const args = parseFilterArgs(argsText);
|
|
5283
|
+
const filterKey = `${filterName}(${args.join(",")}):${filterIOType}`;
|
|
5284
|
+
let filterFn = filterFnByKey.get(filterKey);
|
|
5285
|
+
if (typeof filterFn === "undefined") {
|
|
5286
|
+
filterFn = builtinFilterFn(filterName, args)(builtinFilters3);
|
|
5287
|
+
filterFnByKey.set(filterKey, filterFn);
|
|
5288
|
+
}
|
|
5289
|
+
return {
|
|
5290
|
+
filterName,
|
|
5291
|
+
args,
|
|
5292
|
+
filterFn
|
|
5293
|
+
};
|
|
5294
|
+
}
|
|
5295
|
+
});
|
|
5296
|
+
return filters;
|
|
5297
|
+
}
|
|
5298
|
+
var trimFn = (s) => s.trim();
|
|
5299
|
+
var cacheFilterInfos$1 = /* @__PURE__ */ new Map();
|
|
5300
|
+
function clearPropPartCacheForTooling() {
|
|
5301
|
+
cacheFilterInfos$1.clear();
|
|
5302
|
+
}
|
|
5303
|
+
function parsePropPart(propPart) {
|
|
5304
|
+
const pos = propPart.indexOf(FILTER_SEPARATOR2);
|
|
5305
|
+
let propText = "";
|
|
5306
|
+
let filterTexts = [];
|
|
5307
|
+
let filtersText = "";
|
|
5308
|
+
let filters = [];
|
|
5309
|
+
if (pos !== -1) {
|
|
5310
|
+
propText = propPart.slice(0, pos).trim();
|
|
5311
|
+
filtersText = propPart.slice(pos + 1).trim();
|
|
5312
|
+
if (cacheFilterInfos$1.has(filtersText)) {
|
|
5313
|
+
filters = cacheFilterInfos$1.get(filtersText);
|
|
5314
|
+
} else {
|
|
5315
|
+
filterTexts = filtersText.split(FILTER_SEPARATOR2).map(trimFn);
|
|
5316
|
+
filters = parseFilters(filterTexts, "input");
|
|
5317
|
+
cacheFilterInfos$1.set(filtersText, filters);
|
|
5318
|
+
}
|
|
5319
|
+
} else {
|
|
5320
|
+
propText = propPart.trim();
|
|
5321
|
+
}
|
|
5322
|
+
const [propName, propModifiersText] = propText.split(MODIFIER_SEPARATOR2).map(trimFn);
|
|
5323
|
+
const propSegments = propName.split(DELIMITER2).map(trimFn);
|
|
5324
|
+
const propModifiers = propModifiersText ? propModifiersText.split(",").map(trimFn) : [];
|
|
5325
|
+
return {
|
|
5326
|
+
propName,
|
|
5327
|
+
propSegments,
|
|
5328
|
+
propModifiers,
|
|
5329
|
+
inFilters: filters
|
|
5330
|
+
};
|
|
5331
|
+
}
|
|
5332
|
+
var cacheFilterInfos = /* @__PURE__ */ new Map();
|
|
5333
|
+
function clearStatePartCacheForTooling() {
|
|
5334
|
+
cacheFilterInfos.clear();
|
|
5335
|
+
}
|
|
5336
|
+
function parseStatePart(statePart) {
|
|
5337
|
+
const pos = statePart.indexOf(FILTER_SEPARATOR2);
|
|
5338
|
+
let stateAndPath = "";
|
|
5339
|
+
let filterTexts = [];
|
|
5340
|
+
let filtersText = "";
|
|
5341
|
+
let filters = [];
|
|
5342
|
+
if (pos !== -1) {
|
|
5343
|
+
stateAndPath = statePart.slice(0, pos).trim();
|
|
5344
|
+
filtersText = statePart.slice(pos + 1).trim();
|
|
5345
|
+
if (cacheFilterInfos.has(filtersText)) {
|
|
5346
|
+
filters = cacheFilterInfos.get(filtersText);
|
|
5347
|
+
} else {
|
|
5348
|
+
filterTexts = filtersText.split(FILTER_SEPARATOR2).map(trimFn);
|
|
5349
|
+
filters = parseFilters(filterTexts, "output");
|
|
5350
|
+
cacheFilterInfos.set(filtersText, filters);
|
|
5351
|
+
}
|
|
5352
|
+
} else {
|
|
5353
|
+
stateAndPath = statePart.trim();
|
|
5354
|
+
}
|
|
5355
|
+
const [statePathName, stateName = "default"] = stateAndPath.split(STATE_NAME_SEPARATOR3).map(trimFn);
|
|
5356
|
+
const pathInfo = getPathInfo(statePathName);
|
|
5357
|
+
return {
|
|
5358
|
+
stateName,
|
|
5359
|
+
statePathName,
|
|
5360
|
+
statePathInfo: pathInfo,
|
|
5361
|
+
outFilters: filters
|
|
5362
|
+
};
|
|
5363
|
+
}
|
|
5364
|
+
function parseBindTextsForElement(bindText) {
|
|
5365
|
+
const [...bindTexts] = bindText.split(BINDING_SEPARATOR2).map(trimFn).filter((s) => s.length > 0);
|
|
5366
|
+
const results = bindTexts.map((bindText2) => {
|
|
5367
|
+
const separatorIndex = bindText2.indexOf(PROP_VALUE_SEPARATOR2);
|
|
5368
|
+
if (separatorIndex === -1) {
|
|
5369
|
+
raiseError2(`Invalid bindText: "${bindText2}". Missing ':' separator between propPart and statePart.`);
|
|
5370
|
+
}
|
|
5371
|
+
const propPart = bindText2.slice(0, separatorIndex).trim();
|
|
5372
|
+
const statePart = bindText2.slice(separatorIndex + 1).trim();
|
|
5373
|
+
if (propPart === ELSE_KEYWORD2) {
|
|
5374
|
+
const pathInfo = getPathInfo("#else");
|
|
5375
|
+
return {
|
|
5376
|
+
propName: ELSE_KEYWORD2,
|
|
5377
|
+
propSegments: [ELSE_KEYWORD2],
|
|
5378
|
+
propModifiers: [],
|
|
5379
|
+
statePathName: "#else",
|
|
5380
|
+
statePathInfo: pathInfo,
|
|
5381
|
+
stateName: "",
|
|
5382
|
+
inFilters: [],
|
|
5383
|
+
outFilters: [],
|
|
5384
|
+
bindingType: "else"
|
|
5385
|
+
};
|
|
5386
|
+
} else if (propPart === SPREAD_PROP2) {
|
|
5387
|
+
const stateResult = parseStatePart(statePart);
|
|
5388
|
+
if (stateResult.outFilters.length > 0) {
|
|
5389
|
+
raiseError2(`Invalid spread binding "${bindText2}": filters are not allowed on spread targets.`);
|
|
5390
|
+
}
|
|
5391
|
+
if (stateResult.statePathName.length === 0) {
|
|
5392
|
+
raiseError2(`Invalid spread binding "${bindText2}": spread target path is required.`);
|
|
5393
|
+
}
|
|
5394
|
+
return {
|
|
5395
|
+
propName: SPREAD_PROP2,
|
|
5396
|
+
propSegments: [SPREAD_PROP2],
|
|
5397
|
+
propModifiers: [],
|
|
5398
|
+
inFilters: [],
|
|
5399
|
+
...stateResult,
|
|
5400
|
+
bindingType: "spread"
|
|
5401
|
+
};
|
|
5402
|
+
} else if (propPart === "if" || propPart === "elseif" || propPart === "for" || propPart === "radio" || propPart === "checkbox") {
|
|
5403
|
+
const stateResult = parseStatePart(statePart);
|
|
5404
|
+
return {
|
|
5405
|
+
propName: propPart,
|
|
5406
|
+
propSegments: [propPart],
|
|
5407
|
+
propModifiers: [],
|
|
5408
|
+
inFilters: [],
|
|
5409
|
+
...stateResult,
|
|
5410
|
+
bindingType: propPart
|
|
5411
|
+
};
|
|
5412
|
+
} else {
|
|
5413
|
+
const stateResult = parseStatePart(statePart);
|
|
5414
|
+
const propResult = parsePropPart(propPart);
|
|
5415
|
+
if (propResult.propSegments[0] === EVENT_TOKEN_NAMESPACE2) {
|
|
5416
|
+
return {
|
|
5417
|
+
...propResult,
|
|
5418
|
+
...stateResult,
|
|
5419
|
+
bindingType: "event"
|
|
5420
|
+
};
|
|
5421
|
+
}
|
|
5422
|
+
if (propResult.propSegments[0].startsWith(EVENT_PROP_PREFIX2)) {
|
|
5423
|
+
return {
|
|
5424
|
+
...propResult,
|
|
5425
|
+
...stateResult,
|
|
5426
|
+
bindingType: "event"
|
|
5427
|
+
};
|
|
5428
|
+
} else {
|
|
5429
|
+
return {
|
|
5430
|
+
...propResult,
|
|
5431
|
+
...stateResult,
|
|
5432
|
+
bindingType: "prop"
|
|
5433
|
+
};
|
|
5434
|
+
}
|
|
5435
|
+
}
|
|
5436
|
+
});
|
|
5437
|
+
if (results.length > 1) {
|
|
5438
|
+
const isIncludeSingleBinding = results.some((r) => STRUCTURAL_BINDING_TYPE_SET2.has(r.bindingType));
|
|
5439
|
+
if (isIncludeSingleBinding) {
|
|
5440
|
+
raiseError2(`[wcs/template-syntax] Invalid bindText: "${bindText}". 'if', 'elseif', 'else', and 'for' bindings must be single binding. Put the structural binding alone in its own data-wcs (e.g. <template data-wcs="for: items">).${LINT_HINT}`);
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
return results;
|
|
5444
|
+
}
|
|
5445
|
+
function parseBindTextForEmbeddedNode(bindText) {
|
|
5446
|
+
const stateResult = parseStatePart(bindText);
|
|
5447
|
+
return {
|
|
5448
|
+
propName: "textContent",
|
|
5449
|
+
propSegments: ["textContent"],
|
|
5450
|
+
propModifiers: [],
|
|
5451
|
+
inFilters: [],
|
|
5452
|
+
...stateResult,
|
|
5453
|
+
bindingType: "text"
|
|
5454
|
+
};
|
|
5455
|
+
}
|
|
5456
|
+
function clearParserCaches() {
|
|
5457
|
+
clearPathInfoCacheForTooling();
|
|
5458
|
+
clearPropPartCacheForTooling();
|
|
5459
|
+
clearStatePartCacheForTooling();
|
|
5460
|
+
clearFilterFnCacheForTooling();
|
|
5461
|
+
}
|
|
5462
|
+
|
|
5463
|
+
// src/core/parser/positionalParser.ts
|
|
5464
|
+
var { delimiters } = getWcsManifest().syntax;
|
|
5465
|
+
function locate(haystack, needle, from, to) {
|
|
5466
|
+
if (needle.length === 0) return null;
|
|
5467
|
+
const index = haystack.indexOf(needle, from);
|
|
5468
|
+
if (index === -1 || index + needle.length > to) return null;
|
|
5469
|
+
return { start: index, end: index + needle.length };
|
|
5470
|
+
}
|
|
5471
|
+
function parseEmbeddedTextWithPositions(expression) {
|
|
5472
|
+
const exprRange = { start: 0, end: expression.length };
|
|
5473
|
+
let parsed = null;
|
|
5474
|
+
let error = null;
|
|
5475
|
+
try {
|
|
5476
|
+
parsed = parseBindTextForEmbeddedNode(expression);
|
|
5477
|
+
} catch (e) {
|
|
5478
|
+
error = e.message;
|
|
5479
|
+
}
|
|
5480
|
+
if (parsed === null) {
|
|
5481
|
+
return { exprRange, exprText: expression, parsed, error, propRange: null, pathRange: null, stateNameRange: null };
|
|
5482
|
+
}
|
|
5483
|
+
const firstPipe = expression.indexOf(delimiters.filter);
|
|
5484
|
+
const pathScopeEnd = firstPipe === -1 ? expression.length : firstPipe;
|
|
5485
|
+
const pathLocal = locate(expression, parsed.statePathName, 0, pathScopeEnd);
|
|
5486
|
+
let stateNameLocal = null;
|
|
5487
|
+
const at = expression.indexOf(delimiters.stateName);
|
|
5488
|
+
if (at !== -1 && at < pathScopeEnd) {
|
|
5489
|
+
stateNameLocal = locate(expression, parsed.stateName, at + 1, pathScopeEnd);
|
|
5490
|
+
}
|
|
5491
|
+
return {
|
|
5492
|
+
exprRange,
|
|
5493
|
+
exprText: expression,
|
|
5494
|
+
parsed,
|
|
5495
|
+
error,
|
|
5496
|
+
propRange: null,
|
|
5497
|
+
pathRange: pathLocal,
|
|
5498
|
+
stateNameRange: stateNameLocal
|
|
5499
|
+
};
|
|
5500
|
+
}
|
|
5501
|
+
function parseBindTextWithPositions(bindText) {
|
|
5502
|
+
const results = [];
|
|
5503
|
+
const segments = bindText.split(delimiters.binding);
|
|
5504
|
+
let segmentStart = 0;
|
|
5505
|
+
for (const segment of segments) {
|
|
5506
|
+
const leading = segment.length - segment.trimStart().length;
|
|
5507
|
+
const expr = segment.trim();
|
|
5508
|
+
const exprStart = segmentStart + leading;
|
|
5509
|
+
segmentStart += segment.length + delimiters.binding.length;
|
|
5510
|
+
if (expr.length === 0) continue;
|
|
5511
|
+
const exprRange = { start: exprStart, end: exprStart + expr.length };
|
|
5512
|
+
let parsed = null;
|
|
5513
|
+
let error = null;
|
|
5514
|
+
try {
|
|
5515
|
+
parsed = parseBindTextsForElement(expr)[0] ?? null;
|
|
5516
|
+
} catch (e) {
|
|
5517
|
+
error = e.message;
|
|
5518
|
+
}
|
|
5519
|
+
if (parsed === null) {
|
|
5520
|
+
results.push({ exprRange, exprText: expr, parsed, error, propRange: null, pathRange: null, stateNameRange: null });
|
|
5521
|
+
continue;
|
|
5522
|
+
}
|
|
5523
|
+
const colon = expr.indexOf(delimiters.propValue);
|
|
5524
|
+
const propEndLimit = colon === -1 ? expr.length : colon;
|
|
5525
|
+
const propLocal = locate(expr, parsed.propName, 0, propEndLimit);
|
|
5526
|
+
let pathLocal = null;
|
|
5527
|
+
let stateNameLocal = null;
|
|
5528
|
+
if (colon !== -1) {
|
|
5529
|
+
const stateBase = colon + 1;
|
|
5530
|
+
const firstPipe = expr.indexOf(delimiters.filter, stateBase);
|
|
5531
|
+
const pathScopeEnd = firstPipe === -1 ? expr.length : firstPipe;
|
|
5532
|
+
pathLocal = locate(expr, parsed.statePathName, stateBase, pathScopeEnd);
|
|
5533
|
+
const at = expr.indexOf(delimiters.stateName, stateBase);
|
|
5534
|
+
if (at !== -1 && at < pathScopeEnd) {
|
|
5535
|
+
stateNameLocal = locate(expr, parsed.stateName, at + 1, pathScopeEnd);
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
const lift = (range) => range === null ? null : { start: exprStart + range.start, end: exprStart + range.end };
|
|
5539
|
+
results.push({
|
|
5540
|
+
exprRange,
|
|
5541
|
+
exprText: expr,
|
|
5542
|
+
parsed,
|
|
5543
|
+
error,
|
|
5544
|
+
propRange: lift(propLocal),
|
|
5545
|
+
pathRange: lift(pathLocal),
|
|
5546
|
+
stateNameRange: lift(stateNameLocal)
|
|
5547
|
+
});
|
|
5548
|
+
}
|
|
5549
|
+
return results;
|
|
5550
|
+
}
|
|
5551
|
+
|
|
5552
|
+
// src/core/index/referenceIndex.ts
|
|
5553
|
+
function keyOf(stateName, path) {
|
|
5554
|
+
return `${stateName}\0${path}`;
|
|
5555
|
+
}
|
|
5556
|
+
function buildReferenceIndex(html, options = {}) {
|
|
5557
|
+
clearParserCaches();
|
|
5558
|
+
const bindAttribute = options.bindAttribute ?? "data-wcs";
|
|
5559
|
+
const stateTagName = options.stateTagName ?? "wcs-state";
|
|
5560
|
+
const occurrences = [];
|
|
5561
|
+
const problems = [];
|
|
5562
|
+
for (const attr of findAllBindAttributes(html, bindAttribute)) {
|
|
5563
|
+
for (const binding of parseBindTextWithPositions(attr.value)) {
|
|
5564
|
+
const lift = (range) => ({ start: attr.valueStart + range.start, end: attr.valueStart + range.end });
|
|
5565
|
+
if (binding.parsed === null) {
|
|
5566
|
+
problems.push({ message: binding.error ?? "parse error", range: lift(binding.exprRange) });
|
|
5567
|
+
continue;
|
|
5568
|
+
}
|
|
5569
|
+
if (binding.pathRange === null) continue;
|
|
5570
|
+
occurrences.push({
|
|
5571
|
+
source: "attribute",
|
|
5572
|
+
kind: binding.parsed.propSegments[0] === "eventToken" ? "eventToken" : "path",
|
|
5573
|
+
stateName: binding.parsed.stateName,
|
|
5574
|
+
path: binding.parsed.statePathName,
|
|
5575
|
+
pathRange: lift(binding.pathRange),
|
|
5576
|
+
exprRange: lift(binding.exprRange),
|
|
5577
|
+
propName: binding.parsed.propName,
|
|
5578
|
+
propRange: binding.propRange === null ? null : lift(binding.propRange),
|
|
5579
|
+
stateNameRange: binding.stateNameRange === null ? null : lift(binding.stateNameRange),
|
|
5580
|
+
bindingType: binding.parsed.bindingType
|
|
5581
|
+
});
|
|
5582
|
+
}
|
|
5583
|
+
}
|
|
5584
|
+
const textMatches = [
|
|
5585
|
+
...findAllMustacheSyntax(html),
|
|
5586
|
+
...findAllCommentBindings(html)
|
|
5587
|
+
];
|
|
5588
|
+
for (const match of textMatches) {
|
|
5589
|
+
const binding = parseEmbeddedTextWithPositions(match.expression);
|
|
5590
|
+
const shift = (range) => ({
|
|
5591
|
+
start: match.exprStart + range.start,
|
|
5592
|
+
end: match.exprStart + range.end
|
|
5593
|
+
});
|
|
5594
|
+
if (binding.parsed === null) {
|
|
5595
|
+
problems.push({ message: binding.error ?? "parse error", range: shift(binding.exprRange) });
|
|
5596
|
+
continue;
|
|
5597
|
+
}
|
|
5598
|
+
if (binding.pathRange === null) continue;
|
|
5599
|
+
occurrences.push({
|
|
5600
|
+
source: match.kind,
|
|
5601
|
+
kind: "path",
|
|
5602
|
+
stateName: binding.parsed.stateName,
|
|
5603
|
+
path: binding.parsed.statePathName,
|
|
5604
|
+
pathRange: shift(binding.pathRange),
|
|
5605
|
+
exprRange: { start: match.exprStart, end: match.exprEnd },
|
|
5606
|
+
propName: null,
|
|
5607
|
+
propRange: null,
|
|
5608
|
+
stateNameRange: binding.stateNameRange === null ? null : shift(binding.stateNameRange),
|
|
5609
|
+
bindingType: "text"
|
|
5610
|
+
});
|
|
5611
|
+
}
|
|
5612
|
+
const declarations = [];
|
|
5613
|
+
for (const block of parseWcsScriptBlocks(html, stateTagName)) {
|
|
5614
|
+
for (const span of analyzeDeclarationSpans(block.content)) {
|
|
5615
|
+
declarations.push({
|
|
5616
|
+
stateName: block.stateName,
|
|
5617
|
+
name: span.name,
|
|
5618
|
+
kind: span.kind,
|
|
5619
|
+
range: { start: block.contentStart + span.start, end: block.contentStart + span.end }
|
|
5620
|
+
});
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
5624
|
+
for (const occurrence of occurrences) {
|
|
5625
|
+
if (occurrence.kind !== "path") continue;
|
|
5626
|
+
const key = keyOf(occurrence.stateName, occurrence.path);
|
|
5627
|
+
const list = byPath.get(key);
|
|
5628
|
+
if (list === void 0) {
|
|
5629
|
+
byPath.set(key, [occurrence]);
|
|
5630
|
+
} else {
|
|
5631
|
+
list.push(occurrence);
|
|
5632
|
+
}
|
|
5633
|
+
}
|
|
5634
|
+
const declarationByName = /* @__PURE__ */ new Map();
|
|
5635
|
+
for (const declaration of declarations) {
|
|
5636
|
+
const key = keyOf(declaration.stateName, declaration.name);
|
|
5637
|
+
if (!declarationByName.has(key)) declarationByName.set(key, declaration);
|
|
5638
|
+
}
|
|
5639
|
+
return {
|
|
5640
|
+
occurrences,
|
|
5641
|
+
declarations,
|
|
5642
|
+
problems,
|
|
5643
|
+
referencesOf(stateName, path) {
|
|
5644
|
+
return (byPath.get(keyOf(stateName, path)) ?? []).slice();
|
|
5645
|
+
},
|
|
5646
|
+
declarationOf(stateName, path) {
|
|
5647
|
+
const exact = declarationByName.get(keyOf(stateName, path));
|
|
5648
|
+
if (exact !== void 0) return exact;
|
|
5649
|
+
const firstSegment = path.split(".")[0];
|
|
5650
|
+
if (firstSegment === path) return null;
|
|
5651
|
+
return declarationByName.get(keyOf(stateName, firstSegment)) ?? null;
|
|
5652
|
+
},
|
|
5653
|
+
occurrenceAt(offset) {
|
|
5654
|
+
for (const occurrence of occurrences) {
|
|
5655
|
+
if (offset >= occurrence.pathRange.start && offset < occurrence.pathRange.end) {
|
|
5656
|
+
return occurrence;
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5659
|
+
return null;
|
|
5660
|
+
}
|
|
5661
|
+
};
|
|
5662
|
+
}
|
|
5663
|
+
|
|
5664
|
+
// src/service/semanticValidator.ts
|
|
5665
|
+
var STATE_UPDATED_CALLBACK = "$updatedCallback";
|
|
5666
|
+
var API_CALL = /\.\s*\$(getAll|resolve)\s*\(/g;
|
|
5667
|
+
var STRING_LITERAL = /^\s*(["'])((?:\\.|(?!\1)[^\\])*)\1\s*$/;
|
|
5668
|
+
function splitCallArgs(source, open) {
|
|
5669
|
+
const args = [];
|
|
5670
|
+
const starts = [];
|
|
5671
|
+
let depth = 0;
|
|
5672
|
+
let argStart = open;
|
|
5673
|
+
let i = open;
|
|
5674
|
+
while (i < source.length) {
|
|
5675
|
+
const ch = source[i];
|
|
5676
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
5677
|
+
const quote = ch;
|
|
5678
|
+
i++;
|
|
5679
|
+
while (i < source.length) {
|
|
5680
|
+
if (source[i] === "\\") {
|
|
5681
|
+
i += 2;
|
|
5682
|
+
continue;
|
|
5683
|
+
}
|
|
5684
|
+
if (source[i] === quote) {
|
|
5685
|
+
i++;
|
|
5686
|
+
break;
|
|
5687
|
+
}
|
|
5688
|
+
i++;
|
|
5689
|
+
}
|
|
5690
|
+
continue;
|
|
5691
|
+
}
|
|
5692
|
+
if (ch === "(" || ch === "[" || ch === "{") {
|
|
5693
|
+
depth++;
|
|
5694
|
+
i++;
|
|
5695
|
+
continue;
|
|
5696
|
+
}
|
|
5697
|
+
if (ch === ")" && depth === 0) {
|
|
5698
|
+
args.push(source.slice(argStart, i));
|
|
5699
|
+
starts.push(argStart);
|
|
5700
|
+
return { args, starts, end: i + 1 };
|
|
5701
|
+
}
|
|
5702
|
+
if (ch === ")" || ch === "]" || ch === "}") {
|
|
5703
|
+
depth--;
|
|
5704
|
+
i++;
|
|
5705
|
+
continue;
|
|
5706
|
+
}
|
|
5707
|
+
if (ch === "," && depth === 0) {
|
|
5708
|
+
args.push(source.slice(argStart, i));
|
|
5709
|
+
starts.push(argStart);
|
|
5710
|
+
argStart = i + 1;
|
|
5711
|
+
i++;
|
|
5712
|
+
continue;
|
|
5713
|
+
}
|
|
5714
|
+
i++;
|
|
5715
|
+
}
|
|
5716
|
+
return null;
|
|
5717
|
+
}
|
|
5718
|
+
function literalString(arg) {
|
|
5719
|
+
const match = STRING_LITERAL.exec(arg);
|
|
5720
|
+
return match === null ? null : match[2];
|
|
5721
|
+
}
|
|
5722
|
+
function literalArrayLength(arg) {
|
|
5723
|
+
const trimmed = arg.trim();
|
|
5724
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return null;
|
|
5725
|
+
const inner = trimmed.slice(1, -1);
|
|
5726
|
+
if (inner.trim().length === 0) return 0;
|
|
5727
|
+
if (/(^|[^.])\.\.\./.test(inner)) return null;
|
|
5728
|
+
const parts = splitCallArgs(`${inner})`, 0);
|
|
5729
|
+
if (parts === null) return null;
|
|
5730
|
+
return parts.args.filter((part) => part.trim().length > 0).length;
|
|
5731
|
+
}
|
|
5732
|
+
function validateIndexArity(script, scriptStart, locale3) {
|
|
5733
|
+
const msgs = getMessages(locale3);
|
|
5734
|
+
const out = [];
|
|
5735
|
+
API_CALL.lastIndex = 0;
|
|
5736
|
+
let match;
|
|
5737
|
+
while ((match = API_CALL.exec(script)) !== null) {
|
|
5738
|
+
const api = `$${match[1]}`;
|
|
5739
|
+
const parsed = splitCallArgs(script, match.index + match[0].length);
|
|
5740
|
+
if (parsed === null) continue;
|
|
5741
|
+
API_CALL.lastIndex = parsed.end;
|
|
5742
|
+
if (parsed.args.length < 2) continue;
|
|
5743
|
+
const path = literalString(parsed.args[0]);
|
|
5744
|
+
if (path === null) continue;
|
|
5745
|
+
const actual = literalArrayLength(parsed.args[1]);
|
|
5746
|
+
if (actual === null) continue;
|
|
5747
|
+
const wildcardCount = countWildcardSegments(path);
|
|
5748
|
+
const requirement = api === "$resolve" ? "exact" : "atMost";
|
|
5749
|
+
const mismatched = requirement === "exact" ? actual !== wildcardCount : actual > wildcardCount;
|
|
5750
|
+
if (!mismatched) continue;
|
|
5751
|
+
const argText = parsed.args[1];
|
|
5752
|
+
const leading = argText.length - argText.trimStart().length;
|
|
5753
|
+
out.push({
|
|
5754
|
+
code: WcsDiagnosticCode.IndexArity,
|
|
5755
|
+
start: scriptStart + parsed.starts[1] + leading,
|
|
5756
|
+
end: scriptStart + parsed.starts[1] + argText.trimEnd().length,
|
|
5757
|
+
message: msgs.indexArity(api, path, requirement, wildcardCount, actual),
|
|
5758
|
+
severity: "warning"
|
|
5759
|
+
});
|
|
5760
|
+
}
|
|
5761
|
+
return out;
|
|
5762
|
+
}
|
|
5763
|
+
var READ_BRACKET = /\bthis\s*\??\.\s*\[\s*(["'])((?:\\.|(?!\1)[^\\])*)\1\s*\]|\bthis\s*\??\[\s*(["'])((?:\\.|(?!\3)[^\\])*)\3\s*\]/g;
|
|
5764
|
+
var READ_DOT = /\bthis\s*\??\.\s*([A-Za-z_]\w*)/g;
|
|
5765
|
+
var READ_API = /\bthis\s*\??\.\s*\$(?:getAll|resolve)\s*\(\s*(["'])((?:\\.|(?!\1)[^\\])*)\1/g;
|
|
5766
|
+
function collectReadPaths(body) {
|
|
5767
|
+
const paths = /* @__PURE__ */ new Set();
|
|
5768
|
+
for (const [regex, groups] of [
|
|
5769
|
+
[READ_BRACKET, [2, 4]],
|
|
5770
|
+
[READ_API, [2]],
|
|
5771
|
+
[READ_DOT, [1]]
|
|
5772
|
+
]) {
|
|
5773
|
+
regex.lastIndex = 0;
|
|
5774
|
+
let match;
|
|
5775
|
+
while ((match = regex.exec(body)) !== null) {
|
|
5776
|
+
for (const group of groups) {
|
|
5777
|
+
const value = match[group];
|
|
5778
|
+
if (value !== void 0 && value.length > 0 && !value.startsWith("$")) {
|
|
5779
|
+
paths.add(value);
|
|
5780
|
+
}
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
}
|
|
5784
|
+
return paths;
|
|
5785
|
+
}
|
|
5786
|
+
function validateGetterCycles(script, scriptStart, locale3) {
|
|
5787
|
+
const msgs = getMessages(locale3);
|
|
5788
|
+
const getters = analyzeCallableBodies(script).filter((entry) => entry.kind === "getter");
|
|
5789
|
+
if (getters.length === 0) return [];
|
|
5790
|
+
const declared = new Set(getters.map((getter) => getter.name));
|
|
5791
|
+
const edges = /* @__PURE__ */ new Map();
|
|
5792
|
+
for (const getter of getters) {
|
|
5793
|
+
const targets = [];
|
|
5794
|
+
for (const read of collectReadPaths(getter.body)) {
|
|
5795
|
+
if (declared.has(read)) targets.push(read);
|
|
5796
|
+
}
|
|
5797
|
+
edges.set(getter.name, targets);
|
|
5798
|
+
}
|
|
5799
|
+
const gray = /* @__PURE__ */ new Set();
|
|
5800
|
+
const black = /* @__PURE__ */ new Set();
|
|
5801
|
+
const stack = [];
|
|
5802
|
+
const cyclesByEntry = /* @__PURE__ */ new Map();
|
|
5803
|
+
const visit = (name) => {
|
|
5804
|
+
if (black.has(name)) return;
|
|
5805
|
+
if (gray.has(name)) {
|
|
5806
|
+
const from = stack.indexOf(name);
|
|
5807
|
+
const cycle = stack.slice(from).concat(name).join(" -> ");
|
|
5808
|
+
for (const member of stack.slice(from)) {
|
|
5809
|
+
if (!cyclesByEntry.has(member)) cyclesByEntry.set(member, cycle);
|
|
5810
|
+
}
|
|
5811
|
+
return;
|
|
5812
|
+
}
|
|
5813
|
+
gray.add(name);
|
|
5814
|
+
stack.push(name);
|
|
5815
|
+
for (const next of edges.get(name) ?? []) {
|
|
5816
|
+
visit(next);
|
|
5817
|
+
}
|
|
5818
|
+
stack.pop();
|
|
5819
|
+
gray.delete(name);
|
|
5820
|
+
black.add(name);
|
|
5821
|
+
};
|
|
5822
|
+
for (const getter of getters) {
|
|
5823
|
+
visit(getter.name);
|
|
5824
|
+
}
|
|
5825
|
+
if (cyclesByEntry.size === 0) return [];
|
|
5826
|
+
const out = [];
|
|
5827
|
+
for (const getter of getters) {
|
|
5828
|
+
const cycle = cyclesByEntry.get(getter.name);
|
|
5829
|
+
if (cycle === void 0) continue;
|
|
5830
|
+
out.push({
|
|
5831
|
+
code: WcsDiagnosticCode.GetterCycle,
|
|
5832
|
+
start: scriptStart + getter.start,
|
|
5833
|
+
end: scriptStart + getter.end,
|
|
5834
|
+
message: msgs.getterCycle(cycle),
|
|
5835
|
+
severity: "warning"
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5838
|
+
return out;
|
|
5839
|
+
}
|
|
5840
|
+
function blankComments(source) {
|
|
5841
|
+
const out = source.split("");
|
|
5842
|
+
let i = 0;
|
|
5843
|
+
while (i < source.length) {
|
|
5844
|
+
const ch = source[i];
|
|
5845
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
5846
|
+
const quote = ch;
|
|
5847
|
+
i++;
|
|
5848
|
+
while (i < source.length) {
|
|
5849
|
+
if (source[i] === "\\") {
|
|
5850
|
+
i += 2;
|
|
5851
|
+
continue;
|
|
5852
|
+
}
|
|
5853
|
+
if (source[i] === quote) {
|
|
5854
|
+
i++;
|
|
5855
|
+
break;
|
|
5856
|
+
}
|
|
5857
|
+
i++;
|
|
5858
|
+
}
|
|
5859
|
+
continue;
|
|
5860
|
+
}
|
|
5861
|
+
if (ch === "/" && source[i + 1] === "/") {
|
|
5862
|
+
while (i < source.length && source[i] !== "\n") {
|
|
5863
|
+
out[i] = " ";
|
|
5864
|
+
i++;
|
|
5865
|
+
}
|
|
5866
|
+
continue;
|
|
5867
|
+
}
|
|
5868
|
+
if (ch === "/" && source[i + 1] === "*") {
|
|
5869
|
+
while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) {
|
|
5870
|
+
out[i] = " ";
|
|
5871
|
+
i++;
|
|
5872
|
+
}
|
|
5873
|
+
if (i < source.length) {
|
|
5874
|
+
out[i] = " ";
|
|
5875
|
+
out[i + 1] = " ";
|
|
5876
|
+
i += 2;
|
|
5877
|
+
}
|
|
5878
|
+
continue;
|
|
5879
|
+
}
|
|
5880
|
+
i++;
|
|
5881
|
+
}
|
|
5882
|
+
return out.join("");
|
|
5883
|
+
}
|
|
5884
|
+
var PATH_TEST_LITERAL = /(?:\.\s*(?:includes|indexOf)\s*\(\s*|[!=]==\s*)(["'])((?:\\.|(?!\1)[^\\])*)\1/g;
|
|
5885
|
+
function validateUpdatedCallbackDemand(html, stateTagName, bindAttrName, locale3) {
|
|
5886
|
+
const blocks = parseWcsScriptBlocks(html, stateTagName);
|
|
5887
|
+
if (blocks.length === 0) return [];
|
|
5888
|
+
const hasCallback = blocks.some((block) => block.content.includes(STATE_UPDATED_CALLBACK));
|
|
5889
|
+
if (!hasCallback) return [];
|
|
5890
|
+
const msgs = getMessages(locale3);
|
|
5891
|
+
const boundPaths = collectBoundPaths(html, stateTagName, bindAttrName);
|
|
5892
|
+
const out = [];
|
|
5893
|
+
for (const block of blocks) {
|
|
5894
|
+
const callback = analyzeCallableBodies(block.content).find((entry) => entry.name === STATE_UPDATED_CALLBACK && entry.kind === "method");
|
|
5895
|
+
if (callback === void 0) continue;
|
|
5896
|
+
const declared = new Set(analyzeStatePaths(block.content, block.stateName).map((p) => p.path));
|
|
5897
|
+
const bound = boundPaths.get(block.stateName) ?? /* @__PURE__ */ new Set();
|
|
5898
|
+
const body = blankComments(callback.body);
|
|
5899
|
+
PATH_TEST_LITERAL.lastIndex = 0;
|
|
5900
|
+
let match;
|
|
5901
|
+
const reported = /* @__PURE__ */ new Set();
|
|
5902
|
+
while ((match = PATH_TEST_LITERAL.exec(body)) !== null) {
|
|
5903
|
+
const path = match[2];
|
|
5904
|
+
if (path.length === 0 || !declared.has(path) || bound.has(path)) continue;
|
|
5905
|
+
if (reported.has(path)) continue;
|
|
5906
|
+
reported.add(path);
|
|
5907
|
+
const quoteAt = match.index + match[0].length - path.length - 1;
|
|
5908
|
+
out.push({
|
|
5909
|
+
code: WcsDiagnosticCode.UpdatedCallbackUnbound,
|
|
5910
|
+
start: block.contentStart + callback.bodyStart + quoteAt,
|
|
5911
|
+
end: block.contentStart + callback.bodyStart + quoteAt + path.length,
|
|
5912
|
+
message: msgs.updatedCallbackUnbound(path),
|
|
5913
|
+
severity: "warning"
|
|
5914
|
+
});
|
|
5915
|
+
}
|
|
5916
|
+
}
|
|
5917
|
+
return out;
|
|
5918
|
+
}
|
|
5919
|
+
function collectBoundPaths(html, stateTagName, bindAttrName) {
|
|
5920
|
+
const byState = /* @__PURE__ */ new Map();
|
|
5921
|
+
const add = (stateName, path) => {
|
|
5922
|
+
let set = byState.get(stateName);
|
|
5923
|
+
if (set === void 0) {
|
|
5924
|
+
set = /* @__PURE__ */ new Set();
|
|
5925
|
+
byState.set(stateName, set);
|
|
5926
|
+
}
|
|
5927
|
+
set.add(path);
|
|
5928
|
+
};
|
|
5929
|
+
const index = buildReferenceIndex(html, { bindAttribute: bindAttrName, stateTagName });
|
|
5930
|
+
for (const occurrence of index.occurrences) {
|
|
5931
|
+
add(occurrence.stateName, occurrence.path);
|
|
5932
|
+
if (!occurrence.path.startsWith(".")) continue;
|
|
5933
|
+
const forPath = getInnermostForPath(html, occurrence.pathRange.start, bindAttrName);
|
|
5934
|
+
if (forPath === null || forPath.startsWith(".")) continue;
|
|
5935
|
+
add(
|
|
5936
|
+
occurrence.stateName,
|
|
5937
|
+
occurrence.path === "." ? `${forPath}.*` : `${forPath}.*.${occurrence.path.slice(1)}`
|
|
5938
|
+
);
|
|
5939
|
+
}
|
|
5940
|
+
return byState;
|
|
5941
|
+
}
|
|
5942
|
+
function validateSemantics(html, stateTagName = "wcs-state", locale3, bindAttrName = "data-wcs") {
|
|
5943
|
+
const out = [];
|
|
5944
|
+
for (const block of parseWcsScriptBlocks(html, stateTagName)) {
|
|
5945
|
+
out.push(...validateIndexArity(block.content, block.contentStart, locale3));
|
|
5946
|
+
out.push(...validateGetterCycles(block.content, block.contentStart, locale3));
|
|
5947
|
+
}
|
|
5948
|
+
out.push(...validateUpdatedCallbackDemand(html, stateTagName, bindAttrName, locale3));
|
|
5949
|
+
return out;
|
|
5950
|
+
}
|
|
5951
|
+
|
|
5952
|
+
// src/core/validateDocument.ts
|
|
5953
|
+
function validateDocument(text, options = {}) {
|
|
5954
|
+
const bindAttribute = options.bindAttribute ?? "data-wcs";
|
|
5955
|
+
const stateTagName = options.stateTagName ?? "wcs-state";
|
|
5956
|
+
const locale3 = options.locale;
|
|
5957
|
+
const fileReader = options.fileReader;
|
|
5958
|
+
const out = [];
|
|
5959
|
+
out.push(...validateBindings(text, bindAttribute, stateTagName, locale3, fileReader));
|
|
5960
|
+
out.push(...validateTemplateSyntax(text, stateTagName, bindAttribute, locale3, fileReader));
|
|
5961
|
+
out.push(...validateIoNodes(text, bindAttribute, stateTagName, locale3, fileReader));
|
|
5962
|
+
out.push(...validateDocumentEnv(text, locale3));
|
|
5963
|
+
out.push(...validateSemantics(text, stateTagName, locale3, bindAttribute));
|
|
5964
|
+
out.push(...validateArrayMutations(text, stateTagName, locale3));
|
|
5965
|
+
out.push(...validateWatchDeclarations(text, stateTagName, locale3));
|
|
5966
|
+
for (const d of validateStateTypes(text, stateTagName, locale3)) {
|
|
5967
|
+
out.push({ code: WcsDiagnosticCode.TypeAnnotation, start: d.start, end: d.end, message: d.message, severity: d.severity });
|
|
5968
|
+
}
|
|
5969
|
+
for (const d of validateNestedAssigns(text, stateTagName, locale3)) {
|
|
5970
|
+
out.push({ code: WcsDiagnosticCode.NestedAssign, start: d.start, end: d.end, message: d.message, severity: d.severity });
|
|
5971
|
+
}
|
|
5972
|
+
return sortDiagnostics(out);
|
|
5973
|
+
}
|
|
5974
|
+
|
|
5975
|
+
// src/core/sidecar/schemaSubset.ts
|
|
5976
|
+
var ALLOWED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
5977
|
+
"type",
|
|
5978
|
+
"properties",
|
|
5979
|
+
"required",
|
|
5980
|
+
"items",
|
|
5981
|
+
"enum",
|
|
5982
|
+
"const",
|
|
5983
|
+
"anyOf",
|
|
5984
|
+
"$defs",
|
|
5985
|
+
"$ref"
|
|
5986
|
+
]);
|
|
5987
|
+
var DiagnosticContext = class {
|
|
5988
|
+
constructor(spans) {
|
|
5989
|
+
this.spans = spans;
|
|
3735
5990
|
}
|
|
3736
5991
|
diagnostics = [];
|
|
3737
5992
|
add(code, pointer2, message, severity, extra = {}, useKeySpan = false) {
|
|
@@ -4336,29 +6591,6 @@ function runValidation(inputs, options = {}) {
|
|
|
4336
6591
|
function classify(path) {
|
|
4337
6592
|
return path.endsWith(".manifest.json") ? "manifest" : "html";
|
|
4338
6593
|
}
|
|
4339
|
-
function createFileReader(htmlPath, read = (p) => (0, import_node_fs.readFileSync)(p, "utf8")) {
|
|
4340
|
-
const base = (0, import_node_path.dirname)(htmlPath);
|
|
4341
|
-
const cache = /* @__PURE__ */ new Map();
|
|
4342
|
-
return (relativePath) => {
|
|
4343
|
-
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(relativePath) || relativePath.startsWith("/")) {
|
|
4344
|
-
return void 0;
|
|
4345
|
-
}
|
|
4346
|
-
if (cache.has(relativePath)) {
|
|
4347
|
-
return cache.get(relativePath);
|
|
4348
|
-
}
|
|
4349
|
-
let content;
|
|
4350
|
-
try {
|
|
4351
|
-
content = read((0, import_node_path.resolve)(base, relativePath));
|
|
4352
|
-
if (content.charCodeAt(0) === 65279) {
|
|
4353
|
-
content = content.slice(1);
|
|
4354
|
-
}
|
|
4355
|
-
} catch {
|
|
4356
|
-
content = void 0;
|
|
4357
|
-
}
|
|
4358
|
-
cache.set(relativePath, content);
|
|
4359
|
-
return content;
|
|
4360
|
-
};
|
|
4361
|
-
}
|
|
4362
6594
|
function parseArgs(argv) {
|
|
4363
6595
|
const options = {};
|
|
4364
6596
|
const files = [];
|
|
@@ -4383,7 +6615,7 @@ function resolveCliLocale(explicit, env = process.env) {
|
|
|
4383
6615
|
}
|
|
4384
6616
|
function main(argv) {
|
|
4385
6617
|
const { options, files } = parseArgs(argv);
|
|
4386
|
-
const
|
|
6618
|
+
const locale3 = resolveCliLocale(options.locale);
|
|
4387
6619
|
if (files.length === 0) {
|
|
4388
6620
|
process.stderr.write("usage: wcs-validate [--attr=data-wcs] [--state-tag=wcs-state] [--lang=ja|en] <file> [<file> ...]\n");
|
|
4389
6621
|
return 2;
|
|
@@ -4392,7 +6624,7 @@ function main(argv) {
|
|
|
4392
6624
|
for (const path of files) {
|
|
4393
6625
|
let text;
|
|
4394
6626
|
try {
|
|
4395
|
-
text = (0,
|
|
6627
|
+
text = (0, import_node_fs2.readFileSync)(path, "utf8");
|
|
4396
6628
|
} catch (e) {
|
|
4397
6629
|
process.stderr.write(`cannot read ${path}: ${e.message}
|
|
4398
6630
|
`);
|
|
@@ -4401,7 +6633,7 @@ function main(argv) {
|
|
|
4401
6633
|
const kind = classify(path);
|
|
4402
6634
|
inputs.push({ source: path, text, kind, fileReader: kind === "html" ? createFileReader(path) : void 0 });
|
|
4403
6635
|
}
|
|
4404
|
-
const result = runValidation(inputs, { ...options, locale });
|
|
6636
|
+
const result = runValidation(inputs, { ...options, locale: locale3 });
|
|
4405
6637
|
for (const line of result.lines) {
|
|
4406
6638
|
process.stdout.write(line + "\n");
|
|
4407
6639
|
}
|