@wcstack/typescript 1.32.0 → 2.0.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 +106 -106
- package/README.md +106 -106
- package/dist/index.d.ts +34 -16
- package/dist/index.esm.js +96 -28
- package/dist/index.esm.js.map +1 -1
- package/dist/schema-core.cjs +220 -187
- package/dist/tsc-core.cjs +2 -2
- package/dist/wcs-schema.mjs +149 -47
- package/dist/wcs-schema.mjs.map +1 -1
- package/dist/wcs-tsc.mjs +1 -1
- package/dist/wcs-tsc.mjs.map +1 -1
- package/package.json +84 -84
package/dist/schema-core.cjs
CHANGED
|
@@ -121,7 +121,11 @@ var WcsDiagnosticCode = {
|
|
|
121
121
|
// --- deprecations ---
|
|
122
122
|
// 名前付き State(`<wcs-state name>` / `path@name`)。v2 でマウント(`mount=` と接頭辞付きパス)に
|
|
123
123
|
// 置き換わる(docs/state-mount-design.md D16)。1.x では warning、v2 では parse error と同時に error。
|
|
124
|
-
NamedStateDeprecated: "wcs/named-state-deprecated"
|
|
124
|
+
NamedStateDeprecated: "wcs/named-state-deprecated",
|
|
125
|
+
// --- volume mount ---
|
|
126
|
+
// `<wcs-state mount="...">` の値が runtime の validateVolumeMountPath で raise する形
|
|
127
|
+
// (空・空セグメント・ワイルドカード・予約文字 $ # @)。runtime と同条件・同文言(v2)。
|
|
128
|
+
MountPathInvalid: "wcs/mount-path-invalid"
|
|
125
129
|
};
|
|
126
130
|
function sortDiagnostics(diagnostics) {
|
|
127
131
|
const severityRank = { error: 0, warning: 1, info: 2 };
|
|
@@ -493,8 +497,8 @@ function parseJsonWithSpans(text) {
|
|
|
493
497
|
}
|
|
494
498
|
|
|
495
499
|
// src/core/sidecar/types.ts
|
|
496
|
-
var SUPPORTED_SCHEMA_VERSION =
|
|
497
|
-
var SUPPORTED_NAMESPACE_VERSION =
|
|
500
|
+
var SUPPORTED_SCHEMA_VERSION = 2;
|
|
501
|
+
var SUPPORTED_NAMESPACE_VERSION = 2;
|
|
498
502
|
|
|
499
503
|
// src/core/sidecar/loader.ts
|
|
500
504
|
var NAMESPACE_KEYS = ["wcstack.types", "wcstack.async", "wcstack.platformCapabilities", "wcstack.application"];
|
|
@@ -531,10 +535,11 @@ function loadManifest(artifact) {
|
|
|
531
535
|
return { artifact, manifest: null, ctx, spans: parsed.spans };
|
|
532
536
|
}
|
|
533
537
|
if (obj.schemaVersion !== SUPPORTED_SCHEMA_VERSION) {
|
|
538
|
+
const migration = obj.schemaVersion === 1 ? ` schemaVersion 1 (states[name]) predates v2's single state tree \u2014 regenerate with \`wcs-schema emit\`.` : "";
|
|
534
539
|
ctx.add(
|
|
535
540
|
WcsDiagnosticCode.ManifestSchemaVersion,
|
|
536
541
|
pointer("schemaVersion"),
|
|
537
|
-
`Unsupported schemaVersion ${obj.schemaVersion}; this reader supports ${SUPPORTED_SCHEMA_VERSION}
|
|
542
|
+
`Unsupported schemaVersion ${obj.schemaVersion}; this reader supports ${SUPPORTED_SCHEMA_VERSION}.${migration}`,
|
|
538
543
|
"error"
|
|
539
544
|
);
|
|
540
545
|
return { artifact, manifest: null, ctx, spans: parsed.spans };
|
|
@@ -581,11 +586,10 @@ function validateLoadedSchemas(loaded) {
|
|
|
581
586
|
validateComponentSchemas(tag, component, loaded.ctx);
|
|
582
587
|
}
|
|
583
588
|
const application = loaded.manifest.manifestExtensions?.["wcstack.application"];
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
validateSchemaSubset(schema, ptr, loaded.ctx, schema.$defs ?? {});
|
|
589
|
+
const stateSchema = application?.stateSchema;
|
|
590
|
+
if (stateSchema !== void 0 && stateSchema !== null && typeof stateSchema === "object" && !Array.isArray(stateSchema)) {
|
|
591
|
+
const ptr = pointer("manifestExtensions", "wcstack.application", "stateSchema");
|
|
592
|
+
validateSchemaSubset(stateSchema, ptr, loaded.ctx, stateSchema.$defs ?? {});
|
|
589
593
|
}
|
|
590
594
|
}
|
|
591
595
|
function validateComponentSchemas(tag, component, ctx) {
|
|
@@ -1218,7 +1222,6 @@ var MAX_WILDCARD_DEPTH = 128;
|
|
|
1218
1222
|
var BINDING_SEPARATOR = ";";
|
|
1219
1223
|
var PROP_VALUE_SEPARATOR = ":";
|
|
1220
1224
|
var MODIFIER_SEPARATOR = "#";
|
|
1221
|
-
var STATE_NAME_SEPARATOR = "@";
|
|
1222
1225
|
var FILTER_SEPARATOR = "|";
|
|
1223
1226
|
var MODIFIER_PREVENT = "prevent";
|
|
1224
1227
|
var MODIFIER_STOP = "stop";
|
|
@@ -1276,7 +1279,6 @@ function getWcsManifest() {
|
|
|
1276
1279
|
binding: BINDING_SEPARATOR,
|
|
1277
1280
|
propValue: PROP_VALUE_SEPARATOR,
|
|
1278
1281
|
modifier: MODIFIER_SEPARATOR,
|
|
1279
|
-
stateName: STATE_NAME_SEPARATOR,
|
|
1280
1282
|
filter: FILTER_SEPARATOR
|
|
1281
1283
|
},
|
|
1282
1284
|
// 正本 STRUCTURAL_BINDING_TYPE_SET から導出(手書きの二重定義を排除)。
|
|
@@ -1349,7 +1351,7 @@ var RESERVED_COMMAND_TOKENS_KEY = "$commandTokens";
|
|
|
1349
1351
|
var RESERVED_EVENT_TOKENS_KEY = "$eventTokens";
|
|
1350
1352
|
var RESERVED_LIST_KEYS_KEY = "$listKeys";
|
|
1351
1353
|
var RESERVED_WATCH_KEY = "$watch";
|
|
1352
|
-
function analyzeStatePaths(scriptContent
|
|
1354
|
+
function analyzeStatePaths(scriptContent) {
|
|
1353
1355
|
const objectContent = extractDefaultExportObject(scriptContent);
|
|
1354
1356
|
if (!objectContent) return [];
|
|
1355
1357
|
const paths = [];
|
|
@@ -1358,27 +1360,27 @@ function analyzeStatePaths(scriptContent, stateName = "default") {
|
|
|
1358
1360
|
const pendingListKeys = [];
|
|
1359
1361
|
for (const prop of topLevelProps) {
|
|
1360
1362
|
if (prop.name.startsWith("$")) {
|
|
1361
|
-
collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKeys
|
|
1363
|
+
collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKeys);
|
|
1362
1364
|
continue;
|
|
1363
1365
|
}
|
|
1364
1366
|
if (prop.kind === "method") {
|
|
1365
|
-
paths.push({ path: prop.name, kind: "method"
|
|
1367
|
+
paths.push({ path: prop.name, kind: "method" });
|
|
1366
1368
|
continue;
|
|
1367
1369
|
}
|
|
1368
1370
|
if (prop.kind === "getter") {
|
|
1369
|
-
if (!paths.some((p) => p.
|
|
1370
|
-
paths.push({ path: prop.name, kind: "computed"
|
|
1371
|
+
if (!paths.some((p) => p.path === prop.name)) {
|
|
1372
|
+
paths.push({ path: prop.name, kind: "computed" });
|
|
1371
1373
|
}
|
|
1372
1374
|
continue;
|
|
1373
1375
|
}
|
|
1374
|
-
pushDataPropertyPaths(prop, paths
|
|
1376
|
+
pushDataPropertyPaths(prop, paths);
|
|
1375
1377
|
}
|
|
1376
1378
|
for (const streamValue of pendingStreamValues) {
|
|
1377
|
-
if (paths.some((p) => p.
|
|
1378
|
-
pushDataPropertyPaths(streamValue, paths
|
|
1379
|
+
if (paths.some((p) => p.path === streamValue.name)) continue;
|
|
1380
|
+
pushDataPropertyPaths(streamValue, paths);
|
|
1379
1381
|
}
|
|
1380
1382
|
for (const listKeyEntry of pendingListKeys) {
|
|
1381
|
-
pushListKeyPaths(listKeyEntry, paths
|
|
1383
|
+
pushListKeyPaths(listKeyEntry, paths);
|
|
1382
1384
|
}
|
|
1383
1385
|
return paths;
|
|
1384
1386
|
}
|
|
@@ -1465,7 +1467,7 @@ function findNonObjectWatch(scriptContent) {
|
|
|
1465
1467
|
if (!isArrowFunction && !isWholeLiteral) return null;
|
|
1466
1468
|
return span;
|
|
1467
1469
|
}
|
|
1468
|
-
function collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKeys
|
|
1470
|
+
function collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKeys) {
|
|
1469
1471
|
if (prop.name === RESERVED_STREAMS_KEY && prop.kind === "data" && prop.value && isObjectLiteral(prop.value)) {
|
|
1470
1472
|
const entries = parseTopLevelProperties(extractObjectContent(prop.value));
|
|
1471
1473
|
for (const entry of entries) {
|
|
@@ -1477,20 +1479,20 @@ function collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKe
|
|
|
1477
1479
|
value: initial?.value,
|
|
1478
1480
|
typeHint: initial?.typeHint
|
|
1479
1481
|
});
|
|
1480
|
-
paths.push({ path: `$streamStatus.${entry.name}`, kind: "data", typeHint: "string"
|
|
1481
|
-
paths.push({ path: `$streamError.${entry.name}`, kind: "data"
|
|
1482
|
+
paths.push({ path: `$streamStatus.${entry.name}`, kind: "data", typeHint: "string" });
|
|
1483
|
+
paths.push({ path: `$streamError.${entry.name}`, kind: "data" });
|
|
1482
1484
|
}
|
|
1483
1485
|
return;
|
|
1484
1486
|
}
|
|
1485
1487
|
if (prop.name === RESERVED_COMMAND_TOKENS_KEY && prop.value) {
|
|
1486
1488
|
for (const name of extractStringArrayItems(prop.value)) {
|
|
1487
|
-
paths.push({ path: `$command.${name}`, kind: "command"
|
|
1489
|
+
paths.push({ path: `$command.${name}`, kind: "command" });
|
|
1488
1490
|
}
|
|
1489
1491
|
return;
|
|
1490
1492
|
}
|
|
1491
1493
|
if (prop.name === RESERVED_EVENT_TOKENS_KEY && prop.value) {
|
|
1492
1494
|
for (const name of extractStringArrayItems(prop.value)) {
|
|
1493
|
-
paths.push({ path: name, kind: "eventToken"
|
|
1495
|
+
paths.push({ path: name, kind: "eventToken" });
|
|
1494
1496
|
}
|
|
1495
1497
|
return;
|
|
1496
1498
|
}
|
|
@@ -1502,22 +1504,22 @@ function collectReservedKeyPaths(prop, paths, pendingStreamValues, pendingListKe
|
|
|
1502
1504
|
return;
|
|
1503
1505
|
}
|
|
1504
1506
|
}
|
|
1505
|
-
function pushListKeyPaths(entry, paths
|
|
1507
|
+
function pushListKeyPaths(entry, paths) {
|
|
1506
1508
|
const listPath = entry.name;
|
|
1507
1509
|
const segments = listPath.split(".");
|
|
1508
1510
|
if (listPath.length === 0 || segments.some((s) => s.length === 0) || segments[segments.length - 1] === "*") {
|
|
1509
1511
|
return;
|
|
1510
1512
|
}
|
|
1511
|
-
const has = (path) => paths.some((p) => p.
|
|
1512
|
-
if (!has(listPath)) paths.push({ path: listPath, kind: "data", typeHint: "array"
|
|
1513
|
-
if (!has(`${listPath}.*`)) paths.push({ path: `${listPath}.*`, kind: "list"
|
|
1513
|
+
const has = (path) => paths.some((p) => p.path === path);
|
|
1514
|
+
if (!has(listPath)) paths.push({ path: listPath, kind: "data", typeHint: "array" });
|
|
1515
|
+
if (!has(`${listPath}.*`)) paths.push({ path: `${listPath}.*`, kind: "list" });
|
|
1514
1516
|
if (!has(`${listPath}.length`)) {
|
|
1515
|
-
paths.push({ path: `${listPath}.length`, kind: "data", typeHint: "number"
|
|
1517
|
+
paths.push({ path: `${listPath}.length`, kind: "data", typeHint: "number" });
|
|
1516
1518
|
}
|
|
1517
1519
|
const keyField = extractStringLiteralValue(entry.value);
|
|
1518
1520
|
if (keyField === null || keyField.includes(".") || keyField.includes("*")) return;
|
|
1519
1521
|
if (!has(`${listPath}.*.${keyField}`)) {
|
|
1520
|
-
paths.push({ path: `${listPath}.*.${keyField}`, kind: "data"
|
|
1522
|
+
paths.push({ path: `${listPath}.*.${keyField}`, kind: "data" });
|
|
1521
1523
|
}
|
|
1522
1524
|
}
|
|
1523
1525
|
function extractStringLiteralValue(value) {
|
|
@@ -1540,17 +1542,17 @@ function extractStringArrayItems(value) {
|
|
|
1540
1542
|
return items;
|
|
1541
1543
|
}
|
|
1542
1544
|
var MAX_OBJECT_NEST_DEPTH = 5;
|
|
1543
|
-
function pushDataPropertyPaths(prop, paths
|
|
1544
|
-
pushDataPropertyPathsAt(prop.name, prop, paths,
|
|
1545
|
+
function pushDataPropertyPaths(prop, paths) {
|
|
1546
|
+
pushDataPropertyPathsAt(prop.name, prop, paths, 0);
|
|
1545
1547
|
}
|
|
1546
|
-
function pushDataPropertyPathsAt(path, prop, paths,
|
|
1547
|
-
paths.push({ path, kind: "data", typeHint: prop.typeHint, rawInitial: prop.value?.trim()
|
|
1548
|
+
function pushDataPropertyPathsAt(path, prop, paths, depth) {
|
|
1549
|
+
paths.push({ path, kind: "data", typeHint: prop.typeHint, rawInitial: prop.value?.trim() });
|
|
1548
1550
|
if (prop.value && isArrayLiteral(prop.value)) {
|
|
1549
|
-
paths.push({ path: `${path}.*`, kind: "list"
|
|
1550
|
-
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number"
|
|
1551
|
+
paths.push({ path: `${path}.*`, kind: "list" });
|
|
1552
|
+
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number" });
|
|
1551
1553
|
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
1552
1554
|
for (const childProp of extractArrayElementDataProperties(prop.value)) {
|
|
1553
|
-
pushDataPropertyPathsAt(`${path}.*.${childProp.name}`, childProp, paths,
|
|
1555
|
+
pushDataPropertyPathsAt(`${path}.*.${childProp.name}`, childProp, paths, depth + 1);
|
|
1554
1556
|
}
|
|
1555
1557
|
return;
|
|
1556
1558
|
}
|
|
@@ -1559,11 +1561,11 @@ function pushDataPropertyPathsAt(path, prop, paths, stateName, depth) {
|
|
|
1559
1561
|
const childProps = parseTopLevelProperties(extractObjectContent(prop.value));
|
|
1560
1562
|
for (const childProp of childProps) {
|
|
1561
1563
|
if (childProp.kind !== "data") continue;
|
|
1562
|
-
pushDataPropertyPathsAt(`${path}.${childProp.name}`, childProp, paths,
|
|
1564
|
+
pushDataPropertyPathsAt(`${path}.${childProp.name}`, childProp, paths, depth + 1);
|
|
1563
1565
|
}
|
|
1564
1566
|
}
|
|
1565
1567
|
}
|
|
1566
|
-
function analyzeJsonPaths(jsonString
|
|
1568
|
+
function analyzeJsonPaths(jsonString) {
|
|
1567
1569
|
let data;
|
|
1568
1570
|
try {
|
|
1569
1571
|
data = JSON.parse(jsonString);
|
|
@@ -1572,31 +1574,31 @@ function analyzeJsonPaths(jsonString, stateName = "default") {
|
|
|
1572
1574
|
}
|
|
1573
1575
|
if (typeof data !== "object" || data === null || Array.isArray(data)) return [];
|
|
1574
1576
|
const paths = [];
|
|
1575
|
-
collectJsonPaths(data, "", paths,
|
|
1577
|
+
collectJsonPaths(data, "", paths, 0);
|
|
1576
1578
|
return paths;
|
|
1577
1579
|
}
|
|
1578
|
-
function collectJsonPaths(obj, prefix, paths,
|
|
1580
|
+
function collectJsonPaths(obj, prefix, paths, depth) {
|
|
1579
1581
|
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
1580
1582
|
for (const [key, value] of Object.entries(obj)) {
|
|
1581
1583
|
if (prefix === "" && key.startsWith("$")) continue;
|
|
1582
1584
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
1583
|
-
pushJsonValuePaths(path, value, paths,
|
|
1585
|
+
pushJsonValuePaths(path, value, paths, depth);
|
|
1584
1586
|
}
|
|
1585
1587
|
}
|
|
1586
|
-
function pushJsonValuePaths(path, value, paths,
|
|
1587
|
-
paths.push({ path, kind: "data", typeHint: inferJsonTypeHint(value)
|
|
1588
|
+
function pushJsonValuePaths(path, value, paths, depth) {
|
|
1589
|
+
paths.push({ path, kind: "data", typeHint: inferJsonTypeHint(value) });
|
|
1588
1590
|
if (Array.isArray(value)) {
|
|
1589
|
-
paths.push({ path: `${path}.*`, kind: "list"
|
|
1590
|
-
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number"
|
|
1591
|
+
paths.push({ path: `${path}.*`, kind: "list" });
|
|
1592
|
+
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number" });
|
|
1591
1593
|
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
1592
1594
|
if (value.length > 0 && typeof value[0] === "object" && value[0] !== null && !Array.isArray(value[0])) {
|
|
1593
1595
|
const firstElement = value[0];
|
|
1594
1596
|
for (const [childKey, childValue] of Object.entries(firstElement)) {
|
|
1595
|
-
pushJsonValuePaths(`${path}.*.${childKey}`, childValue, paths,
|
|
1597
|
+
pushJsonValuePaths(`${path}.*.${childKey}`, childValue, paths, depth + 1);
|
|
1596
1598
|
}
|
|
1597
1599
|
}
|
|
1598
1600
|
} else if (typeof value === "object" && value !== null) {
|
|
1599
|
-
collectJsonPaths(value, path, paths,
|
|
1601
|
+
collectJsonPaths(value, path, paths, depth + 1);
|
|
1600
1602
|
}
|
|
1601
1603
|
}
|
|
1602
1604
|
function inferJsonTypeHint(value) {
|
|
@@ -1836,23 +1838,21 @@ function inferTypeHint(valueStart) {
|
|
|
1836
1838
|
if (v.startsWith("{")) return "object";
|
|
1837
1839
|
return void 0;
|
|
1838
1840
|
}
|
|
1839
|
-
function analyzeSchemaPaths(schema
|
|
1841
|
+
function analyzeSchemaPaths(schema) {
|
|
1840
1842
|
const paths = [];
|
|
1841
1843
|
const defs = schema.$defs ?? {};
|
|
1842
|
-
collectSchemaObjectPaths(schema, "", paths,
|
|
1844
|
+
collectSchemaObjectPaths(schema, "", paths, defs, 0);
|
|
1843
1845
|
return paths;
|
|
1844
1846
|
}
|
|
1845
|
-
function mergeSchemaCandidates(candidates,
|
|
1846
|
-
if (
|
|
1847
|
+
function mergeSchemaCandidates(candidates, applicationSchema) {
|
|
1848
|
+
if (applicationSchema === void 0) return candidates;
|
|
1847
1849
|
const schemaCandidates = [];
|
|
1848
1850
|
const schemaKeys = /* @__PURE__ */ new Set();
|
|
1849
|
-
for (const
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
schemaKeys.add(`${stateName} ${p.path}`);
|
|
1853
|
-
}
|
|
1851
|
+
for (const p of analyzeSchemaPaths(applicationSchema)) {
|
|
1852
|
+
schemaCandidates.push(p);
|
|
1853
|
+
schemaKeys.add(p.path);
|
|
1854
1854
|
}
|
|
1855
|
-
const kept = candidates.filter((p) => !schemaKeys.has(
|
|
1855
|
+
const kept = candidates.filter((p) => !schemaKeys.has(p.path));
|
|
1856
1856
|
return [...kept, ...schemaCandidates];
|
|
1857
1857
|
}
|
|
1858
1858
|
function derefSchemaNodes(node, defs) {
|
|
@@ -1904,7 +1904,7 @@ function schemaTypeHint(nodes) {
|
|
|
1904
1904
|
}
|
|
1905
1905
|
return hints.size === 0 ? void 0 : [...hints].join("|");
|
|
1906
1906
|
}
|
|
1907
|
-
function collectSchemaObjectPaths(node, prefix, paths,
|
|
1907
|
+
function collectSchemaObjectPaths(node, prefix, paths, defs, depth) {
|
|
1908
1908
|
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
1909
1909
|
const seen = /* @__PURE__ */ new Set();
|
|
1910
1910
|
for (const n of derefSchemaNodes(node, defs)) {
|
|
@@ -1913,33 +1913,33 @@ function collectSchemaObjectPaths(node, prefix, paths, stateName, defs, depth) {
|
|
|
1913
1913
|
if (seen.has(key)) continue;
|
|
1914
1914
|
seen.add(key);
|
|
1915
1915
|
const path = prefix ? `${prefix}.${key}` : key;
|
|
1916
|
-
pushSchemaValuePaths(path, child, paths,
|
|
1916
|
+
pushSchemaValuePaths(path, child, paths, defs, depth);
|
|
1917
1917
|
}
|
|
1918
1918
|
}
|
|
1919
1919
|
}
|
|
1920
|
-
function pushSchemaValuePaths(path, node, paths,
|
|
1920
|
+
function pushSchemaValuePaths(path, node, paths, defs, depth) {
|
|
1921
1921
|
const nodes = derefSchemaNodes(node, defs);
|
|
1922
1922
|
const typeHint = schemaTypeHint(nodes);
|
|
1923
|
-
paths.push(withHint({ path, kind: "data",
|
|
1923
|
+
paths.push(withHint({ path, kind: "data", fromSchema: true }, typeHint));
|
|
1924
1924
|
const items = nodes.map((n) => n.items).find((i) => i !== void 0 && i !== null && typeof i === "object");
|
|
1925
1925
|
const isArray = items !== void 0 || (typeHint?.split("|").includes("array") ?? false);
|
|
1926
1926
|
if (isArray) {
|
|
1927
1927
|
const itemNodes = items !== void 0 ? derefSchemaNodes(items, defs) : [];
|
|
1928
|
-
paths.push(withHint({ path: `${path}.*`, kind: "list",
|
|
1929
|
-
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number",
|
|
1928
|
+
paths.push(withHint({ path: `${path}.*`, kind: "list", fromSchema: true }, schemaTypeHint(itemNodes)));
|
|
1929
|
+
paths.push({ path: `${path}.length`, kind: "data", typeHint: "number", fromSchema: true });
|
|
1930
1930
|
if (depth >= MAX_OBJECT_NEST_DEPTH) return;
|
|
1931
1931
|
const seen = /* @__PURE__ */ new Set();
|
|
1932
1932
|
for (const n of itemNodes) {
|
|
1933
1933
|
for (const [childKey, childNode] of Object.entries(n.properties ?? {})) {
|
|
1934
1934
|
if (seen.has(childKey)) continue;
|
|
1935
1935
|
seen.add(childKey);
|
|
1936
|
-
pushSchemaValuePaths(`${path}.*.${childKey}`, childNode, paths,
|
|
1936
|
+
pushSchemaValuePaths(`${path}.*.${childKey}`, childNode, paths, defs, depth + 1);
|
|
1937
1937
|
}
|
|
1938
1938
|
}
|
|
1939
1939
|
return;
|
|
1940
1940
|
}
|
|
1941
1941
|
if (nodes.some((n) => n.properties !== void 0)) {
|
|
1942
|
-
collectSchemaObjectPaths(node, path, paths,
|
|
1942
|
+
collectSchemaObjectPaths(node, path, paths, defs, depth + 1);
|
|
1943
1943
|
}
|
|
1944
1944
|
}
|
|
1945
1945
|
function withHint(candidate, typeHint) {
|
|
@@ -1963,7 +1963,7 @@ function parseWcsScriptBlocks(html, stateTagName = "wcs-state") {
|
|
|
1963
1963
|
pos++;
|
|
1964
1964
|
continue;
|
|
1965
1965
|
}
|
|
1966
|
-
const
|
|
1966
|
+
const mountPath = extractAttribute(wcsMatch.tagContent, "mount");
|
|
1967
1967
|
pos = wcsMatch.end;
|
|
1968
1968
|
const wcsCloseIdx = findCloseTag(html, pos, stateTagName);
|
|
1969
1969
|
const wcsEnd = wcsCloseIdx === -1 ? len : wcsCloseIdx;
|
|
@@ -1995,7 +1995,7 @@ function parseWcsScriptBlocks(html, stateTagName = "wcs-state") {
|
|
|
1995
1995
|
contentStart,
|
|
1996
1996
|
contentEnd,
|
|
1997
1997
|
content: html.slice(contentStart, contentEnd),
|
|
1998
|
-
|
|
1998
|
+
mountPath
|
|
1999
1999
|
});
|
|
2000
2000
|
pos = html.indexOf(">", scriptCloseIdx) + 1;
|
|
2001
2001
|
if (pos === 0) break;
|
|
@@ -2024,7 +2024,7 @@ function parseWcsStateElements(html, stateTagName = "wcs-state") {
|
|
|
2024
2024
|
pos++;
|
|
2025
2025
|
continue;
|
|
2026
2026
|
}
|
|
2027
|
-
const
|
|
2027
|
+
const mountPath = extractAttribute(wcsMatch.tagContent, "mount");
|
|
2028
2028
|
const jsonAttr = extractAttribute(wcsMatch.tagContent, "json") ?? void 0;
|
|
2029
2029
|
const stateAttr = extractAttribute(wcsMatch.tagContent, "state") ?? void 0;
|
|
2030
2030
|
const srcAttr = extractAttribute(wcsMatch.tagContent, "src") ?? void 0;
|
|
@@ -2061,12 +2061,12 @@ function parseWcsStateElements(html, stateTagName = "wcs-state") {
|
|
|
2061
2061
|
contentStart,
|
|
2062
2062
|
contentEnd: scriptCloseIdx,
|
|
2063
2063
|
content: html.slice(contentStart, scriptCloseIdx),
|
|
2064
|
-
|
|
2064
|
+
mountPath
|
|
2065
2065
|
});
|
|
2066
2066
|
pos = html.indexOf(">", scriptCloseIdx) + 1;
|
|
2067
2067
|
if (pos === 0) break;
|
|
2068
2068
|
}
|
|
2069
|
-
elements.push({
|
|
2069
|
+
elements.push({ mountPath, jsonAttr, stateAttr, srcAttr, scriptBlocks, tagStart, tagEnd });
|
|
2070
2070
|
pos = wcsEnd;
|
|
2071
2071
|
if (wcsCloseIdx !== -1) {
|
|
2072
2072
|
const closeEnd = html.indexOf(">", wcsCloseIdx);
|
|
@@ -2177,33 +2177,45 @@ function getStatePathsFromHtml(html, stateTagName = "wcs-state", fileReader) {
|
|
|
2177
2177
|
return allPaths;
|
|
2178
2178
|
}
|
|
2179
2179
|
function resolveElementPaths(element, html, fileReader) {
|
|
2180
|
+
const raw = resolveElementPathsRaw(element, html, fileReader);
|
|
2181
|
+
if (element.mountPath === null) return raw;
|
|
2182
|
+
const prefix = element.mountPath + ".";
|
|
2183
|
+
const out = [];
|
|
2184
|
+
for (const p of raw) {
|
|
2185
|
+
if (p.path.startsWith("$")) continue;
|
|
2186
|
+
if (p.kind === "method" || p.kind === "eventToken") continue;
|
|
2187
|
+
out.push({ ...p, path: prefix + p.path });
|
|
2188
|
+
}
|
|
2189
|
+
return out;
|
|
2190
|
+
}
|
|
2191
|
+
function resolveElementPathsRaw(element, html, fileReader) {
|
|
2180
2192
|
if (element.stateAttr) {
|
|
2181
2193
|
const jsonContent = findScriptJsonById(html, element.stateAttr);
|
|
2182
2194
|
if (jsonContent) {
|
|
2183
|
-
const paths = analyzeJsonPaths(jsonContent
|
|
2195
|
+
const paths = analyzeJsonPaths(jsonContent);
|
|
2184
2196
|
if (paths.length > 0) return paths;
|
|
2185
2197
|
}
|
|
2186
2198
|
}
|
|
2187
2199
|
if (element.srcAttr && fileReader) {
|
|
2188
|
-
const paths = resolveSrcAttribute(element.srcAttr,
|
|
2200
|
+
const paths = resolveSrcAttribute(element.srcAttr, fileReader);
|
|
2189
2201
|
if (paths.length > 0) return paths;
|
|
2190
2202
|
}
|
|
2191
2203
|
if (element.jsonAttr) {
|
|
2192
|
-
const paths = analyzeJsonPaths(element.jsonAttr
|
|
2204
|
+
const paths = analyzeJsonPaths(element.jsonAttr);
|
|
2193
2205
|
if (paths.length > 0) return paths;
|
|
2194
2206
|
}
|
|
2195
2207
|
if (element.scriptBlocks.length > 0) {
|
|
2196
2208
|
return element.scriptBlocks.flatMap(
|
|
2197
|
-
(block) => analyzeStatePaths(block.content
|
|
2209
|
+
(block) => analyzeStatePaths(block.content)
|
|
2198
2210
|
);
|
|
2199
2211
|
}
|
|
2200
2212
|
return [];
|
|
2201
2213
|
}
|
|
2202
|
-
function resolveSrcAttribute(srcPath,
|
|
2214
|
+
function resolveSrcAttribute(srcPath, fileReader) {
|
|
2203
2215
|
if (srcPath.endsWith(".json")) {
|
|
2204
2216
|
const content = fileReader(srcPath);
|
|
2205
2217
|
if (content) {
|
|
2206
|
-
return analyzeJsonPaths(content
|
|
2218
|
+
return analyzeJsonPaths(content);
|
|
2207
2219
|
}
|
|
2208
2220
|
return [];
|
|
2209
2221
|
}
|
|
@@ -2211,18 +2223,18 @@ function resolveSrcAttribute(srcPath, stateName, fileReader) {
|
|
|
2211
2223
|
const tsPath = srcPath.replace(/\.js$/, ".ts");
|
|
2212
2224
|
const tsContent = fileReader(tsPath);
|
|
2213
2225
|
if (tsContent) {
|
|
2214
|
-
return analyzeStatePaths(tsContent
|
|
2226
|
+
return analyzeStatePaths(tsContent);
|
|
2215
2227
|
}
|
|
2216
2228
|
const jsContent = fileReader(srcPath);
|
|
2217
2229
|
if (jsContent) {
|
|
2218
|
-
return analyzeStatePaths(jsContent
|
|
2230
|
+
return analyzeStatePaths(jsContent);
|
|
2219
2231
|
}
|
|
2220
2232
|
return [];
|
|
2221
2233
|
}
|
|
2222
2234
|
if (srcPath.endsWith(".ts")) {
|
|
2223
2235
|
const content = fileReader(srcPath);
|
|
2224
2236
|
if (content) {
|
|
2225
|
-
return analyzeStatePaths(content
|
|
2237
|
+
return analyzeStatePaths(content);
|
|
2226
2238
|
}
|
|
2227
2239
|
return [];
|
|
2228
2240
|
}
|
|
@@ -2397,8 +2409,20 @@ var ja = {
|
|
|
2397
2409
|
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`,
|
|
2398
2410
|
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`,
|
|
2399
2411
|
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`,
|
|
2400
|
-
namedStateAttrDeprecated: (name) =>
|
|
2401
|
-
namedStatePathDeprecated: (name) => name === "default" ? `"@default" \
|
|
2412
|
+
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`,
|
|
2413
|
+
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`,
|
|
2414
|
+
mountPathInvalid: (problem, mountPath) => {
|
|
2415
|
+
switch (problem) {
|
|
2416
|
+
case "empty":
|
|
2417
|
+
return `"mount" \u306B\u306F\u7A7A\u3067\u306A\u3044\u30C4\u30EA\u30FC\u30D1\u30B9\u304C\u5FC5\u8981\u3067\u3059\uFF08runtime: "mount" requires a non-empty tree path.\uFF09`;
|
|
2418
|
+
case "emptySegment":
|
|
2419
|
+
return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u7A7A\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u304C\u3042\u308A\u307E\u3059\uFF08runtime: has an empty segment.\uFF09`;
|
|
2420
|
+
case "wildcard":
|
|
2421
|
+
return `"mount" \u30D1\u30B9 "${mountPath}" \u306F\u9759\u7684\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 \u2014 \u30EF\u30A4\u30EB\u30C9\u30AB\u30FC\u30C9\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08runtime: must be static.\uFF09`;
|
|
2422
|
+
default:
|
|
2423
|
+
return `"mount" \u30D1\u30B9 "${mountPath}" \u306B\u4E88\u7D04\u6587\u5B57\uFF08$, #, @\uFF09\u306F\u4F7F\u3048\u307E\u305B\u3093\uFF08runtime: must not use reserved characters.\uFF09`;
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2402
2426
|
};
|
|
2403
2427
|
var EN_EXPECTED_LABEL = {
|
|
2404
2428
|
array: "an array-typed path",
|
|
@@ -2456,8 +2480,20 @@ var en = {
|
|
|
2456
2480
|
devtoolsAfterState: () => `Load @wcstack/devtools/auto BEFORE @wcstack/state/auto (otherwise the wiring ledger is not captured live)`,
|
|
2457
2481
|
baseHrefMissing: () => `An SPA using @wcstack/router needs <base href="/"> in <head> (without it, deep links misderive the basename)`,
|
|
2458
2482
|
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`,
|
|
2459
|
-
namedStateAttrDeprecated: (name) =>
|
|
2460
|
-
namedStatePathDeprecated: (name) => name === "default" ? `The "@default" selector
|
|
2483
|
+
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)`,
|
|
2484
|
+
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)`,
|
|
2485
|
+
mountPathInvalid: (problem, mountPath) => {
|
|
2486
|
+
switch (problem) {
|
|
2487
|
+
case "empty":
|
|
2488
|
+
return `"mount" requires a non-empty tree path.`;
|
|
2489
|
+
case "emptySegment":
|
|
2490
|
+
return `"mount" path "${mountPath}" has an empty segment.`;
|
|
2491
|
+
case "wildcard":
|
|
2492
|
+
return `"mount" path "${mountPath}" must be static (wildcards are not allowed).`;
|
|
2493
|
+
default:
|
|
2494
|
+
return `"mount" path "${mountPath}" must not use reserved characters ($, #, @).`;
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2461
2497
|
};
|
|
2462
2498
|
var CATALOGS = { ja, en };
|
|
2463
2499
|
function getMessages(locale3) {
|
|
@@ -2466,16 +2502,10 @@ function getMessages(locale3) {
|
|
|
2466
2502
|
|
|
2467
2503
|
// src/service/bindingValidator.ts
|
|
2468
2504
|
var filterMap = new Map(BUILTIN_FILTERS.map((f) => [f.name, f]));
|
|
2469
|
-
function validateBindings(html, attrName, stateTagName = "wcs-state", locale3, fileReader,
|
|
2505
|
+
function validateBindings(html, attrName, stateTagName = "wcs-state", locale3, fileReader, applicationSchema) {
|
|
2470
2506
|
const diagnostics = [];
|
|
2471
2507
|
const msgs = getMessages(locale3);
|
|
2472
|
-
const statePaths = mergeSchemaCandidates(getStatePathsFromHtml(html, stateTagName, fileReader),
|
|
2473
|
-
const pathsByState = /* @__PURE__ */ new Map();
|
|
2474
|
-
for (const p of statePaths) {
|
|
2475
|
-
const list = pathsByState.get(p.stateName) ?? [];
|
|
2476
|
-
list.push(p);
|
|
2477
|
-
pathsByState.set(p.stateName, list);
|
|
2478
|
-
}
|
|
2508
|
+
const statePaths = mergeSchemaCandidates(getStatePathsFromHtml(html, stateTagName, fileReader), applicationSchema);
|
|
2479
2509
|
const attrs = findAllBindAttributes(html, attrName);
|
|
2480
2510
|
let structuralTemplates = null;
|
|
2481
2511
|
const getStructuralTemplates = () => {
|
|
@@ -2508,7 +2538,7 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale3, f
|
|
|
2508
2538
|
for (const binding of bindings) {
|
|
2509
2539
|
const bindingStart = attr.valueStart + pos;
|
|
2510
2540
|
const parsed = parseBindingExpression(binding);
|
|
2511
|
-
const scopedPaths =
|
|
2541
|
+
const scopedPaths = statePaths;
|
|
2512
2542
|
const scopedPathSet = new Set(scopedPaths.map((p) => p.path));
|
|
2513
2543
|
const propNoMod = parsed.property.replace(/#.*$/, "").trim();
|
|
2514
2544
|
if (propNoMod === "...") {
|
|
@@ -2592,7 +2622,7 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale3, f
|
|
|
2592
2622
|
}
|
|
2593
2623
|
}
|
|
2594
2624
|
if (checkPath) {
|
|
2595
|
-
const schema =
|
|
2625
|
+
const schema = applicationSchema;
|
|
2596
2626
|
const verdict = schema !== void 0 ? validateSchemaPathExistence(checkPath, pathTrimmed, scopedPaths, scopedPathSet, commandNames, schema, msgs) : toMissingVerdict(validatePathExistence(checkPath, pathTrimmed, scopedPaths, scopedPathSet, commandNames, msgs));
|
|
2597
2627
|
if (verdict) {
|
|
2598
2628
|
const pathOffset = binding.indexOf(parsed.path);
|
|
@@ -2721,7 +2751,7 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale3, f
|
|
|
2721
2751
|
if (typeReq && resultType !== typeReq.expected) {
|
|
2722
2752
|
const pathOffset = binding.indexOf(parsed.path);
|
|
2723
2753
|
const pathStart = bindingStart + pathOffset;
|
|
2724
|
-
const schemaDefinite = typeReq.expected === "array" && parsed.filters.length === 0 &&
|
|
2754
|
+
const schemaDefinite = typeReq.expected === "array" && parsed.filters.length === 0 && applicationSchema !== void 0 && scopedPaths.some((p) => p.path === pathTrimmed && p.fromSchema === true);
|
|
2725
2755
|
diagnostics.push({
|
|
2726
2756
|
code: schemaDefinite ? WcsDiagnosticCode.PathTypeMismatch : WcsDiagnosticCode.BindingTypeExpectation,
|
|
2727
2757
|
start: pathStart,
|
|
@@ -2775,7 +2805,7 @@ function splitBindingExpressions(value) {
|
|
|
2775
2805
|
function parseBindingExpression(expr) {
|
|
2776
2806
|
const colonIndex = expr.indexOf(":");
|
|
2777
2807
|
if (colonIndex === -1) {
|
|
2778
|
-
return { property: expr.trim(), path: null,
|
|
2808
|
+
return { property: expr.trim(), path: null, filters: [], inputFilters: [] };
|
|
2779
2809
|
}
|
|
2780
2810
|
const rawProp = expr.slice(0, colonIndex);
|
|
2781
2811
|
const propSegments = splitByPipe(rawProp);
|
|
@@ -2787,9 +2817,8 @@ function parseBindingExpression(expr) {
|
|
|
2787
2817
|
const filterSegments = segments.slice(1);
|
|
2788
2818
|
const atIndex = pathSegment.indexOf("@");
|
|
2789
2819
|
const path = atIndex !== -1 ? pathSegment.slice(0, atIndex) : pathSegment;
|
|
2790
|
-
const targetState = atIndex !== -1 ? pathSegment.slice(atIndex + 1).trim() || "default" : "default";
|
|
2791
2820
|
const filters = parseFilterSegments(expr, filterSegments, colonIndex + 1 + pathSegment.length + 1);
|
|
2792
|
-
return { property, path: path.trim() || null,
|
|
2821
|
+
return { property, path: path.trim() || null, filters, inputFilters };
|
|
2793
2822
|
}
|
|
2794
2823
|
function parseFilterSegments(expr, segments, searchStart) {
|
|
2795
2824
|
const filters = [];
|
|
@@ -3313,11 +3342,11 @@ function isInsideTag(html, offset, tagName) {
|
|
|
3313
3342
|
}
|
|
3314
3343
|
|
|
3315
3344
|
// src/service/templateSyntaxValidator.ts
|
|
3316
|
-
function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", locale3, fileReader,
|
|
3345
|
+
function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", locale3, fileReader, applicationSchema) {
|
|
3317
3346
|
const diagnostics = [];
|
|
3318
3347
|
const msgs = getMessages(locale3);
|
|
3319
|
-
const allPaths = mergeSchemaCandidates(getStatePathsFromHtml(html, stateTagName, fileReader),
|
|
3320
|
-
const defaultSchema =
|
|
3348
|
+
const allPaths = mergeSchemaCandidates(getStatePathsFromHtml(html, stateTagName, fileReader), applicationSchema);
|
|
3349
|
+
const defaultSchema = applicationSchema;
|
|
3321
3350
|
const missingVerdict = (path, displayPath, pathSet2, scoped) => {
|
|
3322
3351
|
if (isValidTemplatePath(path, pathSet2, scoped)) return null;
|
|
3323
3352
|
if (defaultSchema !== void 0 && !path.startsWith("$")) {
|
|
@@ -3327,7 +3356,7 @@ function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", l
|
|
|
3327
3356
|
return { code: WcsDiagnosticCode.BindingPathMissing, severity: "warning", message: msgs.pathMissing(displayPath) };
|
|
3328
3357
|
};
|
|
3329
3358
|
if (allPaths.length === 0) return diagnostics;
|
|
3330
|
-
const defaultPaths = allPaths
|
|
3359
|
+
const defaultPaths = allPaths;
|
|
3331
3360
|
const pathSet = new Set(defaultPaths.map((p) => p.path));
|
|
3332
3361
|
const filterNameSet = new Set(BUILTIN_FILTERS.map((f) => f.name));
|
|
3333
3362
|
const mustaches = findAllMustacheSyntax(html);
|
|
@@ -3353,9 +3382,8 @@ function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", l
|
|
|
3353
3382
|
}
|
|
3354
3383
|
if (!item.expression) continue;
|
|
3355
3384
|
const parts = item.expression.split("|");
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
if (atIdx !== -1) pathPart = pathPart.slice(0, atIdx).trim();
|
|
3385
|
+
const pathPart = (parts[0] || "").trim();
|
|
3386
|
+
if (pathPart.includes("@")) continue;
|
|
3359
3387
|
const insideFor = item.insideTemplate && isInsideForTemplate(html, item.matchStart, bindAttrName);
|
|
3360
3388
|
if (pathPart && !/^-?\d|^["'`]|^true$|^false$|^null$/.test(pathPart)) {
|
|
3361
3389
|
if (!insideFor && pathPart.includes("*")) {
|
|
@@ -3376,7 +3404,7 @@ function validateTemplateSyntax(html, stateTagName, bindAttrName = "data-wcs", l
|
|
|
3376
3404
|
severity: "warning"
|
|
3377
3405
|
});
|
|
3378
3406
|
}
|
|
3379
|
-
if (insideFor && !pathPart.startsWith(".")
|
|
3407
|
+
if (insideFor && !pathPart.startsWith(".")) {
|
|
3380
3408
|
const indexMatch = /^\$(\d+)$/.exec(pathPart);
|
|
3381
3409
|
const needed = indexMatch !== null ? Number(indexMatch[1]) : pathPart.includes("*") ? countWildcardSegments(pathPart) : 0;
|
|
3382
3410
|
if (needed > 0) {
|
|
@@ -4838,7 +4866,7 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
4838
4866
|
return;
|
|
4839
4867
|
}
|
|
4840
4868
|
if (property === "trigger" && "trigger" in contract.inputs && parsed.path) {
|
|
4841
|
-
const cand = findDataSlot(getPaths(), parsed.path
|
|
4869
|
+
const cand = findDataSlot(getPaths(), parsed.path);
|
|
4842
4870
|
if (cand?.rawInitial === "true") {
|
|
4843
4871
|
diagnostics.push({
|
|
4844
4872
|
code: WcsDiagnosticCode.TriggerSeededTruthy,
|
|
@@ -4852,7 +4880,7 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
4852
4880
|
}
|
|
4853
4881
|
}
|
|
4854
4882
|
if (tagName === "wcs-storage" && property === "value" && !hasManual && parsed.path && !/(?:^|,)init=(?:element|auto)\b/.test(modifiers)) {
|
|
4855
|
-
const cand = findDataSlot(getPaths(), parsed.path
|
|
4883
|
+
const cand = findDataSlot(getPaths(), parsed.path);
|
|
4856
4884
|
if (cand?.rawInitial !== void 0 && EMPTYISH_SEEDS.has(normalizeSeed(cand.rawInitial))) {
|
|
4857
4885
|
diagnostics.push({
|
|
4858
4886
|
code: WcsDiagnosticCode.StorageSeedClobber,
|
|
@@ -4866,8 +4894,8 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
4866
4894
|
}
|
|
4867
4895
|
}
|
|
4868
4896
|
}
|
|
4869
|
-
function findDataSlot(paths, path
|
|
4870
|
-
return paths.find((c) => c.kind === "data" && c.path === path
|
|
4897
|
+
function findDataSlot(paths, path) {
|
|
4898
|
+
return paths.find((c) => c.kind === "data" && c.path === path);
|
|
4871
4899
|
}
|
|
4872
4900
|
function normalizeSeed(raw) {
|
|
4873
4901
|
const compact = raw.replace(/\s+/g, "");
|
|
@@ -5142,7 +5170,7 @@ function blankJsComments(code) {
|
|
|
5142
5170
|
}
|
|
5143
5171
|
|
|
5144
5172
|
// src/service/watchDeclarationValidator.ts
|
|
5145
|
-
var
|
|
5173
|
+
var STATE_NAME_SEPARATOR = "@";
|
|
5146
5174
|
function validateWatchDeclarations(html, stateTagName = "wcs-state", locale3) {
|
|
5147
5175
|
const msgs = getMessages(locale3);
|
|
5148
5176
|
const out = [];
|
|
@@ -5159,7 +5187,7 @@ function validateWatchDeclarations(html, stateTagName = "wcs-state", locale3) {
|
|
|
5159
5187
|
}
|
|
5160
5188
|
const entries = analyzeWatchEntries(block.content);
|
|
5161
5189
|
if (entries.length === 0) continue;
|
|
5162
|
-
const paths = analyzeStatePaths(block.content
|
|
5190
|
+
const paths = analyzeStatePaths(block.content);
|
|
5163
5191
|
const pathSet = new Set(paths.map((p) => p.path));
|
|
5164
5192
|
for (const entry of entries) {
|
|
5165
5193
|
const diagnostic = validateEntry(entry, pathSet, msgs);
|
|
@@ -5178,7 +5206,7 @@ function validateWatchDeclarations(html, stateTagName = "wcs-state", locale3) {
|
|
|
5178
5206
|
function validateEntry(entry, pathSet, msgs) {
|
|
5179
5207
|
const { key } = entry;
|
|
5180
5208
|
const invalid = (message) => ({ code: WcsDiagnosticCode.WatchDeclarationInvalid, message, severity: "error" });
|
|
5181
|
-
if (key.includes(
|
|
5209
|
+
if (key.includes(STATE_NAME_SEPARATOR)) {
|
|
5182
5210
|
return invalid(msgs.watchKeyCrossState(key));
|
|
5183
5211
|
}
|
|
5184
5212
|
if (key.startsWith("$")) {
|
|
@@ -5227,7 +5255,6 @@ function validateNamedState(html, attrName, stateTagName = "wcs-state", locale3)
|
|
|
5227
5255
|
const diagnostics = [];
|
|
5228
5256
|
for (const element of parseWcsStateElements(html, stateTagName)) {
|
|
5229
5257
|
const tagText = html.slice(element.tagStart, element.tagEnd);
|
|
5230
|
-
if (/\sbind-component(?=[\s=>/])/i.test(tagText)) continue;
|
|
5231
5258
|
const match = /(?:^|\s)name\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i.exec(tagText);
|
|
5232
5259
|
if (match === null) continue;
|
|
5233
5260
|
const value = match[1] ?? match[2] ?? match[3] ?? "";
|
|
@@ -5238,7 +5265,7 @@ function validateNamedState(html, attrName, stateTagName = "wcs-state", locale3)
|
|
|
5238
5265
|
start: valueEnd - value.length,
|
|
5239
5266
|
end: valueEnd,
|
|
5240
5267
|
message: msgs.namedStateAttrDeprecated(value),
|
|
5241
|
-
severity: "
|
|
5268
|
+
severity: "error"
|
|
5242
5269
|
});
|
|
5243
5270
|
}
|
|
5244
5271
|
for (const attr of findAllBindAttributes(html, attrName)) {
|
|
@@ -5251,27 +5278,62 @@ function validateNamedState(html, attrName, stateTagName = "wcs-state", locale3)
|
|
|
5251
5278
|
start: attr.valueStart + pos + selector.start,
|
|
5252
5279
|
end: attr.valueStart + pos + selector.end,
|
|
5253
5280
|
message: msgs.namedStatePathDeprecated(selector.name),
|
|
5254
|
-
severity: "
|
|
5281
|
+
severity: "error"
|
|
5255
5282
|
});
|
|
5256
5283
|
}
|
|
5257
5284
|
pos += expr.length + 1;
|
|
5258
5285
|
}
|
|
5259
5286
|
}
|
|
5260
|
-
for (const
|
|
5261
|
-
const selector = findStateSelector(
|
|
5287
|
+
for (const item of [...findAllMustacheSyntax(html), ...findAllCommentBindings(html)]) {
|
|
5288
|
+
const selector = findStateSelector(item.expression, true);
|
|
5262
5289
|
if (selector !== null) {
|
|
5263
5290
|
diagnostics.push({
|
|
5264
5291
|
code: WcsDiagnosticCode.NamedStateDeprecated,
|
|
5265
|
-
start:
|
|
5266
|
-
end:
|
|
5292
|
+
start: item.exprStart + selector.start,
|
|
5293
|
+
end: item.exprStart + selector.end,
|
|
5267
5294
|
message: msgs.namedStatePathDeprecated(selector.name),
|
|
5268
|
-
severity: "
|
|
5295
|
+
severity: "error"
|
|
5269
5296
|
});
|
|
5270
5297
|
}
|
|
5271
5298
|
}
|
|
5272
5299
|
return diagnostics;
|
|
5273
5300
|
}
|
|
5274
5301
|
|
|
5302
|
+
// src/service/mountAttrValidator.ts
|
|
5303
|
+
function findMountPathProblem(mountPath) {
|
|
5304
|
+
if (mountPath.length === 0) return "empty";
|
|
5305
|
+
for (const segment of mountPath.split(".")) {
|
|
5306
|
+
if (segment.length === 0) return "emptySegment";
|
|
5307
|
+
if (segment === "*") return "wildcard";
|
|
5308
|
+
if (segment.includes("$") || segment.includes("#") || segment.includes("@")) return "reserved";
|
|
5309
|
+
}
|
|
5310
|
+
return null;
|
|
5311
|
+
}
|
|
5312
|
+
function validateMountAttributes(html, stateTagName = "wcs-state", locale3) {
|
|
5313
|
+
const msgs = getMessages(locale3);
|
|
5314
|
+
const diagnostics = [];
|
|
5315
|
+
for (const element of parseWcsStateElements(html, stateTagName)) {
|
|
5316
|
+
if (element.mountPath === null) continue;
|
|
5317
|
+
const problem = findMountPathProblem(element.mountPath);
|
|
5318
|
+
if (problem === null) continue;
|
|
5319
|
+
const tagText = html.slice(element.tagStart, element.tagEnd);
|
|
5320
|
+
const match = /(?:^|\s)mount\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i.exec(tagText);
|
|
5321
|
+
if (match === null) continue;
|
|
5322
|
+
const value = match[1] ?? match[2] ?? match[3] ?? "";
|
|
5323
|
+
const quoted = match[1] !== void 0 || match[2] !== void 0;
|
|
5324
|
+
const valueEnd = element.tagStart + match.index + match[0].length - (quoted ? 1 : 0);
|
|
5325
|
+
const attrStart = element.tagStart + match.index + (/^\s/.test(match[0]) ? 1 : 0);
|
|
5326
|
+
diagnostics.push({
|
|
5327
|
+
code: WcsDiagnosticCode.MountPathInvalid,
|
|
5328
|
+
start: value.length === 0 ? attrStart : valueEnd - value.length,
|
|
5329
|
+
end: valueEnd + (quoted && value.length === 0 ? 1 : 0),
|
|
5330
|
+
message: msgs.mountPathInvalid(problem, element.mountPath),
|
|
5331
|
+
severity: "error"
|
|
5332
|
+
});
|
|
5333
|
+
}
|
|
5334
|
+
return diagnostics;
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5275
5337
|
// ../state/dist/parser.esm.js
|
|
5276
5338
|
var DELIMITER2 = ".";
|
|
5277
5339
|
var WILDCARD2 = "*";
|
|
@@ -5279,7 +5341,6 @@ var MAX_WILDCARD_DEPTH2 = 128;
|
|
|
5279
5341
|
var BINDING_SEPARATOR2 = ";";
|
|
5280
5342
|
var PROP_VALUE_SEPARATOR2 = ":";
|
|
5281
5343
|
var MODIFIER_SEPARATOR2 = "#";
|
|
5282
|
-
var STATE_NAME_SEPARATOR3 = "@";
|
|
5283
5344
|
var FILTER_SEPARATOR2 = "|";
|
|
5284
5345
|
var ELSE_KEYWORD2 = "else";
|
|
5285
5346
|
var SPREAD_PROP2 = "...";
|
|
@@ -6135,11 +6196,12 @@ function parseStatePart(statePart) {
|
|
|
6135
6196
|
} else {
|
|
6136
6197
|
stateAndPath = statePart.trim();
|
|
6137
6198
|
}
|
|
6138
|
-
if (stateAndPath.indexOf(
|
|
6139
|
-
|
|
6199
|
+
if (stateAndPath.indexOf("@") !== -1) {
|
|
6200
|
+
raiseError2(`"${stateAndPath}": 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 by its path prefix instead.`);
|
|
6201
|
+
}
|
|
6202
|
+
const statePathName = stateAndPath;
|
|
6140
6203
|
const pathInfo = getPathInfo(statePathName);
|
|
6141
6204
|
return {
|
|
6142
|
-
stateName,
|
|
6143
6205
|
statePathName,
|
|
6144
6206
|
statePathInfo: pathInfo,
|
|
6145
6207
|
outFilters: filters
|
|
@@ -6162,7 +6224,6 @@ function parseBindTextsForElement(bindText) {
|
|
|
6162
6224
|
propModifiers: [],
|
|
6163
6225
|
statePathName: "#else",
|
|
6164
6226
|
statePathInfo: pathInfo,
|
|
6165
|
-
stateName: "",
|
|
6166
6227
|
inFilters: [],
|
|
6167
6228
|
outFilters: [],
|
|
6168
6229
|
bindingType: "else"
|
|
@@ -6262,24 +6323,18 @@ function parseEmbeddedTextWithPositions(expression) {
|
|
|
6262
6323
|
error = e.message;
|
|
6263
6324
|
}
|
|
6264
6325
|
if (parsed === null) {
|
|
6265
|
-
return { exprRange, exprText: expression, parsed, error, propRange: null, pathRange: null
|
|
6326
|
+
return { exprRange, exprText: expression, parsed, error, propRange: null, pathRange: null };
|
|
6266
6327
|
}
|
|
6267
6328
|
const firstPipe = expression.indexOf(delimiters.filter);
|
|
6268
6329
|
const pathScopeEnd = firstPipe === -1 ? expression.length : firstPipe;
|
|
6269
6330
|
const pathLocal = locate(expression, parsed.statePathName, 0, pathScopeEnd);
|
|
6270
|
-
let stateNameLocal = null;
|
|
6271
|
-
const at = expression.indexOf(delimiters.stateName);
|
|
6272
|
-
if (at !== -1 && at < pathScopeEnd) {
|
|
6273
|
-
stateNameLocal = locate(expression, parsed.stateName, at + 1, pathScopeEnd);
|
|
6274
|
-
}
|
|
6275
6331
|
return {
|
|
6276
6332
|
exprRange,
|
|
6277
6333
|
exprText: expression,
|
|
6278
6334
|
parsed,
|
|
6279
6335
|
error,
|
|
6280
6336
|
propRange: null,
|
|
6281
|
-
pathRange: pathLocal
|
|
6282
|
-
stateNameRange: stateNameLocal
|
|
6337
|
+
pathRange: pathLocal
|
|
6283
6338
|
};
|
|
6284
6339
|
}
|
|
6285
6340
|
function parseBindTextWithPositions(bindText) {
|
|
@@ -6301,23 +6356,18 @@ function parseBindTextWithPositions(bindText) {
|
|
|
6301
6356
|
error = e.message;
|
|
6302
6357
|
}
|
|
6303
6358
|
if (parsed === null) {
|
|
6304
|
-
results.push({ exprRange, exprText: expr, parsed, error, propRange: null, pathRange: null
|
|
6359
|
+
results.push({ exprRange, exprText: expr, parsed, error, propRange: null, pathRange: null });
|
|
6305
6360
|
continue;
|
|
6306
6361
|
}
|
|
6307
6362
|
const colon = expr.indexOf(delimiters.propValue);
|
|
6308
6363
|
const propEndLimit = colon === -1 ? expr.length : colon;
|
|
6309
6364
|
const propLocal = locate(expr, parsed.propName, 0, propEndLimit);
|
|
6310
6365
|
let pathLocal = null;
|
|
6311
|
-
let stateNameLocal = null;
|
|
6312
6366
|
if (colon !== -1) {
|
|
6313
6367
|
const stateBase = colon + 1;
|
|
6314
6368
|
const firstPipe = expr.indexOf(delimiters.filter, stateBase);
|
|
6315
6369
|
const pathScopeEnd = firstPipe === -1 ? expr.length : firstPipe;
|
|
6316
6370
|
pathLocal = locate(expr, parsed.statePathName, stateBase, pathScopeEnd);
|
|
6317
|
-
const at = expr.indexOf(delimiters.stateName, stateBase);
|
|
6318
|
-
if (at !== -1 && at < pathScopeEnd) {
|
|
6319
|
-
stateNameLocal = locate(expr, parsed.stateName, at + 1, pathScopeEnd);
|
|
6320
|
-
}
|
|
6321
6371
|
}
|
|
6322
6372
|
const lift = (range) => range === null ? null : { start: exprStart + range.start, end: exprStart + range.end };
|
|
6323
6373
|
results.push({
|
|
@@ -6326,17 +6376,13 @@ function parseBindTextWithPositions(bindText) {
|
|
|
6326
6376
|
parsed,
|
|
6327
6377
|
error,
|
|
6328
6378
|
propRange: lift(propLocal),
|
|
6329
|
-
pathRange: lift(pathLocal)
|
|
6330
|
-
stateNameRange: lift(stateNameLocal)
|
|
6379
|
+
pathRange: lift(pathLocal)
|
|
6331
6380
|
});
|
|
6332
6381
|
}
|
|
6333
6382
|
return results;
|
|
6334
6383
|
}
|
|
6335
6384
|
|
|
6336
6385
|
// src/core/index/referenceIndex.ts
|
|
6337
|
-
function keyOf(stateName, path) {
|
|
6338
|
-
return `${stateName}\0${path}`;
|
|
6339
|
-
}
|
|
6340
6386
|
function buildReferenceIndex(html, options = {}) {
|
|
6341
6387
|
clearParserCaches();
|
|
6342
6388
|
const bindAttribute = options.bindAttribute ?? "data-wcs";
|
|
@@ -6354,13 +6400,11 @@ function buildReferenceIndex(html, options = {}) {
|
|
|
6354
6400
|
occurrences.push({
|
|
6355
6401
|
source: "attribute",
|
|
6356
6402
|
kind: binding.parsed.propSegments[0] === "eventToken" ? "eventToken" : "path",
|
|
6357
|
-
stateName: binding.parsed.stateName,
|
|
6358
6403
|
path: binding.parsed.statePathName,
|
|
6359
6404
|
pathRange: lift(binding.pathRange),
|
|
6360
6405
|
exprRange: lift(binding.exprRange),
|
|
6361
6406
|
propName: binding.parsed.propName,
|
|
6362
6407
|
propRange: binding.propRange === null ? null : lift(binding.propRange),
|
|
6363
|
-
stateNameRange: binding.stateNameRange === null ? null : lift(binding.stateNameRange),
|
|
6364
6408
|
bindingType: binding.parsed.bindingType
|
|
6365
6409
|
});
|
|
6366
6410
|
}
|
|
@@ -6383,22 +6427,21 @@ function buildReferenceIndex(html, options = {}) {
|
|
|
6383
6427
|
occurrences.push({
|
|
6384
6428
|
source: match.kind,
|
|
6385
6429
|
kind: "path",
|
|
6386
|
-
stateName: binding.parsed.stateName,
|
|
6387
6430
|
path: binding.parsed.statePathName,
|
|
6388
6431
|
pathRange: shift(binding.pathRange),
|
|
6389
6432
|
exprRange: { start: match.exprStart, end: match.exprEnd },
|
|
6390
6433
|
propName: null,
|
|
6391
6434
|
propRange: null,
|
|
6392
|
-
stateNameRange: binding.stateNameRange === null ? null : shift(binding.stateNameRange),
|
|
6393
6435
|
bindingType: "text"
|
|
6394
6436
|
});
|
|
6395
6437
|
}
|
|
6396
6438
|
const declarations = [];
|
|
6397
6439
|
for (const block of parseWcsScriptBlocks(html, stateTagName)) {
|
|
6440
|
+
const prefix = block.mountPath === null ? "" : block.mountPath + ".";
|
|
6398
6441
|
for (const span of analyzeDeclarationSpans(block.content)) {
|
|
6442
|
+
if (prefix !== "" && span.name.startsWith("$")) continue;
|
|
6399
6443
|
declarations.push({
|
|
6400
|
-
|
|
6401
|
-
name: span.name,
|
|
6444
|
+
name: prefix + span.name,
|
|
6402
6445
|
kind: span.kind,
|
|
6403
6446
|
range: { start: block.contentStart + span.start, end: block.contentStart + span.end }
|
|
6404
6447
|
});
|
|
@@ -6407,7 +6450,7 @@ function buildReferenceIndex(html, options = {}) {
|
|
|
6407
6450
|
const byPath = /* @__PURE__ */ new Map();
|
|
6408
6451
|
for (const occurrence of occurrences) {
|
|
6409
6452
|
if (occurrence.kind !== "path") continue;
|
|
6410
|
-
const key =
|
|
6453
|
+
const key = occurrence.path;
|
|
6411
6454
|
const list = byPath.get(key);
|
|
6412
6455
|
if (list === void 0) {
|
|
6413
6456
|
byPath.set(key, [occurrence]);
|
|
@@ -6417,22 +6460,22 @@ function buildReferenceIndex(html, options = {}) {
|
|
|
6417
6460
|
}
|
|
6418
6461
|
const declarationByName = /* @__PURE__ */ new Map();
|
|
6419
6462
|
for (const declaration of declarations) {
|
|
6420
|
-
const key =
|
|
6463
|
+
const key = declaration.name;
|
|
6421
6464
|
if (!declarationByName.has(key)) declarationByName.set(key, declaration);
|
|
6422
6465
|
}
|
|
6423
6466
|
return {
|
|
6424
6467
|
occurrences,
|
|
6425
6468
|
declarations,
|
|
6426
6469
|
problems,
|
|
6427
|
-
referencesOf(
|
|
6428
|
-
return (byPath.get(
|
|
6470
|
+
referencesOf(path) {
|
|
6471
|
+
return (byPath.get(path) ?? []).slice();
|
|
6429
6472
|
},
|
|
6430
|
-
declarationOf(
|
|
6431
|
-
const exact = declarationByName.get(
|
|
6473
|
+
declarationOf(path) {
|
|
6474
|
+
const exact = declarationByName.get(path);
|
|
6432
6475
|
if (exact !== void 0) return exact;
|
|
6433
6476
|
const firstSegment = path.split(".")[0];
|
|
6434
6477
|
if (firstSegment === path) return null;
|
|
6435
|
-
return declarationByName.get(
|
|
6478
|
+
return declarationByName.get(firstSegment) ?? null;
|
|
6436
6479
|
},
|
|
6437
6480
|
occurrenceAt(offset) {
|
|
6438
6481
|
for (const occurrence of occurrences) {
|
|
@@ -6677,8 +6720,9 @@ function validateUpdatedCallbackDemand(html, stateTagName, bindAttrName, locale3
|
|
|
6677
6720
|
for (const block of blocks) {
|
|
6678
6721
|
const callback = analyzeCallableBodies(block.content).find((entry) => entry.name === STATE_UPDATED_CALLBACK && entry.kind === "method");
|
|
6679
6722
|
if (callback === void 0) continue;
|
|
6680
|
-
|
|
6681
|
-
const
|
|
6723
|
+
if (block.mountPath !== null) continue;
|
|
6724
|
+
const declared = new Set(analyzeStatePaths(block.content).map((p) => p.path));
|
|
6725
|
+
const bound = boundPaths;
|
|
6682
6726
|
const body = blankComments(callback.body);
|
|
6683
6727
|
PATH_TEST_LITERAL.lastIndex = 0;
|
|
6684
6728
|
let match;
|
|
@@ -6701,27 +6745,18 @@ function validateUpdatedCallbackDemand(html, stateTagName, bindAttrName, locale3
|
|
|
6701
6745
|
return out;
|
|
6702
6746
|
}
|
|
6703
6747
|
function collectBoundPaths(html, stateTagName, bindAttrName) {
|
|
6704
|
-
const
|
|
6705
|
-
const add = (stateName, path) => {
|
|
6706
|
-
let set = byState.get(stateName);
|
|
6707
|
-
if (set === void 0) {
|
|
6708
|
-
set = /* @__PURE__ */ new Set();
|
|
6709
|
-
byState.set(stateName, set);
|
|
6710
|
-
}
|
|
6711
|
-
set.add(path);
|
|
6712
|
-
};
|
|
6748
|
+
const bound = /* @__PURE__ */ new Set();
|
|
6713
6749
|
const index = buildReferenceIndex(html, { bindAttribute: bindAttrName, stateTagName });
|
|
6714
6750
|
for (const occurrence of index.occurrences) {
|
|
6715
|
-
add(occurrence.
|
|
6751
|
+
bound.add(occurrence.path);
|
|
6716
6752
|
if (!occurrence.path.startsWith(".")) continue;
|
|
6717
6753
|
const forPath = getInnermostForPath(html, occurrence.pathRange.start, bindAttrName);
|
|
6718
6754
|
if (forPath === null || forPath.startsWith(".")) continue;
|
|
6719
|
-
add(
|
|
6720
|
-
occurrence.stateName,
|
|
6755
|
+
bound.add(
|
|
6721
6756
|
occurrence.path === "." ? `${forPath}.*` : `${forPath}.*.${occurrence.path.slice(1)}`
|
|
6722
6757
|
);
|
|
6723
6758
|
}
|
|
6724
|
-
return
|
|
6759
|
+
return bound;
|
|
6725
6760
|
}
|
|
6726
6761
|
function validateSemantics(html, stateTagName = "wcs-state", locale3, bindAttrName = "data-wcs") {
|
|
6727
6762
|
const out = [];
|
|
@@ -6742,22 +6777,19 @@ function discoverApplicationManifest(fileReader) {
|
|
|
6742
6777
|
const text = fileReader(relativePath);
|
|
6743
6778
|
if (text === void 0) continue;
|
|
6744
6779
|
const loaded = loadManifest({ text, source: relativePath });
|
|
6745
|
-
return { relativePath, text, loaded,
|
|
6780
|
+
return { relativePath, text, loaded, schema: applicationSchemaOf(loaded) };
|
|
6746
6781
|
}
|
|
6747
6782
|
return void 0;
|
|
6748
6783
|
}
|
|
6749
|
-
function
|
|
6750
|
-
const states = /* @__PURE__ */ new Map();
|
|
6784
|
+
function applicationSchemaOf(loaded) {
|
|
6751
6785
|
const manifest = loaded.manifest;
|
|
6752
|
-
if (manifest === null || manifest.kind !== "application") return
|
|
6786
|
+
if (manifest === null || manifest.kind !== "application") return void 0;
|
|
6753
6787
|
const application = manifest.manifestExtensions?.["wcstack.application"];
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
states.set(name, schema);
|
|
6758
|
-
}
|
|
6788
|
+
const schema = application?.stateSchema;
|
|
6789
|
+
if (schema !== null && typeof schema === "object" && !Array.isArray(schema)) {
|
|
6790
|
+
return schema;
|
|
6759
6791
|
}
|
|
6760
|
-
return
|
|
6792
|
+
return void 0;
|
|
6761
6793
|
}
|
|
6762
6794
|
|
|
6763
6795
|
// src/core/validateDocument.ts
|
|
@@ -6766,10 +6798,10 @@ function validateDocument(text, options = {}) {
|
|
|
6766
6798
|
const stateTagName = options.stateTagName ?? "wcs-state";
|
|
6767
6799
|
const locale3 = options.locale;
|
|
6768
6800
|
const fileReader = options.fileReader;
|
|
6769
|
-
const
|
|
6801
|
+
const applicationSchema = options.applicationSchema ?? (fileReader !== void 0 ? discoverApplicationManifest(fileReader)?.schema : void 0);
|
|
6770
6802
|
const out = [];
|
|
6771
|
-
out.push(...validateBindings(text, bindAttribute, stateTagName, locale3, fileReader,
|
|
6772
|
-
out.push(...validateTemplateSyntax(text, stateTagName, bindAttribute, locale3, fileReader,
|
|
6803
|
+
out.push(...validateBindings(text, bindAttribute, stateTagName, locale3, fileReader, applicationSchema));
|
|
6804
|
+
out.push(...validateTemplateSyntax(text, stateTagName, bindAttribute, locale3, fileReader, applicationSchema));
|
|
6773
6805
|
out.push(...validateIoNodes(text, bindAttribute, stateTagName, locale3, fileReader));
|
|
6774
6806
|
out.push(...validateAriaAttributes(text, bindAttribute, locale3));
|
|
6775
6807
|
out.push(...validateDocumentEnv(text, locale3));
|
|
@@ -6777,6 +6809,7 @@ function validateDocument(text, options = {}) {
|
|
|
6777
6809
|
out.push(...validateArrayMutations(text, stateTagName, locale3));
|
|
6778
6810
|
out.push(...validateWatchDeclarations(text, stateTagName, locale3));
|
|
6779
6811
|
out.push(...validateNamedState(text, bindAttribute, stateTagName, locale3));
|
|
6812
|
+
out.push(...validateMountAttributes(text, stateTagName, locale3));
|
|
6780
6813
|
for (const d of validateStateTypes(text, stateTagName, locale3)) {
|
|
6781
6814
|
out.push({ code: WcsDiagnosticCode.TypeAnnotation, start: d.start, end: d.end, message: d.message, severity: d.severity });
|
|
6782
6815
|
}
|