@wcstack/typescript 4.0.2 → 4.0.4
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 +77 -10
- 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
|
@@ -216,6 +216,10 @@ var WcsDiagnosticCode = {
|
|
|
216
216
|
ScriptOrder: "wcs/script-order",
|
|
217
217
|
// router/auto があるのに <base href> がない(SPA の basename 誤導出)。
|
|
218
218
|
BaseHrefMissing: "wcs/base-href-missing",
|
|
219
|
+
// <wcs-router> の直後に無い <wcs-outlet>(どの router にも使われない)と、直後に outlet を持たない
|
|
220
|
+
// router。router は自前の outlet を直後に作り、ページはそこに描かれ、置いた outlet は空のまま。
|
|
221
|
+
// ランタイムも同じ code で警告する(docs/router-outlet-placement.md)。
|
|
222
|
+
RouterOutletMisplaced: "wcs/router-outlet-misplaced",
|
|
219
223
|
// @wcstack/signals と /dom エントリの同一ページ混在(リアクティブコア二重化)。
|
|
220
224
|
SignalsDualEntry: "wcs/signals-dual-entry",
|
|
221
225
|
// --- deprecations ---
|
|
@@ -3148,7 +3152,9 @@ function analyzeStatePaths(scriptContent) {
|
|
|
3148
3152
|
}
|
|
3149
3153
|
if (prop.kind === "getter") {
|
|
3150
3154
|
if (!paths.some((p) => p.path === prop.name)) {
|
|
3151
|
-
|
|
3155
|
+
const recursive = hasRecursionWildcard(prop.name);
|
|
3156
|
+
const settable = !recursive && effective !== "data" && effective.set;
|
|
3157
|
+
paths.push({ path: prop.name, kind: recursive ? "recursive" : "computed", ...settable ? { settable } : {} });
|
|
3152
3158
|
}
|
|
3153
3159
|
continue;
|
|
3154
3160
|
}
|
|
@@ -10991,9 +10997,12 @@ var ja = {
|
|
|
10991
10997
|
triggerSeededTruthy: (path) => `trigger \u30D0\u30A4\u30F3\u30C9\u5148 "${path}" \u304C true \u3067\u30B7\u30FC\u30C9\u3055\u308C\u3066\u3044\u307E\u3059\u3002trigger \u306F\u30A8\u30C3\u30B8\u691C\u51FA\u306A\u3057\uFF08truthy \u66F8\u304D\u8FBC\u307F\u3067\u5373\u767A\u706B\u30FBmanual \u3082\u30D0\u30A4\u30D1\u30B9\uFF09\u306E\u305F\u3081\u3001\u30D0\u30A4\u30F3\u30C9\u6642\u306B\u5373\u767A\u706B\u3057\u307E\u3059\u3002false \u3067\u30B7\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
10992
10998
|
storageSeedClobber: (path, raw) => `<wcs-storage> \u306E value \u30D0\u30A4\u30F3\u30C9\u5148 "${path}" \u304C ${raw} \u3067\u30B7\u30FC\u30C9\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u8AAD\u307F\u8FBC\u307F\u306E\u305F\u3073\u306B\u521D\u671F\u66F8\u304D\u623B\u3057\u304C\u4FDD\u5B58\u5024\u3092\u4E0A\u66F8\u304D\u3057\u307E\u3059 \u2014 \u30D0\u30A4\u30F3\u30C9\u306B #init=element \u3092\u4ED8\u3051\u3066\uFF08\`value#init=element: ${path}\`\uFF09\u4FDD\u5B58\u5024\u3092\u52DD\u305F\u305B\u3001\u30B9\u30ED\u30C3\u30C8\u306F null\uFF08\u7A7A\u306E\u30AD\u30FC\u304C\u8AAD\u3080\u5024\uFF09\u3067\u30B7\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
10993
10999
|
storageInitSeed: (path, raw) => `<wcs-storage> \u306E value \u30D0\u30A4\u30F3\u30C9\u5148 "${path}" \u304C ${shortSeed(raw)} \u3067\u30B7\u30FC\u30C9\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001#init=element \u306F\u8981\u7D20\u306E\u5024\u3092\u3053\u306E\u30B9\u30ED\u30C3\u30C8\u3078\u5F15\u304D\u8FBC\u307F\u307E\u3059\u3002\u521D\u56DE\uFF08\u7A7A\u306E\u30AD\u30FC\uFF09\u306F null \u306A\u306E\u3067\u3001\u30B7\u30FC\u30C9\u306F null \u306B\u7F6E\u304D\u63DB\u308F\u308A\u307E\u3059 \u2014 null \u3067\u30B7\u30FC\u30C9\u3057\u3066\u8AAD\u3080\u5074\u3067\u65E2\u5B9A\u5024\u3092\u88DC\u3046\uFF08\`this.${path} ?? \u2026\`\uFF09\u304B\u3001null \u3092\u7121\u8996\u3059\u308B setter \u3092\u6301\u3064\u30A2\u30AF\u30BB\u30B5\u30DA\u30A2\u3092\u675F\u306D\u3066\u304F\u3060\u3055\u3044`,
|
|
11000
|
+
storagePairClobber: (path) => `<wcs-storage> \u306E value \u3092 #init=element \u306A\u3057\u3067\u30A2\u30AF\u30BB\u30B5\u30DA\u30A2 "${path}" \u306B\u675F\u306D\u3066\u3044\u307E\u3059\u3002state \u306E\u5074\u304C\u5148\u306B\u66F8\u304F\u306E\u3067\u3001\u8AAD\u307F\u8FBC\u307F\u306E\u305F\u3073\u306B getter \u306E\u6700\u521D\u306E\u5024\u304C\u4FDD\u5B58\u5024\u306E\u4E0A\u306B\u4FDD\u5B58\u3055\u308C\u3001setter \u306F\u4FDD\u5B58\u5024\u3092\u53D7\u3051\u53D6\u308C\u307E\u305B\u3093 \u2014 #init=element \u3092\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\uFF08\`value#init=element: ${path}\`\uFF09`,
|
|
10994
11001
|
inputNestedWrite: (tag, input, path, example) => `<${tag}> \u306E\u5165\u529B "${input}" \u306B "${path}" \u3092\u675F\u306D\u3066\u3044\u307E\u3059\u304C\u3001\u30DA\u30FC\u30B8\u306F\u305D\u306E\u4E0B\uFF08"${example}"\uFF09\u3078\u66F8\u304D\u8FBC\u3093\u3067\u3044\u307E\u3059\u3002\u675F\u7E1B\u306F "${path}" \u81EA\u8EAB\u3078\u306E\u4EE3\u5165\u3067\u3057\u304B\u5F53\u3066\u76F4\u3055\u308C\u306A\u3044\u306E\u3067\u3001\u4E0B\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306F <${tag}> \u306B\u5C4A\u304D\u307E\u305B\u3093 \u2014 \u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u30D1\u30B9\u3067\u8AAD\u3093\u3067\u65B0\u3057\u3044\u5024\u3092\u8FD4\u3059 getter\uFF08\`this["${example}"]\`\u30FB\`$getAll\`\uFF09\u3092\u675F\u306D\u308B\u304B\u3001\u4E0B\u3078\u66F8\u304B\u305A\u306B "${path}" \u3092\u5DEE\u3057\u66FF\u3048\u3066\u304F\u3060\u3055\u3044`,
|
|
11002
|
+
inputNestedWriteOneShot: (tag, input, path, example) => `<${tag}> \u306E\u5165\u529B "${input}" \u306B "${path}" \u3092\u675F\u306D\u3066\u3044\u307E\u3059\u304C\u3001\u30DA\u30FC\u30B8\u306F\u305D\u306E\u4E0B\uFF08"${example}"\uFF09\u3078\u66F8\u304D\u8FBC\u3093\u3067\u3044\u307E\u3059\u3002\u675F\u7E1B\u306F "${path}" \u81EA\u8EAB\u3078\u306E\u4EE3\u5165\u3067\u3057\u304B\u5F53\u3066\u76F4\u3055\u308C\u305A\u3001<${tag}> \u306F\u8981\u6C42\u306E\u305F\u3073\u306B "${input}" \u3092 null \u306B\u623B\u3059\u306E\u3067\u3001\u6B21\u306E\u8981\u6C42\u306F "${input}" \u306A\u3057\u3067\u9001\u3089\u308C\u307E\u3059 \u2014 \u8981\u6C42\u3092\u59CB\u3081\u308B\u30CF\u30F3\u30C9\u30E9\u3067\u65B0\u3057\u3044\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u4F5C\u3063\u3066\u4EE3\u5165\u3057\uFF08\`this.submitBody = { \u2026 }\`\uFF09\u3001\u305D\u308C\u3092\u675F\u306D\u3066\u304F\u3060\u3055\u3044`,
|
|
10995
11003
|
devtoolsAfterState: () => `@wcstack/devtools/auto \u306F @wcstack/state/auto \u3088\u308A\u5148\u306B\u8AAD\u307F\u8FBC\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u5F8C\u3060\u3068\u914D\u7DDA\u53F0\u5E33\u304C\u30E9\u30A4\u30D6\u3067 captured \u3055\u308C\u307E\u305B\u3093\uFF09`,
|
|
10996
11004
|
baseHrefMissing: () => `@wcstack/router \u3092\u4F7F\u3046 SPA \u306B\u306F <head> \u5185\u306E <base href="/"> \u304C\u5FC5\u8981\u3067\u3059\uFF08\u7121\u3044\u3068\u30C7\u30A3\u30FC\u30D7\u30EA\u30F3\u30AF\u3067 basename \u304C\u8AA4\u5C0E\u51FA\u3055\u308C\u307E\u3059\uFF09`,
|
|
11005
|
+
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`,
|
|
10997
11006
|
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`,
|
|
10998
11007
|
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`,
|
|
10999
11008
|
namedStatePathDeprecated: (name) => name === "default" ? `"@default" \u30BB\u30EC\u30AF\u30BF\u306F v2 \u3067\u64A4\u53BB\u3055\u308C\u307E\u3057\u305F\u3002"@default" \u3092\u5916\u3057\u3066\u304F\u3060\u3055\u3044\uFF08docs/state-mount-design.md \xA79\uFF09` : `"@name" \u30BB\u30EC\u30AF\u30BF\u306F v2 \u3067\u64A4\u53BB\u3055\u308C\u307E\u3057\u305F\uFF081 root 1 \u30C4\u30EA\u30FC\uFF09\u3002\u30DE\u30A6\u30F3\u30C8\u3057\u305F\u30C4\u30EA\u30FC\u3092 "${name}.<path>" \u3067\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\uFF08docs/state-mount-design.md \xA79\uFF09`,
|
|
@@ -11179,9 +11188,12 @@ var en = {
|
|
|
11179
11188
|
triggerSeededTruthy: (path) => `The trigger-bound slot "${path}" is seeded with true. trigger has no edge detection (any truthy write fires, and it bypasses manual), so it fires immediately at bind. Seed it with false`,
|
|
11180
11189
|
storageSeedClobber: (path, raw) => `The <wcs-storage> value-bound slot "${path}" is seeded with ${raw}. The initial write-back overwrites the persisted value on every load \u2014 add #init=element to the binding (\`value#init=element: ${path}\`) so the stored value wins, and seed the slot with null (what an empty key loads as)`,
|
|
11181
11190
|
storageInitSeed: (path, raw) => `The <wcs-storage> value-bound slot "${path}" is seeded with ${shortSeed(raw)}, but #init=element pulls the element's value into it. On a first visit (an empty key) that is null, so the seed is replaced by null \u2014 seed it with null and supply the default where you read it (\`this.${path} ?? \u2026\`), or bind an accessor pair whose setter ignores null`,
|
|
11191
|
+
storagePairClobber: (path) => `The <wcs-storage> value is bound to the accessor pair "${path}" without #init=element. The state's side goes first, so on every load the getter's starting value is saved over the stored one, and the setter never receives it \u2014 add #init=element (\`value#init=element: ${path}\`)`,
|
|
11182
11192
|
inputNestedWrite: (tag, input, path, example) => `"${path}" is bound to the input "${input}" of <${tag}>, but the page writes below it ("${example}"). A binding is re-applied only when "${path}" itself is assigned, so those writes never reach <${tag}> \u2014 bind a getter that reads the fields by path (\`this["${example}"]\`, \`$getAll\`) and returns a new value, or replace "${path}" instead of writing below it`,
|
|
11193
|
+
inputNestedWriteOneShot: (tag, input, path, example) => `"${path}" is bound to the input "${input}" of <${tag}>, but the page writes below it ("${example}"). A binding is re-applied only when "${path}" itself is assigned, and <${tag}> resets "${input}" to null after every request, so the next request goes without it \u2014 build a new object in the handler that starts the request (\`this.submitBody = { \u2026 }\`) and bind that`,
|
|
11183
11194
|
devtoolsAfterState: () => `Load @wcstack/devtools/auto BEFORE @wcstack/state/auto (otherwise the wiring ledger is not captured live)`,
|
|
11184
11195
|
baseHrefMissing: () => `An SPA using @wcstack/router needs <base href="/"> in <head> (without it, deep links misderive the basename)`,
|
|
11196
|
+
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>`,
|
|
11185
11197
|
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`,
|
|
11186
11198
|
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)`,
|
|
11187
11199
|
namedStatePathDeprecated: (name) => name === "default" ? `The "@default" selector was removed in v2 \u2014 drop it (docs/state-mount-design.md \xA79)` : `The "@name" selector was removed in v2 \u2014 there is a single state tree. Mount the named state onto the tree (<wcs-state mount="...">) and read it as "${name}.<path>" (docs/state-mount-design.md \xA79)`,
|
|
@@ -14188,7 +14200,8 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
14188
14200
|
}
|
|
14189
14201
|
}
|
|
14190
14202
|
if (tagName === "wcs-storage" && property === "value" && !hasManual && parsed.path && !/(?:^|,)init=(?:element|auto)\b/.test(modifiers)) {
|
|
14191
|
-
const
|
|
14203
|
+
const paths = getPaths();
|
|
14204
|
+
const cand = findDataSlot(paths, parsed.path);
|
|
14192
14205
|
if (cand?.rawInitial !== void 0 && EMPTYISH_SEEDS.has(normalizeSeed(cand.rawInitial))) {
|
|
14193
14206
|
diagnostics.push({
|
|
14194
14207
|
code: WcsDiagnosticCode.StorageSeedClobber,
|
|
@@ -14199,6 +14212,16 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
14199
14212
|
statePath: parsed.path,
|
|
14200
14213
|
message: msgs.storageSeedClobber(parsed.path, cand.rawInitial)
|
|
14201
14214
|
});
|
|
14215
|
+
} else if (cand === void 0 && paths.some((c) => c.kind === "computed" && c.settable && c.path === parsed.path)) {
|
|
14216
|
+
diagnostics.push({
|
|
14217
|
+
code: WcsDiagnosticCode.StorageSeedClobber,
|
|
14218
|
+
start,
|
|
14219
|
+
end,
|
|
14220
|
+
severity: "warning",
|
|
14221
|
+
tag: tagName,
|
|
14222
|
+
statePath: parsed.path,
|
|
14223
|
+
message: msgs.storagePairClobber(parsed.path)
|
|
14224
|
+
});
|
|
14202
14225
|
}
|
|
14203
14226
|
}
|
|
14204
14227
|
if (tagName === "wcs-storage" && property === "value" && parsed.path && /(?:^|,)init=element\b/.test(modifiers)) {
|
|
@@ -14356,10 +14379,10 @@ function validateDocumentEnv(html, locale2) {
|
|
|
14356
14379
|
const msgs = getMessages(locale2);
|
|
14357
14380
|
const scanText = blankHtmlComments(html);
|
|
14358
14381
|
const autos = findWcstackAutoScripts(scanText);
|
|
14359
|
-
const stateIndex = autos.findIndex((a) => a.
|
|
14382
|
+
const stateIndex = autos.findIndex((a) => a.pkgs.includes("state"));
|
|
14360
14383
|
if (stateIndex !== -1) {
|
|
14361
14384
|
for (const later of autos.slice(stateIndex + 1)) {
|
|
14362
|
-
if (later.
|
|
14385
|
+
if (!later.pkgs.includes("devtools")) continue;
|
|
14363
14386
|
diagnostics.push({
|
|
14364
14387
|
code: WcsDiagnosticCode.ScriptOrder,
|
|
14365
14388
|
start: later.start,
|
|
@@ -14369,7 +14392,7 @@ function validateDocumentEnv(html, locale2) {
|
|
|
14369
14392
|
});
|
|
14370
14393
|
}
|
|
14371
14394
|
}
|
|
14372
|
-
const router = autos.find((a) => a.
|
|
14395
|
+
const router = autos.find((a) => a.pkgs.includes("router") && (!a.bundle || /<wcs-router\b/i.test(scanText)));
|
|
14373
14396
|
if (router && !/<base\b[^>]*\bhref\s*=/i.test(scanText)) {
|
|
14374
14397
|
diagnostics.push({
|
|
14375
14398
|
code: WcsDiagnosticCode.BaseHrefMissing,
|
|
@@ -14379,6 +14402,15 @@ function validateDocumentEnv(html, locale2) {
|
|
|
14379
14402
|
message: msgs.baseHrefMissing()
|
|
14380
14403
|
});
|
|
14381
14404
|
}
|
|
14405
|
+
for (const outlet of findMisplacedOutlets(scanText)) {
|
|
14406
|
+
diagnostics.push({
|
|
14407
|
+
code: WcsDiagnosticCode.RouterOutletMisplaced,
|
|
14408
|
+
start: outlet.start,
|
|
14409
|
+
end: outlet.end,
|
|
14410
|
+
severity: "warning",
|
|
14411
|
+
message: msgs.routerOutletMisplaced()
|
|
14412
|
+
});
|
|
14413
|
+
}
|
|
14382
14414
|
const refs = collectSignalsRefs(scanText);
|
|
14383
14415
|
const dom = refs.find((r) => r.kind === "dom");
|
|
14384
14416
|
const bare = refs.find((r) => r.kind === "bare");
|
|
@@ -14394,6 +14426,9 @@ function validateDocumentEnv(html, locale2) {
|
|
|
14394
14426
|
}
|
|
14395
14427
|
return diagnostics;
|
|
14396
14428
|
}
|
|
14429
|
+
var SCOPED_AUTO = /@wcstack\/([a-z0-9-]+)(?:@[^/"'\s]+)?\/(?:auto\b|dist\/(?:split\/)?auto(?:\.min)?\.js\b)/;
|
|
14430
|
+
var BUNDLE_AUTO = /(?:^|\/)wcstack(?:@[^/"'\s]+)?\/(?:auto\b|dist\/auto\.min\.js\b)/;
|
|
14431
|
+
var BUNDLE_PACKAGES = ["state", "router", "fetch", "storage", "autoloader"];
|
|
14397
14432
|
function findWcstackAutoScripts(html) {
|
|
14398
14433
|
const out = [];
|
|
14399
14434
|
const scriptRegex = /<script\b(?:"[^"]*"|'[^']*'|[^>"'])*>/gi;
|
|
@@ -14401,10 +14436,12 @@ function findWcstackAutoScripts(html) {
|
|
|
14401
14436
|
while ((match = scriptRegex.exec(html)) !== null) {
|
|
14402
14437
|
const src = extractSrc(match[0]);
|
|
14403
14438
|
if (!src) continue;
|
|
14404
|
-
const pkgMatch =
|
|
14405
|
-
|
|
14439
|
+
const pkgMatch = SCOPED_AUTO.exec(src.value);
|
|
14440
|
+
const bundle = pkgMatch === null && BUNDLE_AUTO.test(src.value);
|
|
14441
|
+
if (pkgMatch === null && !bundle) continue;
|
|
14406
14442
|
out.push({
|
|
14407
|
-
|
|
14443
|
+
pkgs: bundle ? BUNDLE_PACKAGES : [pkgMatch[1]],
|
|
14444
|
+
bundle,
|
|
14408
14445
|
start: match.index + src.offsetInTag,
|
|
14409
14446
|
end: match.index + src.offsetInTag + src.value.length
|
|
14410
14447
|
});
|
|
@@ -14461,6 +14498,34 @@ function blankHtmlComments(html) {
|
|
|
14461
14498
|
function blankJsComments(code) {
|
|
14462
14499
|
return code.replace(/\/\*[\s\S]*?\*\//g, (m) => " ".repeat(m.length)).replace(/(^|[^:])\/\/[^\n]*/g, (m, pre) => pre + " ".repeat(m.length - pre.length));
|
|
14463
14500
|
}
|
|
14501
|
+
var ROUTER_TAG2 = "wcs-router";
|
|
14502
|
+
var OUTLET_TAG = "wcs-outlet";
|
|
14503
|
+
function findMisplacedOutlets(html) {
|
|
14504
|
+
const scan = html.replace(
|
|
14505
|
+
/(<(script|style)\b[^>]*>)([\s\S]*?)(<\/\2\s*>)/gi,
|
|
14506
|
+
(_m, open, _name, body, close) => open + " ".repeat(body.length) + close
|
|
14507
|
+
);
|
|
14508
|
+
const tokens = [];
|
|
14509
|
+
const tagRegex = /<(\/?)([a-zA-Z][\w-]*)(?:"[^"]*"|'[^']*'|[^>"'])*>/g;
|
|
14510
|
+
let match;
|
|
14511
|
+
while ((match = tagRegex.exec(scan)) !== null) {
|
|
14512
|
+
const nameStart = match.index + 1 + match[1].length;
|
|
14513
|
+
tokens.push({ name: match[2].toLowerCase(), close: match[1] === "/", start: nameStart, end: nameStart + match[2].length });
|
|
14514
|
+
}
|
|
14515
|
+
let routerWithoutOutlet = false;
|
|
14516
|
+
const misplaced = [];
|
|
14517
|
+
tokens.forEach((token, i) => {
|
|
14518
|
+
if (token.name === ROUTER_TAG2 && token.close) {
|
|
14519
|
+
const next = tokens[i + 1];
|
|
14520
|
+
if (!next || next.close || next.name !== OUTLET_TAG) routerWithoutOutlet = true;
|
|
14521
|
+
}
|
|
14522
|
+
if (token.name === OUTLET_TAG && !token.close) {
|
|
14523
|
+
const prev = tokens[i - 1];
|
|
14524
|
+
if (!(prev && prev.close && prev.name === ROUTER_TAG2)) misplaced.push({ start: token.start, end: token.end });
|
|
14525
|
+
}
|
|
14526
|
+
});
|
|
14527
|
+
return routerWithoutOutlet ? misplaced : [];
|
|
14528
|
+
}
|
|
14464
14529
|
|
|
14465
14530
|
// src/service/watchDeclarationValidator.ts
|
|
14466
14531
|
var STATE_NAME_SEPARATOR = "@";
|
|
@@ -15863,7 +15928,8 @@ function validateGetterUntrackedReads(script, scriptStart, nestedWriteRoots, loc
|
|
|
15863
15928
|
return out;
|
|
15864
15929
|
}
|
|
15865
15930
|
var NESTED_WRITE_INPUTS = {
|
|
15866
|
-
"wcs-storage": { inputs: ["value"], exemptWhenManual: true }
|
|
15931
|
+
"wcs-storage": { inputs: ["value"], exemptWhenManual: true },
|
|
15932
|
+
"wcs-fetch": { inputs: ["body"], exemptWhenManual: false, oneShot: true }
|
|
15867
15933
|
};
|
|
15868
15934
|
var MANUAL_ATTRIBUTE = /(?:^|\s)manual(?:\s|=|$)/i;
|
|
15869
15935
|
function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWriteRoots, locale2) {
|
|
@@ -15885,6 +15951,7 @@ function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWrite
|
|
|
15885
15951
|
if (!NESTED_WRITE_INPUTS[tag.tagName].inputs.includes(input)) continue;
|
|
15886
15952
|
const example = nestedWriteRoots().get(occ.path);
|
|
15887
15953
|
if (example === void 0) continue;
|
|
15954
|
+
const message = NESTED_WRITE_INPUTS[tag.tagName].oneShot ? msgs.inputNestedWriteOneShot(tag.tagName, input, occ.path, example) : msgs.inputNestedWrite(tag.tagName, input, occ.path, example);
|
|
15888
15955
|
out.push({
|
|
15889
15956
|
code: WcsDiagnosticCode.InputNestedWrite,
|
|
15890
15957
|
start: occ.pathRange.start,
|
|
@@ -15892,7 +15959,7 @@ function validateInputNestedWrites(html, stateTagName, bindAttrName, nestedWrite
|
|
|
15892
15959
|
severity: "warning",
|
|
15893
15960
|
tag: tag.tagName,
|
|
15894
15961
|
statePath: occ.path,
|
|
15895
|
-
message
|
|
15962
|
+
message
|
|
15896
15963
|
});
|
|
15897
15964
|
}
|
|
15898
15965
|
return out;
|
package/dist/wcs-schema.mjs
CHANGED
package/dist/wcs-tsc.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/typescript",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
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",
|