@wcstack/typescript 4.10.0 → 4.11.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/index.esm.js +1 -1
- package/dist/schema-core.cjs +415 -27
- package/dist/wcs-schema.mjs +1 -1
- package/dist/wcs-tsc.mjs +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
package/dist/schema-core.cjs
CHANGED
|
@@ -58,7 +58,8 @@ var WcsDiagnosticCode = {
|
|
|
58
58
|
PathReadonly: "wcs/path-readonly",
|
|
59
59
|
PathReservedName: "wcs/path-reserved-name",
|
|
60
60
|
// lint の限界の告知(作者の誤りではない): `export default { … }` のトップレベルの spread が持ち込むキーは読めないので、
|
|
61
|
-
// stateSchema の無い state のパスは検査しない — それを spread の上で 1 回だけ言う。info
|
|
61
|
+
// stateSchema の無い state のパスは検査しない — それを spread の上で 1 回だけ言う。info。値の読めないキー(辿れない名前、
|
|
62
|
+
// 読めない spread を持つオブジェクトリテラルの種 `draft: { ...makeDraft() }`)の下を束ねたときも、キーの上で 1 回言う。
|
|
62
63
|
PathDynamicUnknown: "wcs/path-dynamic-unknown",
|
|
63
64
|
// lint の限界の告知(作者の誤りではない): 読めない `<wcs-state src>`(/ から始まるパス・URL・無いファイル)の state は
|
|
64
65
|
// パスもスクリプトの規則も検査しない — それを src の上で 1 回だけ言う。info(docs/seam-apps.md、prod-booking)。
|
|
@@ -264,6 +265,16 @@ var WcsDiagnosticCode = {
|
|
|
264
265
|
RouterOutletMisplaced: "wcs/router-outlet-misplaced",
|
|
265
266
|
// @wcstack/signals と /dom エントリの同一ページ混在(リアクティブコア二重化)。
|
|
266
267
|
SignalsDualEntry: "wcs/signals-dual-entry",
|
|
268
|
+
// wcstack を自分で読み込むページが、あるパッケージのタグ(`<wcs-upload>`・`<wcs-upload-header>`)を書くのに、その
|
|
269
|
+
// パッケージのスクリプトを読み込んでいない。要素は定義されず、束縛は待ち続け、コンソールにも何も出ない(継ぎ目アプリ
|
|
270
|
+
// homeroom — 保存が「送信中 0%」で止まった)。パッケージごとに 1 回、最初のタグに。読めないローカルのスクリプトがある
|
|
271
|
+
// ページ・autoloader の `@components/` が覆うタグ・wcstack を自分で読み込まないページ(断片・バンドラ)では黙る。warning。
|
|
272
|
+
TagPackageMissing: "wcs/tag-package-missing",
|
|
273
|
+
// ページの URL が、lint の規則の版(lint を作った @wcstack/state の版)より新しい minor の wcstack を固定している
|
|
274
|
+
// (`@wcstack/state@4.11.0` と lint 4.10.1)。古い lint は新しい規則を知らず、新しい正しい書き方を error にもする
|
|
275
|
+
// (homeroom — 4.2.0 の lint が 4.10 の `datetime(ja-JP,short,Asia/Tokyo)` を `wcs/filter-arity` に)。ページに 1 回、
|
|
276
|
+
// いちばん新しい固定に。版の無い URL・major だけの `@4`・lint の方が新しいときは黙る。warning。
|
|
277
|
+
LintVersionBehind: "wcs/lint-version-behind",
|
|
267
278
|
// `<wcs-route>`(またはレイアウトのテンプレート)の直下のテキストの `{{ }}`。最初に着いたルートでしか束ねられず、
|
|
268
279
|
// 遷移で入ったルートでは書いたままの文字が出る(router の README「Where route content lives」— docs/seam-apps.md、
|
|
269
280
|
// router-admin)。warning。
|
|
@@ -728,12 +739,12 @@ function loadManifest(artifact) {
|
|
|
728
739
|
for (const ns of NAMESPACE_KEYS) {
|
|
729
740
|
const nsObj = extensions[ns];
|
|
730
741
|
if (nsObj !== null && typeof nsObj === "object") {
|
|
731
|
-
const
|
|
732
|
-
if (typeof
|
|
742
|
+
const version3 = nsObj.version;
|
|
743
|
+
if (typeof version3 === "number" && version3 !== SUPPORTED_NAMESPACE_VERSION) {
|
|
733
744
|
ctx.add(
|
|
734
745
|
WcsDiagnosticCode.ManifestNamespaceVersion,
|
|
735
746
|
pointer("manifestExtensions", ns, "version"),
|
|
736
|
-
`Namespace "${ns}" version ${
|
|
747
|
+
`Namespace "${ns}" version ${version3} is unsupported (expected ${SUPPORTED_NAMESPACE_VERSION}).`,
|
|
737
748
|
"warning"
|
|
738
749
|
);
|
|
739
750
|
}
|
|
@@ -2803,7 +2814,11 @@ function getWcsManifest() {
|
|
|
2803
2814
|
};
|
|
2804
2815
|
}
|
|
2805
2816
|
|
|
2817
|
+
// ../state/package.json
|
|
2818
|
+
var version = "4.11.0";
|
|
2819
|
+
|
|
2806
2820
|
// src/service/wcsManifest.ts
|
|
2821
|
+
var ENGINE_VERSION = version;
|
|
2807
2822
|
var NATIVE_COMMANDS2 = getWcsManifest().nativeCommands ?? null;
|
|
2808
2823
|
function nativeCommandsOf(tag) {
|
|
2809
2824
|
if (NATIVE_COMMANDS2 === null) return null;
|
|
@@ -8531,10 +8546,10 @@ pp.readWord = function() {
|
|
|
8531
8546
|
}
|
|
8532
8547
|
return this.finishToken(type, word);
|
|
8533
8548
|
};
|
|
8534
|
-
var
|
|
8549
|
+
var version2 = "8.18.0";
|
|
8535
8550
|
Parser.acorn = {
|
|
8536
8551
|
Parser,
|
|
8537
|
-
version,
|
|
8552
|
+
version: version2,
|
|
8538
8553
|
defaultOptions,
|
|
8539
8554
|
Position,
|
|
8540
8555
|
SourceLocation,
|
|
@@ -10077,19 +10092,100 @@ function pushDataPropertyPaths(prop, paths, typedefs, scope) {
|
|
|
10077
10092
|
}
|
|
10078
10093
|
function pushDataPropertyPathsAt(path, prop, paths, depth, typedefs, scope) {
|
|
10079
10094
|
const followed = scope === void 0 ? null : followValue(prop, scope);
|
|
10095
|
+
let candidate;
|
|
10096
|
+
let unread = null;
|
|
10080
10097
|
if (followed === null) {
|
|
10081
|
-
|
|
10082
|
-
|
|
10098
|
+
candidate = { path, kind: "data", typeHint: prop.typeHint, rawInitial: prop.value?.trim() };
|
|
10099
|
+
paths.push(candidate);
|
|
10100
|
+
unread = pushLiteralStructurePaths(path, prop, paths, depth, typedefs, scope);
|
|
10083
10101
|
} else {
|
|
10084
10102
|
const value = followed.value;
|
|
10085
10103
|
const shapeHint = value === null ? void 0 : inferTypeHint(value.text);
|
|
10086
10104
|
const typeHint = prop.typeHint ?? (shapeHint === "array" || shapeHint === "object" ? shapeHint : void 0);
|
|
10087
10105
|
const opaque = (value === null || !isReadableLiteral(value.text)) && prop.declaredType === void 0 ? { opaque: { ...followed.name !== void 0 ? { name: followed.name } : {}, ...followed.from !== void 0 ? { from: followed.from } : {} } } : {};
|
|
10088
|
-
|
|
10089
|
-
|
|
10106
|
+
candidate = withHint({ path, kind: "data", rawInitial: prop.value?.trim(), ...opaque }, typeHint);
|
|
10107
|
+
paths.push(candidate);
|
|
10108
|
+
if (value !== null) unread = pushLiteralStructurePaths(path, { ...prop, value: value.text }, paths, depth, typedefs, value.scope);
|
|
10109
|
+
}
|
|
10110
|
+
if (unread !== null && candidate.opaque === void 0 && prop.declaredType === void 0) {
|
|
10111
|
+
candidate.opaque = { spread: unread.text, ...unread.from !== void 0 ? { from: unread.from } : {} };
|
|
10090
10112
|
}
|
|
10091
10113
|
if (prop.declaredType !== void 0) pushDeclaredShapePaths(path, prop.declaredType, paths, depth, typedefs);
|
|
10092
10114
|
}
|
|
10115
|
+
var MAX_SPREAD_HOPS = 8;
|
|
10116
|
+
function objectLiteralKeys(content, scope, shorthands, hops = 0) {
|
|
10117
|
+
const explicit = parseTopLevelProperties(content);
|
|
10118
|
+
const props = shorthands ? withShorthands(content, explicit) : explicit;
|
|
10119
|
+
const spreads = findObjectSpreads(content);
|
|
10120
|
+
if (spreads.length === 0) {
|
|
10121
|
+
return { keys: props.filter((p) => p.kind === "data").map((prop) => ({ prop, scope })), unread: null };
|
|
10122
|
+
}
|
|
10123
|
+
const items = [
|
|
10124
|
+
...props.map((prop) => ({ at: prop.nameStart ?? 0, prop })),
|
|
10125
|
+
...spreads.map((s) => ({ at: s.start, spread: s.text }))
|
|
10126
|
+
].sort((a, b) => a.at - b.at);
|
|
10127
|
+
const keys = /* @__PURE__ */ new Map();
|
|
10128
|
+
const put = (key) => {
|
|
10129
|
+
keys.delete(key.prop.name);
|
|
10130
|
+
keys.set(key.prop.name, key);
|
|
10131
|
+
};
|
|
10132
|
+
let unread = null;
|
|
10133
|
+
for (const item of items) {
|
|
10134
|
+
if ("prop" in item) {
|
|
10135
|
+
put({ prop: item.prop, scope });
|
|
10136
|
+
continue;
|
|
10137
|
+
}
|
|
10138
|
+
const literal2 = hops < MAX_SPREAD_HOPS ? spreadLiteral(item.spread, scope) : { unread: { text: item.spread } };
|
|
10139
|
+
if ("unread" in literal2) {
|
|
10140
|
+
unread ??= literal2.unread;
|
|
10141
|
+
continue;
|
|
10142
|
+
}
|
|
10143
|
+
if (literal2.text === null) continue;
|
|
10144
|
+
const nested = objectLiteralKeys(extractObjectContent(literal2.text), literal2.scope, true, hops + 1);
|
|
10145
|
+
for (const key of nested.keys) put(key);
|
|
10146
|
+
if (nested.unread !== null) unread ??= { text: item.spread };
|
|
10147
|
+
}
|
|
10148
|
+
return { keys: [...keys.values()].filter((k) => k.prop.kind === "data"), unread };
|
|
10149
|
+
}
|
|
10150
|
+
function spreadLiteral(spread, scope) {
|
|
10151
|
+
const expr = unwrapFreeze(spread.replace(/^\.\.\./, ""));
|
|
10152
|
+
if (expr === "null" || expr === "undefined") return { text: null };
|
|
10153
|
+
if (isObjectLiteral(expr)) return { text: expr, scope };
|
|
10154
|
+
if (!isBindingName(expr) || scope === void 0) return { unread: { text: spread } };
|
|
10155
|
+
const from = scope.importOf(expr);
|
|
10156
|
+
const unread = { unread: { text: spread, ...from !== void 0 ? { from } : {} } };
|
|
10157
|
+
let current2 = scope.resolveName(expr);
|
|
10158
|
+
for (let hops = 0; current2 !== null && hops < MAX_SPREAD_HOPS; hops++) {
|
|
10159
|
+
const inner = unwrapFreeze(current2.text);
|
|
10160
|
+
if (isObjectLiteral(inner)) return { text: inner, scope: current2.scope };
|
|
10161
|
+
if (!isBindingName(inner)) return unread;
|
|
10162
|
+
current2 = current2.scope.resolveName(inner);
|
|
10163
|
+
}
|
|
10164
|
+
return unread;
|
|
10165
|
+
}
|
|
10166
|
+
function findObjectSpreads(content) {
|
|
10167
|
+
const scan = maskCommentsAndStrings(content).replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/g, (c) => " ".repeat(c.length));
|
|
10168
|
+
const out = [];
|
|
10169
|
+
let depth = 0;
|
|
10170
|
+
let start = 0;
|
|
10171
|
+
for (let i = 0; i <= scan.length; i++) {
|
|
10172
|
+
const ch = scan[i];
|
|
10173
|
+
if (ch === "{" || ch === "[" || ch === "(") {
|
|
10174
|
+
depth++;
|
|
10175
|
+
} else if (ch === "}" || ch === "]" || ch === ")") {
|
|
10176
|
+
depth--;
|
|
10177
|
+
} else if (ch === "," && depth === 0 || i === scan.length) {
|
|
10178
|
+
const segment = scan.slice(start, i);
|
|
10179
|
+
const lead = segment.length - segment.trimStart().length;
|
|
10180
|
+
if (segment.trimStart().startsWith("...")) {
|
|
10181
|
+
const end = start + segment.trimEnd().length;
|
|
10182
|
+
out.push({ start: start + lead, text: content.slice(start + lead, end) });
|
|
10183
|
+
}
|
|
10184
|
+
start = i + 1;
|
|
10185
|
+
}
|
|
10186
|
+
}
|
|
10187
|
+
return out;
|
|
10188
|
+
}
|
|
10093
10189
|
var WORD_LITERALS = /* @__PURE__ */ new Set(["true", "false", "null", "undefined", "NaN", "Infinity", "this"]);
|
|
10094
10190
|
function isBindingName(text3) {
|
|
10095
10191
|
return /^[$A-Za-z_][$\w]*$/.test(text3) && !WORD_LITERALS.has(text3);
|
|
@@ -10157,23 +10253,30 @@ function pushDeclaredShapePaths(path, type, paths, depth, typedefs) {
|
|
|
10157
10253
|
}
|
|
10158
10254
|
function pushLiteralStructurePaths(path, prop, paths, depth, typedefs, scope) {
|
|
10159
10255
|
if (prop.value && isArrayLiteral(prop.value)) {
|
|
10160
|
-
|
|
10256
|
+
const row = { path: `${path}.*`, kind: "list" };
|
|
10257
|
+
paths.push(row);
|
|
10161
10258
|
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number" });
|
|
10162
|
-
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
10163
|
-
|
|
10164
|
-
|
|
10259
|
+
if (depth >= MAX_OBJECT_NEST_DEPTH) return null;
|
|
10260
|
+
const first = firstRowObjectContent(prop.value);
|
|
10261
|
+
if (first === null) return null;
|
|
10262
|
+
const { keys, unread } = objectLiteralKeys(first, scope, false);
|
|
10263
|
+
for (const key of keys) {
|
|
10264
|
+
pushDataPropertyPathsAt(`${path}.*.${key.prop.name}`, key.prop, paths, depth + 1, typedefs, key.scope);
|
|
10165
10265
|
}
|
|
10166
|
-
|
|
10266
|
+
if (unread !== null && prop.declaredType === void 0) {
|
|
10267
|
+
row.opaque = { spread: unread.text, ...unread.from !== void 0 ? { from: unread.from } : {} };
|
|
10268
|
+
}
|
|
10269
|
+
return null;
|
|
10167
10270
|
}
|
|
10168
10271
|
if (prop.value && isObjectLiteral(prop.value)) {
|
|
10169
|
-
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
10170
|
-
const
|
|
10171
|
-
const
|
|
10172
|
-
|
|
10173
|
-
if (childProp.kind !== "data") continue;
|
|
10174
|
-
pushDataPropertyPathsAt(`${path}.${childProp.name}`, childProp, paths, depth + 1, typedefs, scope);
|
|
10272
|
+
if (depth >= MAX_OBJECT_NEST_DEPTH) return null;
|
|
10273
|
+
const { keys, unread } = objectLiteralKeys(extractObjectContent(prop.value), scope, true);
|
|
10274
|
+
for (const key of keys) {
|
|
10275
|
+
pushDataPropertyPathsAt(`${path}.${key.prop.name}`, key.prop, paths, depth + 1, typedefs, key.scope);
|
|
10175
10276
|
}
|
|
10277
|
+
return unread;
|
|
10176
10278
|
}
|
|
10279
|
+
return null;
|
|
10177
10280
|
}
|
|
10178
10281
|
function analyzeJsonPaths(jsonString) {
|
|
10179
10282
|
let data2;
|
|
@@ -10446,15 +10549,18 @@ function extractObjectContent(value) {
|
|
|
10446
10549
|
if (start === -1) return "";
|
|
10447
10550
|
return extractBracedContent(trimmed, scan, start);
|
|
10448
10551
|
}
|
|
10449
|
-
function
|
|
10552
|
+
function firstRowObjectContent(value) {
|
|
10450
10553
|
const trimmed = value.trim();
|
|
10451
|
-
if (!trimmed.startsWith("[")) return
|
|
10554
|
+
if (!trimmed.startsWith("[")) return null;
|
|
10452
10555
|
const scan = maskCommentsAndStrings(trimmed);
|
|
10453
10556
|
let first = 1;
|
|
10454
10557
|
while (first < scan.length && /\s/.test(scan[first])) first++;
|
|
10455
|
-
if (scan[first] !== "{") return
|
|
10456
|
-
|
|
10457
|
-
|
|
10558
|
+
if (scan[first] !== "{") return null;
|
|
10559
|
+
return extractBracedContent(trimmed, scan, first);
|
|
10560
|
+
}
|
|
10561
|
+
function extractArrayElementDataProperties(value) {
|
|
10562
|
+
const content = firstRowObjectContent(value);
|
|
10563
|
+
return content === null ? [] : parseTopLevelProperties(content).filter((prop) => prop.kind === "data");
|
|
10458
10564
|
}
|
|
10459
10565
|
function normalizeJsDocType(typeExpr) {
|
|
10460
10566
|
const parts = typeExpr.split("|").map((p) => p.trim());
|
|
@@ -11837,6 +11943,7 @@ var ja = {
|
|
|
11837
11943
|
stateSrcUnread: (src) => `"${src}" \u3092\u8AAD\u3081\u306A\u3044\u306E\u3067\u3001\u3053\u306E state \u306E\u30D1\u30B9\u3082\u30B9\u30AF\u30EA\u30D7\u30C8\u306E\u898F\u5247\u3082\u691C\u67FB\u3057\u3066\u3044\u307E\u305B\u3093\u3002src \u306F\u3053\u306E\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9\u3067\u8AAD\u307F\u307E\u3059\uFF08URL \u306F\u8AAD\u307E\u305A\u3001/ \u304B\u3089\u59CB\u307E\u308B\u30D1\u30B9\u306F wcs-validate --root=<\u30B5\u30A4\u30C8\u306E\u30EB\u30FC\u30C8> \u306E\u3068\u304D\u3060\u3051\u305D\u306E\u4E0B\u3067\u8AAD\u307F\u307E\u3059\uFF09\u3002\u30B5\u30FC\u30D0\u30FC\u3068\u540C\u3058\u4E26\u3073\u306B\u7F6E\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u3001\u3053\u306E\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9\u3067\u6307\u3059\u304B\u3001--root \u3092\u6E21\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
11838
11944
|
pathDynamicUnknownValue: (path, n, name, from) => `"${path}" \u306E\u5024${name === void 0 ? "" : from === void 0 ? `\uFF08${name}\uFF09` : `\uFF08${name}\u3002"${from}" \u304B\u3089 import\uFF09`}\u306F\u9759\u7684\u306B\u8AAD\u3081\u306A\u3044\u306E\u3067\u3001\u305D\u306E\u4E0B\u306B\u675F\u306D\u305F\u30D1\u30B9\uFF08${n} \u4EF6\uFF09\u306F\u691C\u67FB\u3057\u3066\u3044\u307E\u305B\u3093\u3002\u30AD\u30FC\u306B JSDoc \u306E @type \u2014 \u5F62\u304B\u3001\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30EA\u30C6\u30E9\u30EB\u3092\u6307\u3059 typeof import("./file.js").name\uFF08\u8F9E\u66F8\u306A\u3089\u5168\u90E8\u306E\u30AD\u30FC\u3092\u6301\u3064\u65E2\u5B9A\u306E\u8A00\u8A9E\u306E\u30D5\u30A1\u30A4\u30EB\uFF09\u2014 \u3092\u4ED8\u3051\u308B\u304B\u3001wcstack.manifest.json \u306E stateSchema \u306B\u5BA3\u8A00\u3059\u308B\u3068\u691C\u67FB\u3055\u308C\u307E\u3059`,
|
|
11839
11945
|
pathDynamicUnknownSpread: (sp) => `${sp} \u304C\u6301\u3061\u8FBC\u3080\u30AD\u30FC\u306F\u9759\u7684\u306B\u8AAD\u3081\u306A\u3044\u306E\u3067\u3001\u3053\u306E state \u306E\u30D1\u30B9\u306F\u691C\u67FB\u3057\u3066\u3044\u307E\u305B\u3093\uFF08\u675F\u7E1B\u30FBgetter \u306E\u4E2D\u306E\u8AAD\u307F\u30FB$watch \u306E\u30AD\u30FC\uFF09\u3002\u30AD\u30FC\u3092 wcstack.manifest.json \u306E stateSchema \u306B\u5BA3\u8A00\u3059\u308B\u3068\u691C\u67FB\u3055\u308C\u307E\u3059\u3002npx wcs-schema\uFF08@wcstack/typescript\uFF09\u304C state \u306E\u578B\uFF08JSDoc\u30FBTypeScript\uFF09\u304B\u3089\u4F5C\u308C\u307E\u3059`,
|
|
11946
|
+
pathDynamicUnknownObjectSpread: (path, n, sp, from) => `${sp}${from === void 0 ? "" : `\uFF08"${from}" \u304B\u3089 import\uFF09`}\u304C "${path}" \u306B\u6301\u3061\u8FBC\u3080\u30AD\u30FC\u306F\u9759\u7684\u306B\u8AAD\u3081\u306A\u3044\u306E\u3067\u3001\u305D\u306E\u4E0B\u306B\u675F\u306D\u305F\u30D1\u30B9\uFF08${n} \u4EF6\uFF09\u306F\u691C\u67FB\u3057\u3066\u3044\u307E\u305B\u3093\u3002\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u30EA\u30C6\u30E9\u30EB\u3092\u675F\u7E1B\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u306E const \u3092 spread \u3059\u308B\u304B\u3001\u30AD\u30FC\u306B\u5F62\u3092\u8868\u3059 JSDoc \u306E @type \u3092\u4ED8\u3051\u308B\u304B\u3001wcstack.manifest.json \u306E stateSchema \u306B\u5BA3\u8A00\u3059\u308B\u3068\u691C\u67FB\u3055\u308C\u307E\u3059`,
|
|
11840
11947
|
pathReadonlyTwoWay: (p, prop) => `"${p}" \u306F setter \u306E\u7121\u3044 getter \u3067\u3059\u304C\u3001${prop}: \u306F\u8AAD\u8005\u306E\u5165\u529B\u3092\u66F8\u304D\u623B\u3059\u306E\u3067\u3001\u5165\u529B\u306E\u305F\u3073\u306B\u66F8\u304D\u8FBC\u307F\u304C\u5931\u6557\u3057\u307E\u3059\uFF08"${p}" is a getter without a setter\uFF09\u3002setter \u3092\u8DB3\u3059\uFF08set "${p}"(v) { \u2026 }\uFF09\u304B\u3001#ro \u3067\u4E00\u65B9\u5411\u306B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08${prop}#ro: ${p}\uFF09`,
|
|
11841
11948
|
submitWithoutPrevent: (h) => `onsubmit \u306B #prevent \u304C\u7121\u304F\u3001"${h}" \u3082 preventDefault \u3092\u547C\u3073\u307E\u305B\u3093\u3002\u30D6\u30E9\u30A6\u30B6\u306F\u30D5\u30A9\u30FC\u30E0\u3082\u9001\u308B\u306E\u3067\u3001\u30DA\u30FC\u30B8\u304C\u8AAD\u307F\u76F4\u3055\u308C\u308B\u304B\u3001router \u304C\u3042\u308C\u3070 GET \u304C\u6B04\u306E\u5024\uFF08\u30D1\u30B9\u30EF\u30FC\u30C9\u3082\uFF09\u3092 URL \u3068\u5C65\u6B74\u306B\u8F09\u305B\u307E\u3059\u3002onsubmit#prevent: ${h} \u3068\u66F8\u304F\u304B\u3001\u30CF\u30F3\u30C9\u30E9\u3067 event.preventDefault() \u3092\u547C\u3093\u3067\u304F\u3060\u3055\u3044`,
|
|
11842
11949
|
getterUntrackedRead: (root, sp) => `\u3053\u3053\u3067\u8FFD\u8DE1\u3055\u308C\u308B\u306E\u306F "${root}" \u3060\u3051\u3067\u3059\u3002"${sp}" \u304C\u5909\u308F\u3063\u3066\u3082\u3053\u306E getter \u306F\u518D\u8A55\u4FA1\u3055\u308C\u307E\u305B\u3093\uFF08\u30D1\u30B9\u8AAD\u307F\u53D6\u308A\u306E\u5148\u306E\u7D20\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u30A2\u30AF\u30BB\u30B9\u306F\u8FFD\u8DE1\u3055\u308C\u306A\u3044\uFF09\u3002this["${sp}"] \u3067\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044`,
|
|
@@ -11904,6 +12011,8 @@ var ja = {
|
|
|
11904
12011
|
routerOutletMisplaced: () => `\u3053\u306E <wcs-outlet> \u306F <wcs-router> \u306E\u76F4\u5F8C\u306B\u7121\u3044\u306E\u3067\u3001\u3069\u306E router \u3082\u4F7F\u3044\u307E\u305B\u3093\u3002router \u306F\u81EA\u5206\u306E\u76F4\u5F8C\u306E\u8981\u7D20\u3060\u3051\u3092 outlet \u3068\u3057\u3066\u4F7F\u3044\u3001\u305D\u3053\u306B <wcs-outlet> \u304C\u7121\u3051\u308C\u3070\u81EA\u524D\u306E outlet \u3092\u4F5C\u308A\u307E\u3059\u3002\u30EB\u30FC\u30C8\u306F router \u306E\u76F4\u5F8C\u306B\u63CF\u304B\u308C\u3001\u3053\u306E outlet \u306F\u7A7A\u306E\u307E\u307E\u3067\u3059 \u2014 <wcs-router> \u306E\u76F4\u5F8C\u3078\u79FB\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
11905
12012
|
signalsDualEntry: () => `@wcstack/signals \u3068 @wcstack/signals/dom \u304C\u540C\u4E00\u30DA\u30FC\u30B8\u304B\u3089 import \u3055\u308C\u3066\u3044\u307E\u3059\u3002CDN \u3067\u306F\u5404\u30A8\u30F3\u30C8\u30EA\u304C\u81EA\u5DF1\u5B8C\u7D50\u30D0\u30F3\u30C9\u30EB\u306E\u305F\u3081\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u30B3\u30A2\u304C\u4E8C\u91CD\u5316\u3057\u3001\u5883\u754C\u3067\u53CD\u5FDC\u304C\u58CA\u308C\u307E\u3059 \u2014 \u3059\u3079\u3066 /dom \u30A8\u30F3\u30C8\u30EA\u304B\u3089 import \u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
11906
12013
|
signalsImportMapBoth: () => `\u3053\u306E import map \u306F @wcstack/signals \u3068 @wcstack/signals/dom \u306E\u4E21\u65B9\u3092\u5272\u308A\u5F53\u3066\u3066\u3044\u307E\u3059\u3002CDN \u3067\u306F\u5404\u30A8\u30F3\u30C8\u30EA\u304C\u30EA\u30A2\u30AF\u30C6\u30A3\u30D6\u30B3\u30A2\u3092\u6301\u3064\u306E\u3067\u3001@wcstack/signals \u3092 import \u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\uFF08\u3053\u306E\u30DA\u30FC\u30B8\u306E\u3082\u306E\u3067\u3082\u3001\u8AAD\u307F\u8FBC\u3080 .js \u3067\u3082\uFF09\u304C 2 \u3064\u76EE\u306E\u30B3\u30A2\u3092\u6301\u3061\u3001\u5883\u754C\u3067\u53CD\u5FDC\u304C\u58CA\u308C\u307E\u3059\u3002@wcstack/signals/dom \u3060\u3051\u3092\u5272\u308A\u5F53\u3066\u3066\u304F\u3060\u3055\u3044\uFF08\u30B3\u30A2\u306E\u5168\u90E8\u3092 export \u3057\u307E\u3059\uFF09`,
|
|
12014
|
+
tagPackageMissing: (tags, pkg, url) => `${tags.map((t) => `<${t}>`).join("\u30FB")} \u306F ${pkg} \u306E\u30BF\u30B0\u3067\u3059\u304C\u3001\u3053\u306E\u30DA\u30FC\u30B8\u306F ${pkg} \u306E\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u8AAD\u307F\u8FBC\u3093\u3067\u3044\u307E\u305B\u3093\u3002\u8981\u7D20\u306F\u5B9A\u7FA9\u3055\u308C\u306A\u3044\u306E\u3067\u3001\u305D\u306E\u675F\u7E1B\u306F\u5F85\u3061\u7D9A\u3051\u3066\u4F55\u3082\u8D77\u304D\u305A\u3001\u30B3\u30F3\u30BD\u30FC\u30EB\u306B\u3082\u4F55\u3082\u51FA\u307E\u305B\u3093 \u2014 <script type="module" src="${url}"></script> \u3067\u8AAD\u307F\u8FBC\u3093\u3067\u304F\u3060\u3055\u3044`,
|
|
12015
|
+
lintVersionBehind: (spec, version3, minor, lint) => `\u3053\u306E\u30DA\u30FC\u30B8\u306F ${spec} \u3092\u56FA\u5B9A\u3057\u3066\u3044\u307E\u3059\u304C\u3001\u3053\u306E lint \u306E\u898F\u5247\uFF08@wcstack ${lint}\uFF09\u3088\u308A\u65B0\u3057\u3044 minor \u3067\u3059\u3002${minor} \u3067\u52A0\u308F\u3063\u305F\u898F\u5247\u306F\u691C\u67FB\u3055\u308C\u305A\u3001${minor} \u306E\u6B63\u3057\u3044\u66F8\u304D\u65B9\u304C error \u306B\u306A\u308B\u3053\u3068\u3082\u3042\u308A\u307E\u3059 \u2014 @wcstack/lint \u3092 ${version3} \u306B\u4E0A\u3052\u3066\u304F\u3060\u3055\u3044\uFF08npm i -D @wcstack/lint@${version3}\u3002VS Code \u306E\u62E1\u5F35\u306F ${minor} \u306B\u5BFE\u5FDC\u3059\u308B\u7248\u3078\uFF09`,
|
|
11907
12016
|
routeBareMustache: (inLayout) => inLayout ? `\u30EC\u30A4\u30A2\u30A6\u30C8\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u306E\u76F4\u4E0B\u306E\u30C6\u30AD\u30B9\u30C8\u306E {{ }} \u306F\u3001\u9077\u79FB\u3067\u306F\u675F\u306D\u3089\u308C\u307E\u305B\u3093 \u2014 \u8981\u7D20\u3067\u5305\u3093\u3067\u304F\u3060\u3055\u3044\uFF08<span>{{ \u2026 }}</span>\uFF09` : `<wcs-route> \u306E\u76F4\u4E0B\u306E\u30C6\u30AD\u30B9\u30C8\u306E {{ }} \u306F\u3001\u6700\u521D\u306B\u7740\u3044\u305F\u30EB\u30FC\u30C8\u3067\u3057\u304B\u675F\u306D\u3089\u308C\u307E\u305B\u3093\u3002\u9077\u79FB\u3067\u5165\u3063\u305F\u30EB\u30FC\u30C8\u3067\u306F\u66F8\u3044\u305F\u307E\u307E\u306E\u6587\u5B57\u304C\u51FA\u307E\u3059 \u2014 \u8981\u7D20\u3067\u5305\u3093\u3067\u304F\u3060\u3055\u3044\uFF08<h1>{{ \u2026 }}</h1>\uFF09`,
|
|
11908
12017
|
layoutSlotMissing: (l) => `\u30EC\u30A4\u30A2\u30A6\u30C8 "${l}" \u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u306B\u65E2\u5B9A\u306E <slot>\uFF08name \u306E\u7121\u3044\u3082\u306E\uFF09\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u3053\u306E <wcs-layout> \u306E\u540D\u524D\u4ED8\u304D\u30B9\u30ED\u30C3\u30C8\u306E\u5916\u306E\u4E2D\u8EAB\uFF08\u5165\u308C\u5B50\u306E\u30EB\u30FC\u30C8\u3068\u305D\u306E\u30DA\u30FC\u30B8\uFF09\u306F\u8868\u793A\u3055\u308C\u307E\u305B\u3093 \u2014 \u30DA\u30FC\u30B8\u3092\u7F6E\u304F\u5834\u6240\u306B <slot></slot> \u3092\u66F8\u3044\u3066\u304F\u3060\u3055\u3044`,
|
|
11909
12018
|
namedStateAttrDeprecated: (name) => `name \u5C5E\u6027\u306F v2 \u3067\u64A4\u53BB\u3055\u308C\u307E\u3057\u305F\uFF081 root 1 \u30C4\u30EA\u30FC\uFF09\u3002\u30EB\u30FC\u30C8\u30C4\u30EA\u30FC\u3078\u306E\u30DE\u30A6\u30F3\u30C8 <wcs-state mount="${name}"> \u306B\u7F6E\u304D\u63DB\u3048\u3001\u30D1\u30B9\u306F "${name}.<path>" \u3067\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\uFF08docs/state-mount-design.md \xA79\uFF09`,
|
|
@@ -12050,6 +12159,7 @@ var en = {
|
|
|
12050
12159
|
stateSrcUnread: (src) => `"${src}" cannot be read, so this state's paths and script rules are not checked. A src is read relative to this file (a URL is not read, and a path from / only under wcs-validate --root=<the site's root>): point it at the file laid out as on the server, relative to this file, or pass --root`,
|
|
12051
12160
|
pathDynamicUnknownValue: (path, n, name, from) => `The value of "${path}"${name === void 0 ? "" : from === void 0 ? ` (${name})` : ` (${name}, imported from "${from}")`} cannot be read statically, so the ${n === 1 ? "path" : `${n} paths`} bound under it ${n === 1 ? "is" : "are"} not checked. Give the key a JSDoc @type \u2014 its shape, or typeof import("./file.js").name for a module's literal (for a dictionary, the default language's file, which has every key) \u2014 or declare it in the stateSchema of wcstack.manifest.json to have them checked`,
|
|
12052
12161
|
pathDynamicUnknownSpread: (sp) => `The keys ${sp} brings in cannot be read statically, so this state's paths are not checked (bindings, reads in getters, $watch keys). Declare the keys in the stateSchema of wcstack.manifest.json to have them checked; npx wcs-schema (@wcstack/typescript) derives it from the state's types (JSDoc or TypeScript)`,
|
|
12162
|
+
pathDynamicUnknownObjectSpread: (path, n, sp, from) => `The keys ${sp}${from === void 0 ? "" : ` (imported from "${from}")`} brings into "${path}" cannot be read statically, so the ${n === 1 ? "path" : `${n} paths`} bound under it ${n === 1 ? "is" : "are"} not checked. Spread a const of the module bound to an object literal, give the key a JSDoc @type with its shape, or declare it in the stateSchema of wcstack.manifest.json to have them checked`,
|
|
12053
12163
|
pathReadonlyTwoWay: (p, prop) => `"${p}" is a getter without a setter, and ${prop}: writes back what the reader enters, so every edit fails ("${p}" is a getter without a setter). Add a setter (set "${p}"(v) { \u2026 }), or bind it one way with #ro (${prop}#ro: ${p})`,
|
|
12054
12164
|
submitWithoutPrevent: (h) => `onsubmit has no #prevent and "${h}" does not call preventDefault, so the browser submits the form too: the page reloads, or with the router a GET puts the fields (a password too) in the URL and the history. Write onsubmit#prevent: ${h}, or call event.preventDefault() in the handler`,
|
|
12055
12165
|
getterUntrackedRead: (root, sp) => `Only "${root}" is tracked here: the getter is not re-evaluated when "${sp}" changes (plain property access after a path read is not tracked). Read this["${sp}"] instead`,
|
|
@@ -12117,6 +12227,8 @@ var en = {
|
|
|
12117
12227
|
routerOutletMisplaced: () => `This <wcs-outlet> is not right after a <wcs-router>, so no router uses it: a router uses only the element right after it as its outlet, and makes an outlet of its own there when that is not a <wcs-outlet>. The routes render right after the router and this outlet stays empty \u2014 move it right after the <wcs-router>`,
|
|
12118
12228
|
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`,
|
|
12119
12229
|
signalsImportMapBoth: () => `This import map maps both @wcstack/signals and @wcstack/signals/dom. On a CDN each entry carries its own reactive core, so a module that imports @wcstack/signals \u2014 this page's, or a .js file it loads \u2014 gets a second core and reactivity breaks at the seam. Map only @wcstack/signals/dom (it exports the whole core)`,
|
|
12230
|
+
tagPackageMissing: (tags, pkg, url) => `${tags.map((t) => `<${t}>`).join(", ")} ${tags.length === 1 ? "is a tag" : "are tags"} of ${pkg}, and this page loads no script of ${pkg}: the element is never defined, so its bindings wait and nothing happens, without a word in the console. Load it with <script type="module" src="${url}"></script>`,
|
|
12231
|
+
lintVersionBehind: (spec, version3, minor, lint) => `This page pins ${spec}, a newer minor than the rules of this lint (@wcstack ${lint}): what ${minor} added is not checked, and correct ${minor} syntax can be reported as an error. Upgrade @wcstack/lint to ${version3} (npm i -D @wcstack/lint@${version3}; the VS Code extension to its release for ${minor})`,
|
|
12120
12232
|
routeBareMustache: (inLayout) => inLayout ? `{{ }} in text directly under a layout template is not bound on a navigation. Wrap it in an element (<span>{{ \u2026 }}</span>)` : `{{ }} in text directly under <wcs-route> is bound only on the landing route: a route entered by navigation shows it as written. Wrap it in an element (<h1>{{ \u2026 }}</h1>)`,
|
|
12121
12233
|
layoutSlotMissing: (l) => `The template of layout "${l}" has no default <slot> (one without a name), so what this <wcs-layout> holds outside the named slots \u2014 the nested routes and their pages \u2014 is not shown. Put a <slot></slot> where the page goes`,
|
|
12122
12234
|
namedStateAttrDeprecated: (name) => `The "name" attribute was removed in v2 \u2014 there is a single state tree per root. Mount this state onto the tree instead: <wcs-state mount="${name}"> and read it as "${name}.<path>" (docs/state-mount-design.md \xA79)`,
|
|
@@ -15950,6 +16062,281 @@ function findMisplacedOutlets(html) {
|
|
|
15950
16062
|
return routerWithoutOutlet ? misplaced : [];
|
|
15951
16063
|
}
|
|
15952
16064
|
|
|
16065
|
+
// src/service/packageLoadValidator.ts
|
|
16066
|
+
var CORE_TAG_PACKAGES = {
|
|
16067
|
+
"wcs-state": "state",
|
|
16068
|
+
"wcs-ssr": "state",
|
|
16069
|
+
"wcs-router": "router",
|
|
16070
|
+
"wcs-route": "router",
|
|
16071
|
+
"wcs-outlet": "router",
|
|
16072
|
+
"wcs-layout": "router",
|
|
16073
|
+
"wcs-layout-outlet": "router",
|
|
16074
|
+
"wcs-link": "router",
|
|
16075
|
+
"wcs-head": "router",
|
|
16076
|
+
"wcs-guard-handler": "router",
|
|
16077
|
+
"wcs-autoloader": "autoloader",
|
|
16078
|
+
"wcs-devtools": "devtools"
|
|
16079
|
+
};
|
|
16080
|
+
function packageOfTag(tag) {
|
|
16081
|
+
if (Object.hasOwn(BUILTIN_TAGS, tag)) return BUILTIN_TAGS[tag].package;
|
|
16082
|
+
return Object.hasOwn(CORE_TAG_PACKAGES, tag) ? CORE_TAG_PACKAGES[tag] : void 0;
|
|
16083
|
+
}
|
|
16084
|
+
var SCOPED_NAME = /@wcstack\/([a-z0-9-]+)/g;
|
|
16085
|
+
var REPO_DIST = /\/packages\/([a-z0-9-]+)\/dist\//g;
|
|
16086
|
+
var BUNDLE = /(?:^|[/"'`\s])wcstack(?:@[^/"'`\s]+)?\/(?:auto\b|dist\/)/;
|
|
16087
|
+
var PINNED = /(?:@wcstack\/([a-z0-9-]+)|(?:^|(?<=[/"'`\s]))wcstack)@(\d+)\.(\d+)(?:\.(\d+))?(-[0-9A-Za-z.-]+)?/g;
|
|
16088
|
+
function namedPackages(text3) {
|
|
16089
|
+
const out = [];
|
|
16090
|
+
for (const m of text3.matchAll(SCOPED_NAME)) out.push(m[1]);
|
|
16091
|
+
for (const m of text3.matchAll(REPO_DIST)) out.push(m[1]);
|
|
16092
|
+
if (BUNDLE.test(text3)) out.push("wcstack");
|
|
16093
|
+
return out.flatMap((p) => p === "wcstack" ? [...BUNDLE_PACKAGES] : [p]);
|
|
16094
|
+
}
|
|
16095
|
+
var MAX_FILES2 = 32;
|
|
16096
|
+
var MAX_DEPTH = 4;
|
|
16097
|
+
function validatePackageLoads(html, locale2, fileReader) {
|
|
16098
|
+
const msgs = getMessages(locale2);
|
|
16099
|
+
const scan = blankHtmlComments(html);
|
|
16100
|
+
const loads = collectPageLoads(scan, fileReader);
|
|
16101
|
+
const out = [];
|
|
16102
|
+
const lint = parseVersion(ENGINE_VERSION);
|
|
16103
|
+
let newest = null;
|
|
16104
|
+
for (const ref2 of loads.references) {
|
|
16105
|
+
for (const m of ref2.text.matchAll(PINNED)) {
|
|
16106
|
+
const pin = {
|
|
16107
|
+
spec: m[0],
|
|
16108
|
+
version: m[0].slice(m[0].lastIndexOf("@") + 1),
|
|
16109
|
+
major: Number(m[2]),
|
|
16110
|
+
minor: Number(m[3]),
|
|
16111
|
+
patch: m[4] === void 0 ? 0 : Number(m[4])
|
|
16112
|
+
};
|
|
16113
|
+
if (newest === null || comparePins(pin, newest.pin) > 0) {
|
|
16114
|
+
newest = { pin, start: ref2.start + m.index, end: ref2.start + m.index + m[0].length };
|
|
16115
|
+
}
|
|
16116
|
+
}
|
|
16117
|
+
}
|
|
16118
|
+
if (lint !== null && newest !== null && newest.pin.major === lint.major && newest.pin.minor > lint.minor) {
|
|
16119
|
+
out.push({
|
|
16120
|
+
code: WcsDiagnosticCode.LintVersionBehind,
|
|
16121
|
+
start: newest.start,
|
|
16122
|
+
end: newest.end,
|
|
16123
|
+
severity: "warning",
|
|
16124
|
+
message: msgs.lintVersionBehind(newest.pin.spec, newest.pin.version, `${newest.pin.major}.${newest.pin.minor}`, ENGINE_VERSION)
|
|
16125
|
+
});
|
|
16126
|
+
}
|
|
16127
|
+
if (!loads.own || loads.unclear) return out;
|
|
16128
|
+
const autoloader = loads.autoloader;
|
|
16129
|
+
const components = loads.mapKeys.filter((k) => k.startsWith("@components/"));
|
|
16130
|
+
const defined = new Set([...loads.definedTags].map((t) => packageOfTag(t)).filter((p) => p !== void 0));
|
|
16131
|
+
const byPackage = /* @__PURE__ */ new Map();
|
|
16132
|
+
for (const tag of findWcsTags(scan)) {
|
|
16133
|
+
const pkg = packageOfTag(tag.name);
|
|
16134
|
+
if (pkg === void 0 || loads.pkgs.has(pkg) || defined.has(pkg)) continue;
|
|
16135
|
+
if (autoloader && tag.name !== "wcs-autoloader" && components.some((k) => coversTag(k, tag.name))) continue;
|
|
16136
|
+
const seen2 = byPackage.get(pkg);
|
|
16137
|
+
if (seen2 === void 0) byPackage.set(pkg, { tags: [tag.name], start: tag.start, end: tag.end });
|
|
16138
|
+
else if (!seen2.tags.includes(tag.name)) seen2.tags.push(tag.name);
|
|
16139
|
+
}
|
|
16140
|
+
const version3 = suggestedVersion(loads.references);
|
|
16141
|
+
for (const [pkg, at2] of byPackage) {
|
|
16142
|
+
out.push({
|
|
16143
|
+
code: WcsDiagnosticCode.TagPackageMissing,
|
|
16144
|
+
start: at2.start,
|
|
16145
|
+
end: at2.end,
|
|
16146
|
+
severity: "warning",
|
|
16147
|
+
tag: at2.tags[0],
|
|
16148
|
+
message: msgs.tagPackageMissing(at2.tags, `@wcstack/${pkg}`, `https://esm.run/@wcstack/${pkg}${version3 === null ? "" : `@${version3}`}/auto`)
|
|
16149
|
+
});
|
|
16150
|
+
}
|
|
16151
|
+
return out;
|
|
16152
|
+
}
|
|
16153
|
+
function comparePins(a, b) {
|
|
16154
|
+
return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
|
|
16155
|
+
}
|
|
16156
|
+
function parseVersion(version3) {
|
|
16157
|
+
const m = /^(\d+)\.(\d+)/.exec(version3);
|
|
16158
|
+
return m === null ? null : { major: Number(m[1]), minor: Number(m[2]) };
|
|
16159
|
+
}
|
|
16160
|
+
function suggestedVersion(references) {
|
|
16161
|
+
const versions = /* @__PURE__ */ new Set();
|
|
16162
|
+
for (const ref2 of references) {
|
|
16163
|
+
for (const m of ref2.text.matchAll(PINNED)) versions.add(m[0].slice(m[0].lastIndexOf("@") + 1));
|
|
16164
|
+
}
|
|
16165
|
+
return versions.size === 1 ? [...versions][0] : null;
|
|
16166
|
+
}
|
|
16167
|
+
function coversTag(key, tag) {
|
|
16168
|
+
const body = key.slice("@components/".length);
|
|
16169
|
+
if (body.endsWith("/")) {
|
|
16170
|
+
const prefix = body.slice(0, -1).replace(/\|[^/]*$/, "").replace(/\//g, "-");
|
|
16171
|
+
return prefix !== "" && tag.startsWith(`${prefix}-`);
|
|
16172
|
+
}
|
|
16173
|
+
return body.replace(/\|.*$/, "") === tag;
|
|
16174
|
+
}
|
|
16175
|
+
function markupOf(scan) {
|
|
16176
|
+
return scan.replace(
|
|
16177
|
+
/(<(script|style)\b[^>]*>)([\s\S]*?)(<\/\2\s*>)/gi,
|
|
16178
|
+
(_m, open, _name, body, close) => open + " ".repeat(body.length) + close
|
|
16179
|
+
);
|
|
16180
|
+
}
|
|
16181
|
+
function findWcsTags(scan) {
|
|
16182
|
+
const out = [];
|
|
16183
|
+
for (const m of markupOf(scan).matchAll(/<(wcs-[a-z0-9-]+)(?=[\s/>])/gi)) {
|
|
16184
|
+
const start = m.index + 1;
|
|
16185
|
+
out.push({ name: m[1].toLowerCase(), start, end: start + m[1].length });
|
|
16186
|
+
}
|
|
16187
|
+
return out;
|
|
16188
|
+
}
|
|
16189
|
+
function autoloaderModules(scan, imports) {
|
|
16190
|
+
const markup = markupOf(scan);
|
|
16191
|
+
const tags = /* @__PURE__ */ new Set();
|
|
16192
|
+
for (const m of markup.matchAll(/<([a-z][a-z0-9]*-[a-z0-9-]*)(?=[\s/>])/gi)) tags.add(m[1].toLowerCase());
|
|
16193
|
+
for (const m of markup.matchAll(/\sis\s*=\s*["']([a-z][a-z0-9]*-[a-z0-9-]*)["']/gi)) tags.add(m[1].toLowerCase());
|
|
16194
|
+
for (const tag of tags) if (tag.startsWith("wcs-")) tags.delete(tag);
|
|
16195
|
+
const out = [];
|
|
16196
|
+
for (const [key, value] of imports) {
|
|
16197
|
+
if (!key.startsWith("@components/") || isUrl(value)) continue;
|
|
16198
|
+
const body = key.slice("@components/".length);
|
|
16199
|
+
if (!body.endsWith("/")) {
|
|
16200
|
+
if (!body.startsWith("wcs-")) out.push(pagePath(value));
|
|
16201
|
+
continue;
|
|
16202
|
+
}
|
|
16203
|
+
const prefix = body.slice(0, -1).replace(/\|[^/]*$/, "").replace(/\//g, "-");
|
|
16204
|
+
for (const tag of tags) {
|
|
16205
|
+
if (prefix !== "" && tag.startsWith(`${prefix}-`)) out.push(pagePath(`${value}${tag.slice(prefix.length + 1)}.js`));
|
|
16206
|
+
}
|
|
16207
|
+
}
|
|
16208
|
+
return out;
|
|
16209
|
+
}
|
|
16210
|
+
function collectPageLoads(scan, fileReader) {
|
|
16211
|
+
const loads = {
|
|
16212
|
+
pkgs: /* @__PURE__ */ new Set(),
|
|
16213
|
+
definedTags: /* @__PURE__ */ new Set(),
|
|
16214
|
+
own: false,
|
|
16215
|
+
unclear: false,
|
|
16216
|
+
autoloader: false,
|
|
16217
|
+
imports: /* @__PURE__ */ new Map(),
|
|
16218
|
+
mapKeys: [],
|
|
16219
|
+
references: []
|
|
16220
|
+
};
|
|
16221
|
+
const name = (text3, own2) => {
|
|
16222
|
+
const pkgs = namedPackages(text3);
|
|
16223
|
+
for (const p of pkgs) loads.pkgs.add(p);
|
|
16224
|
+
if (own2 && pkgs.length > 0) loads.own = true;
|
|
16225
|
+
};
|
|
16226
|
+
const locals = [];
|
|
16227
|
+
const specifiers = [];
|
|
16228
|
+
const scriptRegex = /<script\b((?:"[^"]*"|'[^']*'|[^>"'])*)>([\s\S]*?)<\/script\s*>/gi;
|
|
16229
|
+
let match;
|
|
16230
|
+
while ((match = scriptRegex.exec(scan)) !== null) {
|
|
16231
|
+
const attrs = match[1];
|
|
16232
|
+
const type = (attrValue(attrs, "type") ?? "").trim().toLowerCase();
|
|
16233
|
+
const src = extractSrc(`<script${attrs}>`);
|
|
16234
|
+
const bodyStart = match.index + match[0].indexOf(">") + 1;
|
|
16235
|
+
if (src !== null) {
|
|
16236
|
+
const start = match.index + src.offsetInTag;
|
|
16237
|
+
loads.references.push({ text: src.value, start });
|
|
16238
|
+
name(src.value, true);
|
|
16239
|
+
if (namedPackages(src.value).length === 0 && !isUrl(src.value)) locals.push(pagePath(src.value));
|
|
16240
|
+
continue;
|
|
16241
|
+
}
|
|
16242
|
+
if (type === "importmap") {
|
|
16243
|
+
readImportMap(match[2], bodyStart, loads, name);
|
|
16244
|
+
continue;
|
|
16245
|
+
}
|
|
16246
|
+
if (type !== "" && type !== "module" && !/^(?:text|application)\/(?:x-)?(?:javascript|ecmascript)$/.test(type)) continue;
|
|
16247
|
+
const body = blankJsComments(match[2]);
|
|
16248
|
+
name(body, false);
|
|
16249
|
+
for (const im of body.matchAll(/(?:\bfrom\s*|\bimport\s*\(?\s*)(["'])([^"'\n]*)\1/g)) {
|
|
16250
|
+
const start = bodyStart + im.index + im[0].indexOf(im[1]) + 1;
|
|
16251
|
+
loads.references.push({ text: im[2], start });
|
|
16252
|
+
name(im[2], true);
|
|
16253
|
+
specifiers.push(im[2]);
|
|
16254
|
+
}
|
|
16255
|
+
}
|
|
16256
|
+
for (const m of scan.matchAll(/<link\b((?:"[^"]*"|'[^']*'|[^>"'])*)>/gi)) {
|
|
16257
|
+
if (!/^\s*modulepreload\s*$/i.test(attrValue(m[1], "rel") ?? "")) continue;
|
|
16258
|
+
const href = attrValue(m[1], "href");
|
|
16259
|
+
if (href !== null) name(href, false);
|
|
16260
|
+
}
|
|
16261
|
+
for (const spec of specifiers) {
|
|
16262
|
+
if (namedPackages(spec).length > 0) continue;
|
|
16263
|
+
const target = resolveSpecifier(spec, loads.imports);
|
|
16264
|
+
if (target === void 0 || namedPackages(target).length > 0 || isUrl(target)) continue;
|
|
16265
|
+
if (isRelative(target)) locals.push(pagePath(target));
|
|
16266
|
+
}
|
|
16267
|
+
loads.autoloader = loads.pkgs.has("autoloader") || /<wcs-autoloader\b/i.test(scan);
|
|
16268
|
+
if (loads.autoloader) locals.push(...autoloaderModules(scan, loads.imports));
|
|
16269
|
+
if (locals.length > 0) readLocalModules(locals, fileReader, loads);
|
|
16270
|
+
return loads;
|
|
16271
|
+
}
|
|
16272
|
+
function readImportMap(body, bodyStart, loads, name) {
|
|
16273
|
+
for (const m of body.matchAll(/"((?:[^"\\]|\\.)*)"/g)) {
|
|
16274
|
+
loads.references.push({ text: m[1], start: bodyStart + m.index + 1 });
|
|
16275
|
+
name(m[1], true);
|
|
16276
|
+
}
|
|
16277
|
+
let parsed = null;
|
|
16278
|
+
try {
|
|
16279
|
+
parsed = JSON.parse(body);
|
|
16280
|
+
} catch {
|
|
16281
|
+
return;
|
|
16282
|
+
}
|
|
16283
|
+
const imports = parsed?.imports;
|
|
16284
|
+
if (imports === null || typeof imports !== "object") return;
|
|
16285
|
+
for (const [key, value] of Object.entries(imports)) {
|
|
16286
|
+
loads.mapKeys.push(key);
|
|
16287
|
+
if (typeof value === "string") loads.imports.set(key, value);
|
|
16288
|
+
}
|
|
16289
|
+
}
|
|
16290
|
+
function resolveSpecifier(spec, imports) {
|
|
16291
|
+
if (isUrl(spec) || isRelative(spec)) return spec;
|
|
16292
|
+
if (imports.has(spec)) return imports.get(spec);
|
|
16293
|
+
let best;
|
|
16294
|
+
for (const key of imports.keys()) {
|
|
16295
|
+
if (key.endsWith("/") && spec.startsWith(key) && (best === void 0 || key.length > best.length)) best = key;
|
|
16296
|
+
}
|
|
16297
|
+
return best === void 0 ? void 0 : imports.get(best) + spec.slice(best.length);
|
|
16298
|
+
}
|
|
16299
|
+
function isUrl(spec) {
|
|
16300
|
+
return /^[a-z][a-z0-9+.-]*:/i.test(spec) || spec.startsWith("//");
|
|
16301
|
+
}
|
|
16302
|
+
function isRelative(spec) {
|
|
16303
|
+
return spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/");
|
|
16304
|
+
}
|
|
16305
|
+
function pagePath(src) {
|
|
16306
|
+
return isRelative(src) ? src : `./${src}`;
|
|
16307
|
+
}
|
|
16308
|
+
function readLocalModules(entries, fileReader, loads) {
|
|
16309
|
+
if (fileReader === void 0) {
|
|
16310
|
+
loads.unclear = true;
|
|
16311
|
+
return;
|
|
16312
|
+
}
|
|
16313
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
16314
|
+
const queue = entries.map((spec) => ({ spec, from: "", depth: 0 }));
|
|
16315
|
+
while (queue.length > 0) {
|
|
16316
|
+
const { spec, from, depth } = queue.shift();
|
|
16317
|
+
const path = joinModulePath(from, spec);
|
|
16318
|
+
if (seen2.has(path)) continue;
|
|
16319
|
+
if (seen2.size >= MAX_FILES2 || depth > MAX_DEPTH) {
|
|
16320
|
+
loads.unclear = true;
|
|
16321
|
+
return;
|
|
16322
|
+
}
|
|
16323
|
+
seen2.add(path);
|
|
16324
|
+
const text3 = fileReader(path);
|
|
16325
|
+
if (text3 === void 0) {
|
|
16326
|
+
loads.unclear = true;
|
|
16327
|
+
return;
|
|
16328
|
+
}
|
|
16329
|
+
for (const p of namedPackages(text3)) loads.pkgs.add(p);
|
|
16330
|
+
for (const m of text3.matchAll(/["'`](wcs-[a-z0-9-]+)["'`]/g)) loads.definedTags.add(m[1]);
|
|
16331
|
+
for (const im of text3.matchAll(/(?:\bfrom\s*|\bimport\s*\(?\s*)(["'])([^"'\n]*)\1/g)) {
|
|
16332
|
+
if (namedPackages(im[2]).length > 0) continue;
|
|
16333
|
+
const target = resolveSpecifier(im[2], loads.imports);
|
|
16334
|
+
if (target === void 0 || namedPackages(target).length > 0 || isUrl(target) || !isRelative(target)) continue;
|
|
16335
|
+
queue.push({ spec: target, from: isRelative(im[2]) ? path : "", depth: depth + 1 });
|
|
16336
|
+
}
|
|
16337
|
+
}
|
|
16338
|
+
}
|
|
16339
|
+
|
|
15953
16340
|
// src/service/watchDeclarationValidator.ts
|
|
15954
16341
|
var STATE_NAME_SEPARATOR = "@";
|
|
15955
16342
|
function validateWatchDeclarations(html, stateTagName = "wcs-state", locale2, fileReader) {
|
|
@@ -17940,7 +18327,7 @@ function validateScriptReads(html, stateTagName = "wcs-state", locale2, fileRead
|
|
|
17940
18327
|
code: WcsDiagnosticCode.PathDynamicUnknown,
|
|
17941
18328
|
start: block.contentStart + span.start,
|
|
17942
18329
|
end: block.contentStart + span.end,
|
|
17943
|
-
message: msgs.pathDynamicUnknownValue(path, count, candidate.opaque?.name, candidate.opaque?.from),
|
|
18330
|
+
message: candidate.opaque?.spread !== void 0 ? msgs.pathDynamicUnknownObjectSpread(path, count, candidate.opaque.spread, candidate.opaque.from) : msgs.pathDynamicUnknownValue(path, count, candidate.opaque?.name, candidate.opaque?.from),
|
|
17944
18331
|
severity: "info"
|
|
17945
18332
|
});
|
|
17946
18333
|
}
|
|
@@ -18179,6 +18566,7 @@ function validateText(text3, options, applicationSchema) {
|
|
|
18179
18566
|
out.push(...validateAriaAttributes(text3, bindAttribute, locale2));
|
|
18180
18567
|
out.push(...validateLiveRegions(text3, bindAttribute, stateTagName, locale2));
|
|
18181
18568
|
out.push(...validateDocumentEnv(text3, locale2));
|
|
18569
|
+
out.push(...validatePackageLoads(text3, locale2, fileReader));
|
|
18182
18570
|
out.push(...validateSemantics(text3, stateTagName, locale2, bindAttribute));
|
|
18183
18571
|
out.push(...validateScriptStateUses(text3, stateTagName, locale2, bindAttribute));
|
|
18184
18572
|
out.push(...validateScriptReads(text3, stateTagName, locale2, fileReader, applicationSchema, bindAttribute));
|
package/dist/wcs-schema.mjs
CHANGED
package/dist/wcs-tsc.mjs
CHANGED
|
@@ -25,7 +25,7 @@ function unsupportedTypeScriptMessage(version) {
|
|
|
25
25
|
return `@wcstack/typescript runs on TypeScript 5 or 6, and the project has TypeScript ${version}, which has no JavaScript compiler API: npm i -D typescript@6`;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
var version = "4.
|
|
28
|
+
var version = "4.11.0";
|
|
29
29
|
var pkg = {
|
|
30
30
|
version: version};
|
|
31
31
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/typescript",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.0",
|
|
4
4
|
"description": "TypeScript tooling for wcstack apps: wcs-schema generates the sidecar stateSchema from a typed state file, so wcs-validate checks data-wcs paths against real types in CI and every editor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|