@wcstack/lint 1.26.0 → 1.28.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/README.ja.md +2 -0
- package/README.md +2 -0
- package/dist/cli.cjs +540 -22
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -23,6 +23,8 @@ npx wcs-validate --errors-only src/**/*.html
|
|
|
23
23
|
|
|
24
24
|
`.manifest.json` で終わるファイルは sidecar manifest として、それ以外は `data-wcs` バインディングを含む HTML として検査されます。
|
|
25
25
|
|
|
26
|
+
`<wcs-state src="...">` で参照される外部 state(`.json` / `.js` / `.ts`)は HTML ファイルからの相対パスで解決され、パス検証の対象になります。URL・絶対パスは読み込まず、読めないファイルはスキップされ、解決できないパスは warning のままです。なお外部 state が**解決できた**ページには通常の検証面が全て適用されるため、error severity の検出(例: 配列でない値への `for:`)が「これまでパス未解決で沈黙していたビルド」を新たに落とすことがあります。
|
|
27
|
+
|
|
26
28
|
```
|
|
27
29
|
wcs-validate [--attr=data-wcs] [--state-tag=wcs-state] [--lang=ja|en] [--errors-only] <file> [<file> ...]
|
|
28
30
|
```
|
package/README.md
CHANGED
|
@@ -23,6 +23,8 @@ npx wcs-validate --errors-only src/**/*.html
|
|
|
23
23
|
|
|
24
24
|
Files ending in `.manifest.json` are validated as sidecar manifests; everything else is validated as HTML with `data-wcs` bindings.
|
|
25
25
|
|
|
26
|
+
External state referenced via `<wcs-state src="...">` (`.json` / `.js` / `.ts`) is resolved relative to the HTML file and included in path validation. URLs and absolute paths are never read, unreadable files are skipped, and unresolved paths stay warnings. Note that once external state *does* resolve, the full validation surface applies to those pages — error-severity findings (e.g. `for:` bound to a non-array) can fail a build that was previously silent because the paths could not be checked.
|
|
27
|
+
|
|
26
28
|
```
|
|
27
29
|
wcs-validate [--attr=data-wcs] [--state-tag=wcs-state] [--lang=ja|en] [--errors-only] <file> [<file> ...]
|
|
28
30
|
```
|
package/dist/cli.cjs
CHANGED
|
@@ -21,12 +21,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/cli.ts
|
|
22
22
|
var cli_exports = {};
|
|
23
23
|
__export(cli_exports, {
|
|
24
|
+
createFileReader: () => createFileReader,
|
|
24
25
|
main: () => main,
|
|
25
26
|
parseArgs: () => parseArgs,
|
|
26
27
|
resolveCliLocale: () => resolveCliLocale
|
|
27
28
|
});
|
|
28
29
|
module.exports = __toCommonJS(cli_exports);
|
|
29
30
|
var import_node_fs = require("node:fs");
|
|
31
|
+
var import_node_path = require("node:path");
|
|
30
32
|
|
|
31
33
|
// src/core/offsetToPosition.ts
|
|
32
34
|
function createPositionMapper(text) {
|
|
@@ -89,6 +91,13 @@ var WcsDiagnosticCode = {
|
|
|
89
91
|
TokenUndeclared: "wcs/token-undeclared",
|
|
90
92
|
TokenMisconfigured: "wcs/token-misconfigured",
|
|
91
93
|
NestedAssign: "wcs/nested-assign",
|
|
94
|
+
// --- <wcs-state> script: $watch declaration ---
|
|
95
|
+
// ランタイム(watch/processWatchDeclaration.ts)が raiseError で落とす宣言。
|
|
96
|
+
// 越境 `@` / `$` 始まり / 空キー・空セグメント / 明らかな非関数ハンドラ。
|
|
97
|
+
WatchDeclarationInvalid: "wcs/watch-declaration-invalid",
|
|
98
|
+
// `$watch` のキーが状態定義に存在しない。バインディング側と違い黙って発火しない
|
|
99
|
+
// だけなので気づけない。severity は binding-path-missing に揃える(warning)。
|
|
100
|
+
WatchPathMissing: "wcs/watch-path-missing",
|
|
92
101
|
TypeAnnotation: "wcs/type-annotation",
|
|
93
102
|
TemplateSyntax: "wcs/template-syntax",
|
|
94
103
|
// --- <wcs-state> script: array reactivity hazards ---
|
|
@@ -134,6 +143,8 @@ var builtinFilterMeta = {
|
|
|
134
143
|
mul: { description: "\u4E57\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
135
144
|
div: { description: "\u9664\u7B97", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
136
145
|
mod: { description: "\u5270\u4F59", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
146
|
+
abs: { description: "\u7D76\u5BFE\u5024", hasArgs: false, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 0 },
|
|
147
|
+
clamp: { description: "\u7BC4\u56F2\u5185\u306B\u4E38\u3081\u308B (min,max)", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 2, maxArgs: 2, argTypes: ["number", "number"] },
|
|
137
148
|
// 数値フォーマット
|
|
138
149
|
fix: { description: "\u56FA\u5B9A\u5C0F\u6570\u70B9\u8868\u8A18", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
139
150
|
locale: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u3067\u6570\u5024\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
@@ -147,6 +158,8 @@ var builtinFilterMeta = {
|
|
|
147
158
|
pad: { description: "\u30D1\u30C7\u30A3\u30F3\u30B0 (length[,char])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
|
|
148
159
|
rep: { description: "\u7E70\u308A\u8FD4\u3057 (count)", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
149
160
|
rev: { description: "\u6587\u5B57\u9806\u3092\u53CD\u8EE2", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
|
|
161
|
+
truncate: { description: "\u5207\u308A\u8A70\u3081\u3066\u7701\u7565\u8A18\u53F7 (length[,suffix])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
|
|
162
|
+
join: { description: "\u914D\u5217\u3092\u9023\u7D50 ([separator])", hasArgs: true, resultType: "string", acceptTypes: ["array"], minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
150
163
|
// 数値パース・丸め
|
|
151
164
|
int: { description: "\u6574\u6570\u306B\u30D1\u30FC\u30B9", hasArgs: false, resultType: "number", acceptTypes: ["string", "number"], minArgs: 0, maxArgs: 0 },
|
|
152
165
|
float: { description: "\u6D6E\u52D5\u5C0F\u6570\u70B9\u6570\u306B\u30D1\u30FC\u30B9", hasArgs: false, resultType: "number", acceptTypes: ["string", "number"], minArgs: 0, maxArgs: 0 },
|
|
@@ -154,11 +167,15 @@ var builtinFilterMeta = {
|
|
|
154
167
|
floor: { description: "\u5207\u308A\u4E0B\u3052", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
155
168
|
ceil: { description: "\u5207\u308A\u4E0A\u3052", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
156
169
|
percent: { description: "\u30D1\u30FC\u30BB\u30F3\u30C6\u30FC\u30B8\u5F62\u5F0F", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
170
|
+
// number だけでなく string も受ける。実用チェーンは fix / percent の後ろに繋がり、
|
|
171
|
+
// それらは既に string を返すため(builtinFilters.ts の unit を参照)
|
|
172
|
+
unit: { description: "\u5358\u4F4D\uFF08\u63A5\u5C3E\u8F9E\uFF09\u3092\u4ED8\u52A0", hasArgs: true, resultType: "string", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["string"] },
|
|
157
173
|
// 日付・時刻
|
|
158
174
|
date: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u306E\u65E5\u4ED8", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
159
175
|
time: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u306E\u6642\u523B", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
160
176
|
datetime: { description: "\u30ED\u30B1\u30FC\u30EB\u5F62\u5F0F\u306E\u65E5\u6642", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
161
177
|
ymd: { description: "YYYY-MM-DD \u5F62\u5F0F", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
178
|
+
hms: { description: "HH:MM:SS \u5F62\u5F0F", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
162
179
|
// 真偽値・変換
|
|
163
180
|
falsy: { description: "\u507D\u5024\u304B\u5224\u5B9A", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
164
181
|
truthy: { description: "\u771F\u5024\u304B\u5224\u5B9A", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
@@ -175,9 +192,24 @@ var STRUCTURAL_BINDING_TYPE_SET = /* @__PURE__ */ new Set([
|
|
|
175
192
|
"for"
|
|
176
193
|
]);
|
|
177
194
|
var MAX_WILDCARD_DEPTH = 128;
|
|
195
|
+
var MODIFIER_PREVENT = "prevent";
|
|
196
|
+
var MODIFIER_STOP = "stop";
|
|
197
|
+
var MODIFIER_READONLY = "ro";
|
|
198
|
+
var MODIFIER_FLAGS = Object.freeze([
|
|
199
|
+
MODIFIER_PREVENT,
|
|
200
|
+
MODIFIER_STOP,
|
|
201
|
+
MODIFIER_READONLY
|
|
202
|
+
]);
|
|
203
|
+
var MODIFIER_KEY_INIT = "init";
|
|
204
|
+
var MODIFIER_KEY_SYNC = "sync";
|
|
205
|
+
var MODIFIER_KEYS = Object.freeze([
|
|
206
|
+
MODIFIER_KEY_INIT,
|
|
207
|
+
MODIFIER_KEY_SYNC
|
|
208
|
+
]);
|
|
209
|
+
var INDEX_PARAM_PREFIX = "$";
|
|
178
210
|
var tmpIndexByIndexName = {};
|
|
179
211
|
for (let i = 0; i < MAX_WILDCARD_DEPTH; i++) {
|
|
180
|
-
tmpIndexByIndexName[
|
|
212
|
+
tmpIndexByIndexName[`${INDEX_PARAM_PREFIX}${i + 1}`] = i;
|
|
181
213
|
}
|
|
182
214
|
Object.freeze(tmpIndexByIndexName);
|
|
183
215
|
|
|
@@ -419,6 +451,7 @@ var RESERVED_STREAMS_KEY = "$streams";
|
|
|
419
451
|
var RESERVED_COMMAND_TOKENS_KEY = "$commandTokens";
|
|
420
452
|
var RESERVED_EVENT_TOKENS_KEY = "$eventTokens";
|
|
421
453
|
var RESERVED_LIST_KEYS_KEY = "$listKeys";
|
|
454
|
+
var RESERVED_WATCH_KEY = "$watch";
|
|
422
455
|
function analyzeStatePaths(scriptContent, stateName = "default") {
|
|
423
456
|
const objectContent = extractDefaultExportObject(scriptContent);
|
|
424
457
|
if (!objectContent) return [];
|
|
@@ -452,6 +485,36 @@ function analyzeStatePaths(scriptContent, stateName = "default") {
|
|
|
452
485
|
}
|
|
453
486
|
return paths;
|
|
454
487
|
}
|
|
488
|
+
function analyzeWatchEntries(scriptContent) {
|
|
489
|
+
const root = locateDefaultExportObject(scriptContent);
|
|
490
|
+
if (!root) return [];
|
|
491
|
+
const watchProp = parseTopLevelProperties(root.content).find((p) => p.name === RESERVED_WATCH_KEY);
|
|
492
|
+
if (!watchProp || watchProp.kind !== "data" || !watchProp.value || !isObjectLiteral(watchProp.value) || watchProp.valueStart === void 0) {
|
|
493
|
+
return [];
|
|
494
|
+
}
|
|
495
|
+
const leading = watchProp.value.length - watchProp.value.trimStart().length;
|
|
496
|
+
const innerStart = root.start + watchProp.valueStart + leading + 1;
|
|
497
|
+
const entries = [];
|
|
498
|
+
for (const entry of parseTopLevelProperties(extractObjectContent(watchProp.value))) {
|
|
499
|
+
if (entry.nameStart === void 0 || entry.nameEnd === void 0) continue;
|
|
500
|
+
entries.push({
|
|
501
|
+
key: entry.name,
|
|
502
|
+
start: innerStart + entry.nameStart,
|
|
503
|
+
end: innerStart + entry.nameEnd,
|
|
504
|
+
// メソッド短縮記法は関数。data は値リテラルの形で判定し、識別子参照は疑わない。
|
|
505
|
+
definitelyNotFunction: entry.kind === "data" && isNonFunctionLiteral(entry.value)
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
return entries;
|
|
509
|
+
}
|
|
510
|
+
function isNonFunctionLiteral(value) {
|
|
511
|
+
if (value === void 0) return false;
|
|
512
|
+
const trimmed = value.trim();
|
|
513
|
+
if (trimmed.length === 0) return false;
|
|
514
|
+
const scan = maskCommentsAndStrings(trimmed);
|
|
515
|
+
if (/^(?:async\s+)?function\b/.test(trimmed) || scan.includes("=>")) return false;
|
|
516
|
+
return /^["'`]/.test(trimmed) || /^-?\d/.test(trimmed) || /^(?:true|false|null|undefined)\b/.test(trimmed) || trimmed.startsWith("[") || trimmed.startsWith("{");
|
|
517
|
+
}
|
|
455
518
|
function collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKeys, stateName) {
|
|
456
519
|
if (prop.name === RESERVED_STREAMS_KEY && prop.kind === "data" && prop.value && isObjectLiteral(prop.value)) {
|
|
457
520
|
const entries = parseTopLevelProperties(extractObjectContent(prop.value));
|
|
@@ -598,23 +661,29 @@ function inferJsonTypeHint(value) {
|
|
|
598
661
|
if (typeof value === "object") return "object";
|
|
599
662
|
return void 0;
|
|
600
663
|
}
|
|
601
|
-
function
|
|
664
|
+
function locateDefaultExportObject(script) {
|
|
602
665
|
const scan = maskCommentsAndStrings(script);
|
|
603
666
|
const match = scan.match(/export\s+default\s+(?:defineState\s*\(\s*)?(\{)/);
|
|
604
667
|
if (!match) return null;
|
|
605
|
-
const
|
|
606
|
-
return extractBracedContent(script, scan,
|
|
668
|
+
const braceIndex = scan.indexOf(match[1], match.index);
|
|
669
|
+
return { content: extractBracedContent(script, scan, braceIndex), start: braceIndex + 1 };
|
|
670
|
+
}
|
|
671
|
+
function extractDefaultExportObject(script) {
|
|
672
|
+
return locateDefaultExportObject(script)?.content ?? null;
|
|
607
673
|
}
|
|
608
674
|
function parseTopLevelProperties(objectContent) {
|
|
609
675
|
const props = [];
|
|
610
676
|
const scan = maskCommentsAndStrings(objectContent);
|
|
611
|
-
const regex = /(?:(?:get|set)\s+(?:"([^"]+)"|'([^']+)'|([$\w]+))\s*\([^)]*\)\s*\{)|(?:(?:async\s+)?([$\w]+)\s*\([^)]*\)\s*\{)|(?:(?:"([^"]+)"|'([^']+)'|([$\w]+))\s*:\s*)/gd;
|
|
677
|
+
const regex = /(?:(?:get|set)\s+(?:"([^"]+)"|'([^']+)'|([$\w]+))\s*\([^)]*\)\s*\{)|(?:(?:async\s+)?(?:"([^"]+)"|'([^']+)'|([$\w]+))\s*\([^)]*\)\s*\{)|(?:(?:"([^"]+)"|'([^']+)'|([$\w]+))\s*:\s*)/gd;
|
|
612
678
|
let match;
|
|
613
679
|
while ((match = regex.exec(scan)) !== null) {
|
|
614
680
|
const indices = match.indices;
|
|
681
|
+
let nameSpan;
|
|
615
682
|
const nameAt = (group) => {
|
|
616
683
|
const span = indices[group];
|
|
617
|
-
|
|
684
|
+
if (!span) return void 0;
|
|
685
|
+
nameSpan = [span[0], span[1]];
|
|
686
|
+
return objectContent.slice(span[0], span[1]);
|
|
618
687
|
};
|
|
619
688
|
const skipBody = () => {
|
|
620
689
|
const braceStart = match.index + match[0].length - 1;
|
|
@@ -623,23 +692,31 @@ function parseTopLevelProperties(objectContent) {
|
|
|
623
692
|
};
|
|
624
693
|
const accessorName = nameAt(1) ?? nameAt(2) ?? nameAt(3);
|
|
625
694
|
if (accessorName) {
|
|
626
|
-
props.push({ name: accessorName, kind: "getter" });
|
|
695
|
+
props.push({ name: accessorName, kind: "getter", nameStart: nameSpan[0], nameEnd: nameSpan[1] });
|
|
627
696
|
skipBody();
|
|
628
697
|
continue;
|
|
629
698
|
}
|
|
630
|
-
const methodName = nameAt(4);
|
|
699
|
+
const methodName = nameAt(4) ?? nameAt(5) ?? nameAt(6);
|
|
631
700
|
if (methodName) {
|
|
632
|
-
props.push({ name: methodName, kind: "method" });
|
|
701
|
+
props.push({ name: methodName, kind: "method", nameStart: nameSpan[0], nameEnd: nameSpan[1] });
|
|
633
702
|
skipBody();
|
|
634
703
|
continue;
|
|
635
704
|
}
|
|
636
|
-
const propName = nameAt(
|
|
705
|
+
const propName = nameAt(7) ?? nameAt(8) ?? nameAt(9);
|
|
637
706
|
if (propName) {
|
|
638
707
|
const valueStartIndex = match.index + match[0].length;
|
|
639
708
|
const value = extractFullValue(objectContent, scan, valueStartIndex);
|
|
640
709
|
const jsdocType = extractJsDocType(objectContent, match.index);
|
|
641
710
|
const typeHint = jsdocType ?? inferTypeHint(value);
|
|
642
|
-
props.push({
|
|
711
|
+
props.push({
|
|
712
|
+
name: propName,
|
|
713
|
+
kind: "data",
|
|
714
|
+
value,
|
|
715
|
+
typeHint,
|
|
716
|
+
nameStart: nameSpan[0],
|
|
717
|
+
nameEnd: nameSpan[1],
|
|
718
|
+
valueStart: valueStartIndex
|
|
719
|
+
});
|
|
643
720
|
regex.lastIndex = valueStartIndex + value.length;
|
|
644
721
|
}
|
|
645
722
|
}
|
|
@@ -971,6 +1048,11 @@ var ja = {
|
|
|
971
1048
|
wcsTextInfo: (e) => `wcs-text \u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0: ${e}`,
|
|
972
1049
|
moustacheFouc: (e) => `<template> \u5916\u306E {{ }} \u69CB\u6587\u306F FOUC\uFF08\u521D\u671F\u8868\u793A\u6642\u306B\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u6587\u5B57\u5217\u304C\u898B\u3048\u308B\uFF09\u306E\u539F\u56E0\u306B\u306A\u308A\u307E\u3059\u3002<!--@@:${e}--> \u307E\u305F\u306F\u30B3\u30E1\u30F3\u30C8\u69CB\u6587\u306E\u4F7F\u7528\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,
|
|
973
1050
|
nestedAssign: (sp) => `\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30D7\u30ED\u30D1\u30C6\u30A3\u3078\u306E\u4EE3\u5165\u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\u3002this["${sp}"] \u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,
|
|
1051
|
+
watchKeyCrossState: (k) => `$watch \u306E\u30AD\u30FC "${k}" \u306F\u4ED6\u306E state \u3092\u6307\u3057\u3066\u3044\u307E\u3059\u3002@ \u4ED8\u304D\u306E\u8D8A\u5883 watch \u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08\u81EA state \u306E\u30D1\u30B9\u306E\u307F\uFF09`,
|
|
1052
|
+
watchKeyReserved: (k) => `$watch \u306E\u30AD\u30FC "${k}" \u306F "$" \u3067\u59CB\u3081\u3089\u308C\u307E\u305B\u3093\uFF08\u4E88\u7D04\u540D\u524D\u7A7A\u9593\uFF09`,
|
|
1053
|
+
watchKeyEmptySegment: (k) => `$watch \u306E\u30AD\u30FC "${k}" \u306B\u7A7A\u306E\u30D1\u30B9\u30BB\u30B0\u30E1\u30F3\u30C8\u304C\u3042\u308A\u307E\u3059`,
|
|
1054
|
+
watchHandlerNotFunction: (k) => `$watch \u306E\u30A8\u30F3\u30C8\u30EA "${k}" \u306E\u5024\u306F\u95A2\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059`,
|
|
1055
|
+
watchPathMissing: (k) => `$watch \u306E\u30AD\u30FC "${k}" \u306F\u72B6\u614B\u5B9A\u7FA9\u306B\u5B58\u5728\u3057\u307E\u305B\u3093\uFF08\u4E00\u5EA6\u3082\u767A\u706B\u3057\u307E\u305B\u3093\uFF09`,
|
|
974
1056
|
typeAnnotationIncompatible: (vt, rt) => `\u578B "${vt}" \u306F @type {${rt}} \u3068\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093`,
|
|
975
1057
|
arrayMutation: (m, alt) => `\u914D\u5217\u306E\u7834\u58CA\u7684\u30E1\u30BD\u30C3\u30C9 "${m}" \u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\uFF08\u540C\u4E00\u53C2\u7167\u306E\u81EA\u5DF1\u518D\u4EE3\u5165\u3067\u3082\u8981\u7D20\u306E\u8FFD\u52A0\u30FB\u524A\u9664\u306F\u53CD\u6620\u3055\u308C\u307E\u305B\u3093\uFF09\u3002\u975E\u7834\u58CA\u30E1\u30BD\u30C3\u30C9\u3068\u518D\u4EE3\u5165\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: ${alt}\uFF09\u3002`,
|
|
976
1058
|
arrayIndexAssign: (sp) => `\u914D\u5217\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3078\u306E\u76F4\u63A5\u4EE3\u5165\u306F\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u66F4\u65B0\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\u3002this["${sp}"] \u306E\u3088\u3046\u306A\u30C9\u30C3\u30C8\u30D1\u30B9\u4EE3\u5165\u3001\u307E\u305F\u306F with() \u3068\u518D\u4EE3\u5165\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,
|
|
@@ -1013,6 +1095,11 @@ var en = {
|
|
|
1013
1095
|
wcsTextInfo: (e) => `wcs-text binding: ${e}`,
|
|
1014
1096
|
moustacheFouc: (e) => `{{ }} outside a <template> causes FOUC (the raw template string is visible before binding). Consider the comment syntax <!--@@:${e}--> instead.`,
|
|
1015
1097
|
nestedAssign: (sp) => `Assigning to a nested property does not trigger a reactive update. Use this["${sp}"] instead.`,
|
|
1098
|
+
watchKeyCrossState: (k) => `$watch key "${k}" targets another state. Cross-state watching with @ is not supported (own paths only)`,
|
|
1099
|
+
watchKeyReserved: (k) => `$watch key "${k}" must not start with "$" (reserved namespace)`,
|
|
1100
|
+
watchKeyEmptySegment: (k) => `$watch key "${k}" has an empty path segment`,
|
|
1101
|
+
watchHandlerNotFunction: (k) => `The value of $watch entry "${k}" must be a function`,
|
|
1102
|
+
watchPathMissing: (k) => `$watch key "${k}" does not exist in the state definition (it will never fire)`,
|
|
1016
1103
|
typeAnnotationIncompatible: (vt, rt) => `Type "${vt}" is not compatible with @type {${rt}}`,
|
|
1017
1104
|
arrayMutation: (m, alt) => `Destructive array method "${m}" does not trigger a reactive update (re-assigning the same reference does not reflect added/removed elements either). Use a non-destructive method with reassignment (e.g. ${alt}).`,
|
|
1018
1105
|
arrayIndexAssign: (sp) => `Assigning directly to an array index does not trigger a reactive update. Use a dot-path assignment like this["${sp}"], or with() plus reassignment.`,
|
|
@@ -1034,10 +1121,10 @@ function getMessages(locale) {
|
|
|
1034
1121
|
|
|
1035
1122
|
// src/service/bindingValidator.ts
|
|
1036
1123
|
var filterMap = new Map(BUILTIN_FILTERS.map((f) => [f.name, f]));
|
|
1037
|
-
function validateBindings(html, attrName, stateTagName = "wcs-state", locale) {
|
|
1124
|
+
function validateBindings(html, attrName, stateTagName = "wcs-state", locale, fileReader) {
|
|
1038
1125
|
const diagnostics = [];
|
|
1039
1126
|
const msgs = getMessages(locale);
|
|
1040
|
-
const statePaths = getStatePathsFromHtml(html, stateTagName);
|
|
1127
|
+
const statePaths = getStatePathsFromHtml(html, stateTagName, fileReader);
|
|
1041
1128
|
const pathsByState = /* @__PURE__ */ new Map();
|
|
1042
1129
|
for (const p of statePaths) {
|
|
1043
1130
|
const list = pathsByState.get(p.stateName) ?? [];
|
|
@@ -1828,10 +1915,10 @@ function isInsideTag(html, offset, tagName) {
|
|
|
1828
1915
|
}
|
|
1829
1916
|
|
|
1830
1917
|
// src/service/templateSyntaxValidator.ts
|
|
1831
|
-
function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", locale) {
|
|
1918
|
+
function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", locale, fileReader) {
|
|
1832
1919
|
const diagnostics = [];
|
|
1833
1920
|
const msgs = getMessages(locale);
|
|
1834
|
-
const allPaths = getStatePathsFromHtml(html, stateTagName);
|
|
1921
|
+
const allPaths = getStatePathsFromHtml(html, stateTagName, fileReader);
|
|
1835
1922
|
if (allPaths.length === 0) return diagnostics;
|
|
1836
1923
|
const defaultPaths = allPaths.filter((p) => p.stateName === "default");
|
|
1837
1924
|
const pathSet = new Set(defaultPaths.map((p) => p.path));
|
|
@@ -1945,6 +2032,7 @@ function isValidTemplatePath(path, pathSet, scopedPaths) {
|
|
|
1945
2032
|
var BUILTIN_TAGS = {
|
|
1946
2033
|
"wcs-accelerometer": {
|
|
1947
2034
|
"package": "accelerometer",
|
|
2035
|
+
"observedAttributes": [],
|
|
1948
2036
|
"inputs": {
|
|
1949
2037
|
"frequency": null
|
|
1950
2038
|
},
|
|
@@ -1962,6 +2050,7 @@ var BUILTIN_TAGS = {
|
|
|
1962
2050
|
},
|
|
1963
2051
|
"wcs-ambient-light-sensor": {
|
|
1964
2052
|
"package": "ambient-light-sensor",
|
|
2053
|
+
"observedAttributes": [],
|
|
1965
2054
|
"inputs": {
|
|
1966
2055
|
"frequency": null
|
|
1967
2056
|
},
|
|
@@ -1975,8 +2064,240 @@ var BUILTIN_TAGS = {
|
|
|
1975
2064
|
"stop"
|
|
1976
2065
|
]
|
|
1977
2066
|
},
|
|
2067
|
+
"wcs-audio": {
|
|
2068
|
+
"package": "audio",
|
|
2069
|
+
"observedAttributes": [
|
|
2070
|
+
"volume",
|
|
2071
|
+
"limiter",
|
|
2072
|
+
"resume-on-gesture"
|
|
2073
|
+
],
|
|
2074
|
+
"inputs": {
|
|
2075
|
+
"volume": "volume",
|
|
2076
|
+
"limiter": "limiter",
|
|
2077
|
+
"resumeOnGesture": "resume-on-gesture"
|
|
2078
|
+
},
|
|
2079
|
+
"properties": [
|
|
2080
|
+
"state",
|
|
2081
|
+
"running",
|
|
2082
|
+
"suspended",
|
|
2083
|
+
"unsupported",
|
|
2084
|
+
"voices",
|
|
2085
|
+
"noteOn",
|
|
2086
|
+
"noteOff",
|
|
2087
|
+
"warnings",
|
|
2088
|
+
"error",
|
|
2089
|
+
"errorInfo"
|
|
2090
|
+
],
|
|
2091
|
+
"commands": [
|
|
2092
|
+
"resume",
|
|
2093
|
+
"suspend",
|
|
2094
|
+
"noteOn",
|
|
2095
|
+
"noteOff",
|
|
2096
|
+
"allNotesOff"
|
|
2097
|
+
]
|
|
2098
|
+
},
|
|
2099
|
+
"wcs-voice": {
|
|
2100
|
+
"package": "audio",
|
|
2101
|
+
"observedAttributes": [
|
|
2102
|
+
"poly"
|
|
2103
|
+
],
|
|
2104
|
+
"inputs": {},
|
|
2105
|
+
"properties": [],
|
|
2106
|
+
"commands": []
|
|
2107
|
+
},
|
|
2108
|
+
"wcs-osc": {
|
|
2109
|
+
"package": "audio",
|
|
2110
|
+
"observedAttributes": [
|
|
2111
|
+
"frequency",
|
|
2112
|
+
"detune",
|
|
2113
|
+
"type",
|
|
2114
|
+
"glide",
|
|
2115
|
+
"transpose",
|
|
2116
|
+
"id",
|
|
2117
|
+
"out",
|
|
2118
|
+
"param",
|
|
2119
|
+
"note",
|
|
2120
|
+
"master",
|
|
2121
|
+
"poly"
|
|
2122
|
+
],
|
|
2123
|
+
"inputs": {
|
|
2124
|
+
"frequency": "frequency",
|
|
2125
|
+
"detune": "detune",
|
|
2126
|
+
"type": "type",
|
|
2127
|
+
"glide": "glide",
|
|
2128
|
+
"transpose": "transpose"
|
|
2129
|
+
},
|
|
2130
|
+
"properties": [],
|
|
2131
|
+
"commands": []
|
|
2132
|
+
},
|
|
2133
|
+
"wcs-noise": {
|
|
2134
|
+
"package": "audio",
|
|
2135
|
+
"observedAttributes": [
|
|
2136
|
+
"id",
|
|
2137
|
+
"out",
|
|
2138
|
+
"param",
|
|
2139
|
+
"note",
|
|
2140
|
+
"master",
|
|
2141
|
+
"poly"
|
|
2142
|
+
],
|
|
2143
|
+
"inputs": {},
|
|
2144
|
+
"properties": [],
|
|
2145
|
+
"commands": []
|
|
2146
|
+
},
|
|
2147
|
+
"wcs-biquad": {
|
|
2148
|
+
"package": "audio",
|
|
2149
|
+
"observedAttributes": [
|
|
2150
|
+
"frequency",
|
|
2151
|
+
"q",
|
|
2152
|
+
"gain",
|
|
2153
|
+
"detune",
|
|
2154
|
+
"type",
|
|
2155
|
+
"id",
|
|
2156
|
+
"out",
|
|
2157
|
+
"param",
|
|
2158
|
+
"note",
|
|
2159
|
+
"master",
|
|
2160
|
+
"poly"
|
|
2161
|
+
],
|
|
2162
|
+
"inputs": {
|
|
2163
|
+
"frequency": "frequency",
|
|
2164
|
+
"q": "q",
|
|
2165
|
+
"gain": "gain",
|
|
2166
|
+
"detune": "detune",
|
|
2167
|
+
"type": "type"
|
|
2168
|
+
},
|
|
2169
|
+
"properties": [],
|
|
2170
|
+
"commands": []
|
|
2171
|
+
},
|
|
2172
|
+
"wcs-gain": {
|
|
2173
|
+
"package": "audio",
|
|
2174
|
+
"observedAttributes": [
|
|
2175
|
+
"gain",
|
|
2176
|
+
"id",
|
|
2177
|
+
"out",
|
|
2178
|
+
"param",
|
|
2179
|
+
"note",
|
|
2180
|
+
"master",
|
|
2181
|
+
"poly"
|
|
2182
|
+
],
|
|
2183
|
+
"inputs": {
|
|
2184
|
+
"gain": "gain"
|
|
2185
|
+
},
|
|
2186
|
+
"properties": [],
|
|
2187
|
+
"commands": []
|
|
2188
|
+
},
|
|
2189
|
+
"wcs-delay": {
|
|
2190
|
+
"package": "audio",
|
|
2191
|
+
"observedAttributes": [
|
|
2192
|
+
"time",
|
|
2193
|
+
"feedback",
|
|
2194
|
+
"mix",
|
|
2195
|
+
"id",
|
|
2196
|
+
"out",
|
|
2197
|
+
"param",
|
|
2198
|
+
"note",
|
|
2199
|
+
"master",
|
|
2200
|
+
"poly"
|
|
2201
|
+
],
|
|
2202
|
+
"inputs": {
|
|
2203
|
+
"time": "time",
|
|
2204
|
+
"feedback": "feedback",
|
|
2205
|
+
"mix": "mix"
|
|
2206
|
+
},
|
|
2207
|
+
"properties": [],
|
|
2208
|
+
"commands": []
|
|
2209
|
+
},
|
|
2210
|
+
"wcs-shaper": {
|
|
2211
|
+
"package": "audio",
|
|
2212
|
+
"observedAttributes": [
|
|
2213
|
+
"amount",
|
|
2214
|
+
"id",
|
|
2215
|
+
"out",
|
|
2216
|
+
"param",
|
|
2217
|
+
"note",
|
|
2218
|
+
"master",
|
|
2219
|
+
"poly"
|
|
2220
|
+
],
|
|
2221
|
+
"inputs": {
|
|
2222
|
+
"amount": "amount"
|
|
2223
|
+
},
|
|
2224
|
+
"properties": [],
|
|
2225
|
+
"commands": []
|
|
2226
|
+
},
|
|
2227
|
+
"wcs-env": {
|
|
2228
|
+
"package": "audio",
|
|
2229
|
+
"observedAttributes": [
|
|
2230
|
+
"attack",
|
|
2231
|
+
"decay",
|
|
2232
|
+
"sustain",
|
|
2233
|
+
"release",
|
|
2234
|
+
"depth",
|
|
2235
|
+
"id",
|
|
2236
|
+
"out",
|
|
2237
|
+
"param",
|
|
2238
|
+
"note",
|
|
2239
|
+
"master",
|
|
2240
|
+
"poly"
|
|
2241
|
+
],
|
|
2242
|
+
"inputs": {
|
|
2243
|
+
"attack": "attack",
|
|
2244
|
+
"decay": "decay",
|
|
2245
|
+
"sustain": "sustain",
|
|
2246
|
+
"release": "release",
|
|
2247
|
+
"depth": "depth"
|
|
2248
|
+
},
|
|
2249
|
+
"properties": [],
|
|
2250
|
+
"commands": []
|
|
2251
|
+
},
|
|
2252
|
+
"wcs-lfo": {
|
|
2253
|
+
"package": "audio",
|
|
2254
|
+
"observedAttributes": [
|
|
2255
|
+
"rate",
|
|
2256
|
+
"depth",
|
|
2257
|
+
"type",
|
|
2258
|
+
"id",
|
|
2259
|
+
"out",
|
|
2260
|
+
"param",
|
|
2261
|
+
"note",
|
|
2262
|
+
"master",
|
|
2263
|
+
"poly"
|
|
2264
|
+
],
|
|
2265
|
+
"inputs": {
|
|
2266
|
+
"rate": "rate",
|
|
2267
|
+
"depth": "depth",
|
|
2268
|
+
"type": "type"
|
|
2269
|
+
},
|
|
2270
|
+
"properties": [],
|
|
2271
|
+
"commands": []
|
|
2272
|
+
},
|
|
2273
|
+
"wcs-analyser": {
|
|
2274
|
+
"package": "audio",
|
|
2275
|
+
"observedAttributes": [
|
|
2276
|
+
"fft",
|
|
2277
|
+
"smoothing",
|
|
2278
|
+
"id",
|
|
2279
|
+
"out",
|
|
2280
|
+
"param",
|
|
2281
|
+
"note",
|
|
2282
|
+
"master",
|
|
2283
|
+
"poly"
|
|
2284
|
+
],
|
|
2285
|
+
"inputs": {
|
|
2286
|
+
"fft": "fft",
|
|
2287
|
+
"smoothing": "smoothing"
|
|
2288
|
+
},
|
|
2289
|
+
"properties": [
|
|
2290
|
+
"frame"
|
|
2291
|
+
],
|
|
2292
|
+
"commands": [
|
|
2293
|
+
"sample"
|
|
2294
|
+
]
|
|
2295
|
+
},
|
|
1978
2296
|
"wcs-broadcast": {
|
|
1979
2297
|
"package": "broadcast",
|
|
2298
|
+
"observedAttributes": [
|
|
2299
|
+
"name"
|
|
2300
|
+
],
|
|
1980
2301
|
"inputs": {
|
|
1981
2302
|
"name": "name",
|
|
1982
2303
|
"manual": "manual"
|
|
@@ -1994,6 +2315,13 @@ var BUILTIN_TAGS = {
|
|
|
1994
2315
|
},
|
|
1995
2316
|
"wcs-camera": {
|
|
1996
2317
|
"package": "camera",
|
|
2318
|
+
"observedAttributes": [
|
|
2319
|
+
"facing-mode",
|
|
2320
|
+
"device-id",
|
|
2321
|
+
"audio",
|
|
2322
|
+
"width",
|
|
2323
|
+
"height"
|
|
2324
|
+
],
|
|
1997
2325
|
"inputs": {
|
|
1998
2326
|
"audio": "audio",
|
|
1999
2327
|
"facingMode": "facing-mode",
|
|
@@ -2022,6 +2350,7 @@ var BUILTIN_TAGS = {
|
|
|
2022
2350
|
},
|
|
2023
2351
|
"wcs-recorder": {
|
|
2024
2352
|
"package": "camera",
|
|
2353
|
+
"observedAttributes": [],
|
|
2025
2354
|
"inputs": {
|
|
2026
2355
|
"mimeType": "mime-type",
|
|
2027
2356
|
"timeslice": "timeslice",
|
|
@@ -2050,6 +2379,7 @@ var BUILTIN_TAGS = {
|
|
|
2050
2379
|
},
|
|
2051
2380
|
"wcs-clipboard": {
|
|
2052
2381
|
"package": "clipboard",
|
|
2382
|
+
"observedAttributes": [],
|
|
2053
2383
|
"inputs": {
|
|
2054
2384
|
"monitor": "monitor"
|
|
2055
2385
|
},
|
|
@@ -2077,6 +2407,7 @@ var BUILTIN_TAGS = {
|
|
|
2077
2407
|
},
|
|
2078
2408
|
"wcs-contacts": {
|
|
2079
2409
|
"package": "contacts",
|
|
2410
|
+
"observedAttributes": [],
|
|
2080
2411
|
"inputs": {},
|
|
2081
2412
|
"properties": [
|
|
2082
2413
|
"value",
|
|
@@ -2091,6 +2422,7 @@ var BUILTIN_TAGS = {
|
|
|
2091
2422
|
},
|
|
2092
2423
|
"wcs-credential": {
|
|
2093
2424
|
"package": "credential",
|
|
2425
|
+
"observedAttributes": [],
|
|
2094
2426
|
"inputs": {},
|
|
2095
2427
|
"properties": [
|
|
2096
2428
|
"value",
|
|
@@ -2106,6 +2438,7 @@ var BUILTIN_TAGS = {
|
|
|
2106
2438
|
},
|
|
2107
2439
|
"wcs-debounce": {
|
|
2108
2440
|
"package": "debounce",
|
|
2441
|
+
"observedAttributes": [],
|
|
2109
2442
|
"inputs": {
|
|
2110
2443
|
"source": null,
|
|
2111
2444
|
"wait": "wait",
|
|
@@ -2126,6 +2459,7 @@ var BUILTIN_TAGS = {
|
|
|
2126
2459
|
},
|
|
2127
2460
|
"wcs-throttle": {
|
|
2128
2461
|
"package": "debounce",
|
|
2462
|
+
"observedAttributes": [],
|
|
2129
2463
|
"inputs": {
|
|
2130
2464
|
"source": null,
|
|
2131
2465
|
"wait": "wait",
|
|
@@ -2146,6 +2480,7 @@ var BUILTIN_TAGS = {
|
|
|
2146
2480
|
},
|
|
2147
2481
|
"wcs-defined": {
|
|
2148
2482
|
"package": "defined",
|
|
2483
|
+
"observedAttributes": [],
|
|
2149
2484
|
"inputs": {
|
|
2150
2485
|
"tags": "tags",
|
|
2151
2486
|
"mode": "mode",
|
|
@@ -2163,6 +2498,7 @@ var BUILTIN_TAGS = {
|
|
|
2163
2498
|
},
|
|
2164
2499
|
"wcs-eyedropper": {
|
|
2165
2500
|
"package": "eyedropper",
|
|
2501
|
+
"observedAttributes": [],
|
|
2166
2502
|
"inputs": {},
|
|
2167
2503
|
"properties": [
|
|
2168
2504
|
"value",
|
|
@@ -2178,6 +2514,9 @@ var BUILTIN_TAGS = {
|
|
|
2178
2514
|
},
|
|
2179
2515
|
"wcs-fetch": {
|
|
2180
2516
|
"package": "fetch",
|
|
2517
|
+
"observedAttributes": [
|
|
2518
|
+
"url"
|
|
2519
|
+
],
|
|
2181
2520
|
"inputs": {
|
|
2182
2521
|
"url": null,
|
|
2183
2522
|
"method": null,
|
|
@@ -2203,24 +2542,36 @@ var BUILTIN_TAGS = {
|
|
|
2203
2542
|
},
|
|
2204
2543
|
"wcs-fetch-header": {
|
|
2205
2544
|
"package": "fetch",
|
|
2545
|
+
"observedAttributes": [],
|
|
2206
2546
|
"inputs": {},
|
|
2207
2547
|
"properties": [],
|
|
2208
2548
|
"commands": []
|
|
2209
2549
|
},
|
|
2210
2550
|
"wcs-fetch-body": {
|
|
2211
2551
|
"package": "fetch",
|
|
2552
|
+
"observedAttributes": [],
|
|
2212
2553
|
"inputs": {},
|
|
2213
2554
|
"properties": [],
|
|
2214
2555
|
"commands": []
|
|
2215
2556
|
},
|
|
2216
2557
|
"wcs-infinite-scroll": {
|
|
2217
2558
|
"package": "fetch",
|
|
2559
|
+
"observedAttributes": [
|
|
2560
|
+
"target",
|
|
2561
|
+
"root",
|
|
2562
|
+
"root-margin",
|
|
2563
|
+
"threshold",
|
|
2564
|
+
"disabled"
|
|
2565
|
+
],
|
|
2218
2566
|
"inputs": {},
|
|
2219
2567
|
"properties": [],
|
|
2220
2568
|
"commands": []
|
|
2221
2569
|
},
|
|
2222
2570
|
"wcs-fullscreen": {
|
|
2223
2571
|
"package": "fullscreen",
|
|
2572
|
+
"observedAttributes": [
|
|
2573
|
+
"target"
|
|
2574
|
+
],
|
|
2224
2575
|
"inputs": {
|
|
2225
2576
|
"target": "target"
|
|
2226
2577
|
},
|
|
@@ -2236,6 +2587,7 @@ var BUILTIN_TAGS = {
|
|
|
2236
2587
|
},
|
|
2237
2588
|
"wcs-geo": {
|
|
2238
2589
|
"package": "geolocation",
|
|
2590
|
+
"observedAttributes": [],
|
|
2239
2591
|
"inputs": {
|
|
2240
2592
|
"highAccuracy": "high-accuracy",
|
|
2241
2593
|
"timeout": "timeout",
|
|
@@ -2266,6 +2618,7 @@ var BUILTIN_TAGS = {
|
|
|
2266
2618
|
},
|
|
2267
2619
|
"wcs-gyroscope": {
|
|
2268
2620
|
"package": "gyroscope",
|
|
2621
|
+
"observedAttributes": [],
|
|
2269
2622
|
"inputs": {
|
|
2270
2623
|
"frequency": null
|
|
2271
2624
|
},
|
|
@@ -2283,6 +2636,7 @@ var BUILTIN_TAGS = {
|
|
|
2283
2636
|
},
|
|
2284
2637
|
"wcs-idle": {
|
|
2285
2638
|
"package": "idle",
|
|
2639
|
+
"observedAttributes": [],
|
|
2286
2640
|
"inputs": {
|
|
2287
2641
|
"threshold": "threshold"
|
|
2288
2642
|
},
|
|
@@ -2301,6 +2655,12 @@ var BUILTIN_TAGS = {
|
|
|
2301
2655
|
},
|
|
2302
2656
|
"wcs-intersect": {
|
|
2303
2657
|
"package": "intersection",
|
|
2658
|
+
"observedAttributes": [
|
|
2659
|
+
"target",
|
|
2660
|
+
"root",
|
|
2661
|
+
"root-margin",
|
|
2662
|
+
"threshold"
|
|
2663
|
+
],
|
|
2304
2664
|
"inputs": {
|
|
2305
2665
|
"target": "target",
|
|
2306
2666
|
"root": "root",
|
|
@@ -2328,6 +2688,7 @@ var BUILTIN_TAGS = {
|
|
|
2328
2688
|
},
|
|
2329
2689
|
"wcs-magnetometer": {
|
|
2330
2690
|
"package": "magnetometer",
|
|
2691
|
+
"observedAttributes": [],
|
|
2331
2692
|
"inputs": {
|
|
2332
2693
|
"frequency": null
|
|
2333
2694
|
},
|
|
@@ -2343,8 +2704,46 @@ var BUILTIN_TAGS = {
|
|
|
2343
2704
|
"stop"
|
|
2344
2705
|
]
|
|
2345
2706
|
},
|
|
2707
|
+
"wcs-midi": {
|
|
2708
|
+
"package": "midi",
|
|
2709
|
+
"observedAttributes": [
|
|
2710
|
+
"input",
|
|
2711
|
+
"output",
|
|
2712
|
+
"channel"
|
|
2713
|
+
],
|
|
2714
|
+
"inputs": {
|
|
2715
|
+
"input": "input",
|
|
2716
|
+
"output": "output",
|
|
2717
|
+
"channel": "channel",
|
|
2718
|
+
"sysex": "sysex",
|
|
2719
|
+
"auto": "auto"
|
|
2720
|
+
},
|
|
2721
|
+
"properties": [
|
|
2722
|
+
"message",
|
|
2723
|
+
"type",
|
|
2724
|
+
"channel",
|
|
2725
|
+
"note",
|
|
2726
|
+
"velocity",
|
|
2727
|
+
"control",
|
|
2728
|
+
"value",
|
|
2729
|
+
"devices",
|
|
2730
|
+
"connected",
|
|
2731
|
+
"permission",
|
|
2732
|
+
"granted",
|
|
2733
|
+
"denied",
|
|
2734
|
+
"unsupported",
|
|
2735
|
+
"error",
|
|
2736
|
+
"errorInfo"
|
|
2737
|
+
],
|
|
2738
|
+
"commands": [
|
|
2739
|
+
"request",
|
|
2740
|
+
"close",
|
|
2741
|
+
"send"
|
|
2742
|
+
]
|
|
2743
|
+
},
|
|
2346
2744
|
"wcs-network": {
|
|
2347
2745
|
"package": "network",
|
|
2746
|
+
"observedAttributes": [],
|
|
2348
2747
|
"inputs": {},
|
|
2349
2748
|
"properties": [
|
|
2350
2749
|
"effectiveType",
|
|
@@ -2357,6 +2756,7 @@ var BUILTIN_TAGS = {
|
|
|
2357
2756
|
},
|
|
2358
2757
|
"wcs-notify": {
|
|
2359
2758
|
"package": "notification",
|
|
2759
|
+
"observedAttributes": [],
|
|
2360
2760
|
"inputs": {
|
|
2361
2761
|
"notice": null,
|
|
2362
2762
|
"mode": "mode",
|
|
@@ -2392,6 +2792,7 @@ var BUILTIN_TAGS = {
|
|
|
2392
2792
|
},
|
|
2393
2793
|
"wcs-permission": {
|
|
2394
2794
|
"package": "permission",
|
|
2795
|
+
"observedAttributes": [],
|
|
2395
2796
|
"inputs": {
|
|
2396
2797
|
"name": "name",
|
|
2397
2798
|
"userVisibleOnly": "user-visible-only",
|
|
@@ -2408,6 +2809,9 @@ var BUILTIN_TAGS = {
|
|
|
2408
2809
|
},
|
|
2409
2810
|
"wcs-pip": {
|
|
2410
2811
|
"package": "picture-in-picture",
|
|
2812
|
+
"observedAttributes": [
|
|
2813
|
+
"target"
|
|
2814
|
+
],
|
|
2411
2815
|
"inputs": {
|
|
2412
2816
|
"target": "target"
|
|
2413
2817
|
},
|
|
@@ -2423,6 +2827,9 @@ var BUILTIN_TAGS = {
|
|
|
2423
2827
|
},
|
|
2424
2828
|
"wcs-pointer-lock": {
|
|
2425
2829
|
"package": "pointer-lock",
|
|
2830
|
+
"observedAttributes": [
|
|
2831
|
+
"target"
|
|
2832
|
+
],
|
|
2426
2833
|
"inputs": {
|
|
2427
2834
|
"target": "target"
|
|
2428
2835
|
},
|
|
@@ -2438,6 +2845,7 @@ var BUILTIN_TAGS = {
|
|
|
2438
2845
|
},
|
|
2439
2846
|
"wcs-raf": {
|
|
2440
2847
|
"package": "raf",
|
|
2848
|
+
"observedAttributes": [],
|
|
2441
2849
|
"inputs": {
|
|
2442
2850
|
"once": "once",
|
|
2443
2851
|
"repeat": "repeat",
|
|
@@ -2462,6 +2870,11 @@ var BUILTIN_TAGS = {
|
|
|
2462
2870
|
},
|
|
2463
2871
|
"wcs-resize": {
|
|
2464
2872
|
"package": "resize",
|
|
2873
|
+
"observedAttributes": [
|
|
2874
|
+
"target",
|
|
2875
|
+
"box",
|
|
2876
|
+
"round"
|
|
2877
|
+
],
|
|
2465
2878
|
"inputs": {
|
|
2466
2879
|
"target": "target",
|
|
2467
2880
|
"box": "box",
|
|
@@ -2485,6 +2898,7 @@ var BUILTIN_TAGS = {
|
|
|
2485
2898
|
},
|
|
2486
2899
|
"wcs-screen-orientation": {
|
|
2487
2900
|
"package": "screen-orientation",
|
|
2901
|
+
"observedAttributes": [],
|
|
2488
2902
|
"inputs": {},
|
|
2489
2903
|
"properties": [
|
|
2490
2904
|
"type",
|
|
@@ -2501,6 +2915,7 @@ var BUILTIN_TAGS = {
|
|
|
2501
2915
|
},
|
|
2502
2916
|
"wcs-share": {
|
|
2503
2917
|
"package": "share",
|
|
2918
|
+
"observedAttributes": [],
|
|
2504
2919
|
"inputs": {},
|
|
2505
2920
|
"properties": [
|
|
2506
2921
|
"value",
|
|
@@ -2515,6 +2930,7 @@ var BUILTIN_TAGS = {
|
|
|
2515
2930
|
},
|
|
2516
2931
|
"wcs-speak": {
|
|
2517
2932
|
"package": "speech",
|
|
2933
|
+
"observedAttributes": [],
|
|
2518
2934
|
"inputs": {
|
|
2519
2935
|
"say": null,
|
|
2520
2936
|
"rate": "rate",
|
|
@@ -2544,6 +2960,7 @@ var BUILTIN_TAGS = {
|
|
|
2544
2960
|
},
|
|
2545
2961
|
"wcs-listen": {
|
|
2546
2962
|
"package": "speech",
|
|
2963
|
+
"observedAttributes": [],
|
|
2547
2964
|
"inputs": {
|
|
2548
2965
|
"lang": "lang",
|
|
2549
2966
|
"continuous": "continuous",
|
|
@@ -2571,6 +2988,9 @@ var BUILTIN_TAGS = {
|
|
|
2571
2988
|
},
|
|
2572
2989
|
"wcs-sse": {
|
|
2573
2990
|
"package": "sse",
|
|
2991
|
+
"observedAttributes": [
|
|
2992
|
+
"url"
|
|
2993
|
+
],
|
|
2574
2994
|
"inputs": {
|
|
2575
2995
|
"url": "url",
|
|
2576
2996
|
"withCredentials": "with-credentials",
|
|
@@ -2595,6 +3015,10 @@ var BUILTIN_TAGS = {
|
|
|
2595
3015
|
},
|
|
2596
3016
|
"wcs-storage": {
|
|
2597
3017
|
"package": "storage",
|
|
3018
|
+
"observedAttributes": [
|
|
3019
|
+
"key",
|
|
3020
|
+
"type"
|
|
3021
|
+
],
|
|
2598
3022
|
"inputs": {
|
|
2599
3023
|
"key": null,
|
|
2600
3024
|
"type": null,
|
|
@@ -2617,6 +3041,7 @@ var BUILTIN_TAGS = {
|
|
|
2617
3041
|
},
|
|
2618
3042
|
"wcs-tilt": {
|
|
2619
3043
|
"package": "tilt",
|
|
3044
|
+
"observedAttributes": [],
|
|
2620
3045
|
"inputs": {},
|
|
2621
3046
|
"properties": [
|
|
2622
3047
|
"alpha",
|
|
@@ -2635,6 +3060,9 @@ var BUILTIN_TAGS = {
|
|
|
2635
3060
|
},
|
|
2636
3061
|
"wcs-timer": {
|
|
2637
3062
|
"package": "timer",
|
|
3063
|
+
"observedAttributes": [
|
|
3064
|
+
"interval"
|
|
3065
|
+
],
|
|
2638
3066
|
"inputs": {
|
|
2639
3067
|
"interval": "interval",
|
|
2640
3068
|
"once": "once",
|
|
@@ -2659,6 +3087,9 @@ var BUILTIN_TAGS = {
|
|
|
2659
3087
|
},
|
|
2660
3088
|
"wcs-upload": {
|
|
2661
3089
|
"package": "upload",
|
|
3090
|
+
"observedAttributes": [
|
|
3091
|
+
"url"
|
|
3092
|
+
],
|
|
2662
3093
|
"inputs": {
|
|
2663
3094
|
"url": null,
|
|
2664
3095
|
"method": null,
|
|
@@ -2687,6 +3118,10 @@ var BUILTIN_TAGS = {
|
|
|
2687
3118
|
},
|
|
2688
3119
|
"wcs-wakelock": {
|
|
2689
3120
|
"package": "wakelock",
|
|
3121
|
+
"observedAttributes": [
|
|
3122
|
+
"active",
|
|
3123
|
+
"type"
|
|
3124
|
+
],
|
|
2690
3125
|
"inputs": {
|
|
2691
3126
|
"active": "active",
|
|
2692
3127
|
"type": "type",
|
|
@@ -2704,6 +3139,9 @@ var BUILTIN_TAGS = {
|
|
|
2704
3139
|
},
|
|
2705
3140
|
"wcs-ws": {
|
|
2706
3141
|
"package": "websocket",
|
|
3142
|
+
"observedAttributes": [
|
|
3143
|
+
"url"
|
|
3144
|
+
],
|
|
2707
3145
|
"inputs": {
|
|
2708
3146
|
"url": "url",
|
|
2709
3147
|
"protocols": "protocols",
|
|
@@ -2733,6 +3171,9 @@ var BUILTIN_TAGS = {
|
|
|
2733
3171
|
},
|
|
2734
3172
|
"wcs-worker": {
|
|
2735
3173
|
"package": "worker",
|
|
3174
|
+
"observedAttributes": [
|
|
3175
|
+
"src"
|
|
3176
|
+
],
|
|
2736
3177
|
"inputs": {
|
|
2737
3178
|
"src": "src",
|
|
2738
3179
|
"type": "type",
|
|
@@ -2774,13 +3215,13 @@ var DOM_COMMON_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
2774
3215
|
]);
|
|
2775
3216
|
var STRUCTURAL_DIRECTIVES2 = /* @__PURE__ */ new Set(["for", "if", "elseif", "else"]);
|
|
2776
3217
|
var EMPTYISH_SEEDS = /* @__PURE__ */ new Set(["''", '""', "``", "null", "[]", "{}"]);
|
|
2777
|
-
function validateIoNodes(html, bindAttribute = "data-wcs", stateTagName = "wcs-state", locale) {
|
|
3218
|
+
function validateIoNodes(html, bindAttribute = "data-wcs", stateTagName = "wcs-state", locale, fileReader) {
|
|
2778
3219
|
const diagnostics = [];
|
|
2779
3220
|
const msgs = getMessages(locale);
|
|
2780
3221
|
const occurrences = findBuiltinTagOccurrences(html);
|
|
2781
3222
|
if (occurrences.length === 0) return diagnostics;
|
|
2782
3223
|
let statePaths = null;
|
|
2783
|
-
const getPaths = () => statePaths ??= getStatePathsFromHtml(html, stateTagName);
|
|
3224
|
+
const getPaths = () => statePaths ??= getStatePathsFromHtml(html, stateTagName, fileReader);
|
|
2784
3225
|
for (const occ of occurrences) {
|
|
2785
3226
|
const contract = BUILTIN_TAGS[occ.tagName];
|
|
2786
3227
|
if (contract.properties.length === 0 && contract.commands.length === 0 && Object.keys(contract.inputs).length === 0) continue;
|
|
@@ -3078,17 +3519,68 @@ function blankJsComments(code) {
|
|
|
3078
3519
|
return code.replace(/\/\*[\s\S]*?\*\//g, (m) => " ".repeat(m.length)).replace(/(^|[^:])\/\/[^\n]*/g, (m, pre) => pre + " ".repeat(m.length - pre.length));
|
|
3079
3520
|
}
|
|
3080
3521
|
|
|
3522
|
+
// src/service/watchDeclarationValidator.ts
|
|
3523
|
+
var STATE_NAME_SEPARATOR = "@";
|
|
3524
|
+
function validateWatchDeclarations(html, stateTagName = "wcs-state", locale) {
|
|
3525
|
+
const msgs = getMessages(locale);
|
|
3526
|
+
const out = [];
|
|
3527
|
+
for (const block of parseWcsScriptBlocks(html, stateTagName)) {
|
|
3528
|
+
const entries = analyzeWatchEntries(block.content);
|
|
3529
|
+
if (entries.length === 0) continue;
|
|
3530
|
+
const paths = analyzeStatePaths(block.content, block.stateName);
|
|
3531
|
+
const pathSet = new Set(paths.map((p) => p.path));
|
|
3532
|
+
for (const entry of entries) {
|
|
3533
|
+
const diagnostic = validateEntry(entry, pathSet, msgs);
|
|
3534
|
+
if (diagnostic === null) continue;
|
|
3535
|
+
out.push({
|
|
3536
|
+
code: diagnostic.code,
|
|
3537
|
+
start: block.contentStart + entry.start,
|
|
3538
|
+
end: block.contentStart + entry.end,
|
|
3539
|
+
message: diagnostic.message,
|
|
3540
|
+
severity: diagnostic.severity
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
return out;
|
|
3545
|
+
}
|
|
3546
|
+
function validateEntry(entry, pathSet, msgs) {
|
|
3547
|
+
const { key } = entry;
|
|
3548
|
+
const invalid = (message) => ({ code: WcsDiagnosticCode.WatchDeclarationInvalid, message, severity: "error" });
|
|
3549
|
+
if (key.includes(STATE_NAME_SEPARATOR)) {
|
|
3550
|
+
return invalid(msgs.watchKeyCrossState(key));
|
|
3551
|
+
}
|
|
3552
|
+
if (key.startsWith("$")) {
|
|
3553
|
+
return invalid(msgs.watchKeyReserved(key));
|
|
3554
|
+
}
|
|
3555
|
+
if (key.split(".").some((segment) => segment.length === 0)) {
|
|
3556
|
+
return invalid(msgs.watchKeyEmptySegment(key));
|
|
3557
|
+
}
|
|
3558
|
+
if (entry.definitelyNotFunction) {
|
|
3559
|
+
return invalid(msgs.watchHandlerNotFunction(key));
|
|
3560
|
+
}
|
|
3561
|
+
if (pathSet.size > 0 && !pathSet.has(key)) {
|
|
3562
|
+
return {
|
|
3563
|
+
code: WcsDiagnosticCode.WatchPathMissing,
|
|
3564
|
+
message: msgs.watchPathMissing(key),
|
|
3565
|
+
severity: "warning"
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
return null;
|
|
3569
|
+
}
|
|
3570
|
+
|
|
3081
3571
|
// src/core/validateDocument.ts
|
|
3082
3572
|
function validateDocument(text, options = {}) {
|
|
3083
3573
|
const bindAttribute = options.bindAttribute ?? "data-wcs";
|
|
3084
3574
|
const stateTagName = options.stateTagName ?? "wcs-state";
|
|
3085
3575
|
const locale = options.locale;
|
|
3576
|
+
const fileReader = options.fileReader;
|
|
3086
3577
|
const out = [];
|
|
3087
|
-
out.push(...validateBindings(text, bindAttribute, stateTagName, locale));
|
|
3088
|
-
out.push(...validateTemplateSyntax(text, stateTagName, bindAttribute, locale));
|
|
3089
|
-
out.push(...validateIoNodes(text, bindAttribute, stateTagName, locale));
|
|
3578
|
+
out.push(...validateBindings(text, bindAttribute, stateTagName, locale, fileReader));
|
|
3579
|
+
out.push(...validateTemplateSyntax(text, stateTagName, bindAttribute, locale, fileReader));
|
|
3580
|
+
out.push(...validateIoNodes(text, bindAttribute, stateTagName, locale, fileReader));
|
|
3090
3581
|
out.push(...validateDocumentEnv(text, locale));
|
|
3091
3582
|
out.push(...validateArrayMutations(text, stateTagName, locale));
|
|
3583
|
+
out.push(...validateWatchDeclarations(text, stateTagName, locale));
|
|
3092
3584
|
for (const d of validateStateTypes(text, stateTagName, locale)) {
|
|
3093
3585
|
out.push({ code: WcsDiagnosticCode.TypeAnnotation, start: d.start, end: d.end, message: d.message, severity: d.severity });
|
|
3094
3586
|
}
|
|
@@ -3672,7 +4164,8 @@ function runValidation(inputs, options = {}) {
|
|
|
3672
4164
|
const diagnosticsBySource = /* @__PURE__ */ new Map();
|
|
3673
4165
|
for (const input of inputs) {
|
|
3674
4166
|
if (input.kind === "html") {
|
|
3675
|
-
|
|
4167
|
+
const docOptions = input.fileReader !== void 0 ? { ...options, fileReader: input.fileReader } : options;
|
|
4168
|
+
diagnosticsBySource.set(input.source, validateDocument(input.text, docOptions));
|
|
3676
4169
|
}
|
|
3677
4170
|
}
|
|
3678
4171
|
const manifestInputs = inputs.filter((i) => i.kind === "manifest");
|
|
@@ -3716,6 +4209,29 @@ function runValidation(inputs, options = {}) {
|
|
|
3716
4209
|
function classify(path) {
|
|
3717
4210
|
return path.endsWith(".manifest.json") ? "manifest" : "html";
|
|
3718
4211
|
}
|
|
4212
|
+
function createFileReader(htmlPath, read = (p) => (0, import_node_fs.readFileSync)(p, "utf8")) {
|
|
4213
|
+
const base = (0, import_node_path.dirname)(htmlPath);
|
|
4214
|
+
const cache = /* @__PURE__ */ new Map();
|
|
4215
|
+
return (relativePath) => {
|
|
4216
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(relativePath) || relativePath.startsWith("/")) {
|
|
4217
|
+
return void 0;
|
|
4218
|
+
}
|
|
4219
|
+
if (cache.has(relativePath)) {
|
|
4220
|
+
return cache.get(relativePath);
|
|
4221
|
+
}
|
|
4222
|
+
let content;
|
|
4223
|
+
try {
|
|
4224
|
+
content = read((0, import_node_path.resolve)(base, relativePath));
|
|
4225
|
+
if (content.charCodeAt(0) === 65279) {
|
|
4226
|
+
content = content.slice(1);
|
|
4227
|
+
}
|
|
4228
|
+
} catch {
|
|
4229
|
+
content = void 0;
|
|
4230
|
+
}
|
|
4231
|
+
cache.set(relativePath, content);
|
|
4232
|
+
return content;
|
|
4233
|
+
};
|
|
4234
|
+
}
|
|
3719
4235
|
function parseArgs(argv) {
|
|
3720
4236
|
const options = {};
|
|
3721
4237
|
const files = [];
|
|
@@ -3755,7 +4271,8 @@ function main(argv) {
|
|
|
3755
4271
|
`);
|
|
3756
4272
|
return 2;
|
|
3757
4273
|
}
|
|
3758
|
-
|
|
4274
|
+
const kind = classify(path);
|
|
4275
|
+
inputs.push({ source: path, text, kind, fileReader: kind === "html" ? createFileReader(path) : void 0 });
|
|
3759
4276
|
}
|
|
3760
4277
|
const result = runValidation(inputs, { ...options, locale });
|
|
3761
4278
|
for (const line of result.lines) {
|
|
@@ -3773,6 +4290,7 @@ if (typeof require !== "undefined" && typeof module !== "undefined" && require.m
|
|
|
3773
4290
|
}
|
|
3774
4291
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3775
4292
|
0 && (module.exports = {
|
|
4293
|
+
createFileReader,
|
|
3776
4294
|
main,
|
|
3777
4295
|
parseArgs,
|
|
3778
4296
|
resolveCliLocale
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/lint",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "Static-contract validator CLI (wcs-validate) for wcstack data-wcs bindings and wcstack.manifest.json sidecars. Thin npm wrapper around the wcstack-intellisense validator core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|