@wcstack/lint 1.31.0 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +147 -18
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -118,7 +118,7 @@ var WcsDiagnosticCode = {
|
|
|
118
118
|
TokenMisconfigured: "wcs/token-misconfigured",
|
|
119
119
|
NestedAssign: "wcs/nested-assign",
|
|
120
120
|
// --- 意味論(構文・存在検査では捕まらない取り違え。service/semanticValidator.ts) ---
|
|
121
|
-
// `$getAll` / `$resolve` の添字の本数がパスの `*` の本数と噛み合わない。
|
|
121
|
+
// `$getAll` / `$setAll` / `$resolve` の添字の本数がパスの `*` の本数と噛み合わない。
|
|
122
122
|
// ランタイムは同じ code で raiseError する(超過は以前は黙って無視されていた)。
|
|
123
123
|
IndexArity: "wcs/index-arity",
|
|
124
124
|
// ワイルドカードの階数がスコープの段数を超える(`matrix.*.*` を 1 段の for で読む、
|
|
@@ -157,6 +157,11 @@ var WcsDiagnosticCode = {
|
|
|
157
157
|
TriggerSeededTruthy: "wcs/trigger-seeded-truthy",
|
|
158
158
|
// 非 manual <wcs-storage> value バインド先の空値シード(初期書き戻しが保存値を上書き)。
|
|
159
159
|
StorageSeedClobber: "wcs/storage-seed-clobber",
|
|
160
|
+
// --- accessibility (docs/a11y-design.md §8 / D9) ---
|
|
161
|
+
// `attr.aria-*` バインドの属性名が WAI-ARIA に存在しない(タイポ)。
|
|
162
|
+
// setAttribute はそのまま書き、支援技術は黙って無視する。severity は warning
|
|
163
|
+
// (error 昇格時は packages/lint/scripts/smoke-test.mjs の対ケース更新が必須)。
|
|
164
|
+
AriaAttrUnknown: "wcs/aria-attr-unknown",
|
|
160
165
|
// --- document-level load configuration ---
|
|
161
166
|
// @wcstack/state/auto より後に他 wcstack /auto が読まれている。
|
|
162
167
|
ScriptOrder: "wcs/script-order",
|
|
@@ -391,12 +396,12 @@ var fix = (options) => {
|
|
|
391
396
|
};
|
|
392
397
|
};
|
|
393
398
|
var locale = (options) => {
|
|
394
|
-
const
|
|
399
|
+
const explicit = options?.[0];
|
|
395
400
|
return (value) => {
|
|
396
401
|
if (typeof value !== "number") {
|
|
397
402
|
valueMustBeNumber("locale");
|
|
398
403
|
}
|
|
399
|
-
return value.toLocaleString(
|
|
404
|
+
return value.toLocaleString(explicit ?? config.locale);
|
|
400
405
|
};
|
|
401
406
|
};
|
|
402
407
|
var uc = (_options) => {
|
|
@@ -576,30 +581,30 @@ var truncate = (options) => {
|
|
|
576
581
|
};
|
|
577
582
|
};
|
|
578
583
|
var date = (options) => {
|
|
579
|
-
const
|
|
584
|
+
const explicit = options?.[0];
|
|
580
585
|
return (value) => {
|
|
581
586
|
if (!(value instanceof Date)) {
|
|
582
587
|
valueMustBeDate("date");
|
|
583
588
|
}
|
|
584
|
-
return value.toLocaleDateString(
|
|
589
|
+
return value.toLocaleDateString(explicit ?? config.locale);
|
|
585
590
|
};
|
|
586
591
|
};
|
|
587
592
|
var time = (options) => {
|
|
588
|
-
const
|
|
593
|
+
const explicit = options?.[0];
|
|
589
594
|
return (value) => {
|
|
590
595
|
if (!(value instanceof Date)) {
|
|
591
596
|
valueMustBeDate("time");
|
|
592
597
|
}
|
|
593
|
-
return value.toLocaleTimeString(
|
|
598
|
+
return value.toLocaleTimeString(explicit ?? config.locale);
|
|
594
599
|
};
|
|
595
600
|
};
|
|
596
601
|
var datetime = (options) => {
|
|
597
|
-
const
|
|
602
|
+
const explicit = options?.[0];
|
|
598
603
|
return (value) => {
|
|
599
604
|
if (!(value instanceof Date)) {
|
|
600
605
|
valueMustBeDate("datetime");
|
|
601
606
|
}
|
|
602
|
-
return value.toLocaleString(
|
|
607
|
+
return value.toLocaleString(explicit ?? config.locale);
|
|
603
608
|
};
|
|
604
609
|
};
|
|
605
610
|
var ymd = (options) => {
|
|
@@ -1839,6 +1844,7 @@ var ja = {
|
|
|
1839
1844
|
tagCommandUnknown: (name, tag, declared) => `"${name}" \u306F <${tag}> \u306E command \u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF08\u5BA3\u8A00\u6E08\u307F: ${declared}\uFF09`,
|
|
1840
1845
|
spreadNoBindable: (tag) => `'...'\uFF08spread\uFF09\u306F <${tag}> \u306B\u6709\u52B9\u306A wcBindable \u5BA3\u8A00\u304C\u5FC5\u8981\u3067\u3059 \u2014 \u3053\u306E\u30BF\u30B0\u306F\u5BA3\u8A00\u3092\u6301\u305F\u306A\u3044\u305F\u3081\u3001\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u30A8\u30E9\u30FC\u3092\u9001\u51FA\u3057\u307E\u3059`,
|
|
1841
1846
|
tagEventTokenKeyUnknown: (name, tag, declared) => `eventToken \u306E\u30AD\u30FC "${name}" \u306F <${tag}> \u306E wcBindable \u30D7\u30ED\u30D1\u30C6\u30A3\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u751F DOM \u30A4\u30D9\u30F3\u30C8\u540D\u306F\u767A\u706B\u3057\u307E\u305B\u3093 \u2014 \u30D7\u30ED\u30D1\u30C6\u30A3\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5BA3\u8A00\u6E08\u307F: ${declared}\uFF09`,
|
|
1847
|
+
ariaAttrUnknown: (name) => `"${name}" \u306F WAI-ARIA \u306E\u5C5E\u6027\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002setAttribute \u306F\u305D\u306E\u307E\u307E\u66F8\u304D\u8FBC\u307F\u307E\u3059\u304C\u3001\u652F\u63F4\u6280\u8853\u306B\u306F\u9ED9\u3063\u3066\u7121\u8996\u3055\u308C\u307E\u3059`,
|
|
1842
1848
|
didYouMean: (c) => `\u3002\u3082\u3057\u304B\u3057\u3066: "${c}"`,
|
|
1843
1849
|
none: () => `\u306A\u3057`,
|
|
1844
1850
|
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`,
|
|
@@ -1893,6 +1899,7 @@ var en = {
|
|
|
1893
1899
|
tagCommandUnknown: (name, tag, declared) => `"${name}" is not a command of <${tag}> (declared: ${declared})`,
|
|
1894
1900
|
spreadNoBindable: (tag) => `'...' (spread) requires <${tag}> to expose a valid wcBindable declaration \u2014 this tag declares none, so the runtime raises an error`,
|
|
1895
1901
|
tagEventTokenKeyUnknown: (name, tag, declared) => `eventToken key "${name}" is not a wcBindable property of <${tag}>. Raw DOM event names never fire \u2014 use the property name (declared: ${declared})`,
|
|
1902
|
+
ariaAttrUnknown: (name) => `"${name}" is not a WAI-ARIA attribute. setAttribute writes it anyway, and assistive technology silently ignores it`,
|
|
1896
1903
|
didYouMean: (c) => `. Did you mean "${c}"?`,
|
|
1897
1904
|
none: () => `none`,
|
|
1898
1905
|
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`,
|
|
@@ -4006,6 +4013,35 @@ var BUILTIN_TAGS = {
|
|
|
4006
4013
|
"abort"
|
|
4007
4014
|
]
|
|
4008
4015
|
},
|
|
4016
|
+
"wcs-view-transition": {
|
|
4017
|
+
"package": "view-transition",
|
|
4018
|
+
"hasWcBindable": true,
|
|
4019
|
+
"observedAttributes": [
|
|
4020
|
+
"mode",
|
|
4021
|
+
"naming",
|
|
4022
|
+
"naming-limit",
|
|
4023
|
+
"reduced-motion",
|
|
4024
|
+
"types",
|
|
4025
|
+
"disabled",
|
|
4026
|
+
"for"
|
|
4027
|
+
],
|
|
4028
|
+
"inputs": {
|
|
4029
|
+
"disabled": "disabled",
|
|
4030
|
+
"mode": "mode",
|
|
4031
|
+
"naming": "naming",
|
|
4032
|
+
"namingLimit": "naming-limit",
|
|
4033
|
+
"reducedMotion": "reduced-motion",
|
|
4034
|
+
"types": "types",
|
|
4035
|
+
"participants": "for"
|
|
4036
|
+
},
|
|
4037
|
+
"properties": [
|
|
4038
|
+
"active",
|
|
4039
|
+
"error"
|
|
4040
|
+
],
|
|
4041
|
+
"commands": [
|
|
4042
|
+
"skip"
|
|
4043
|
+
]
|
|
4044
|
+
},
|
|
4009
4045
|
"wcs-wakelock": {
|
|
4010
4046
|
"package": "wakelock",
|
|
4011
4047
|
"hasWcBindable": true,
|
|
@@ -4318,6 +4354,98 @@ function hasBooleanAttribute(attrsText, attrName) {
|
|
|
4318
4354
|
return new RegExp(`(?:^|\\s)${attrName}(?:\\s|=|$)`, "i").test(attrsText);
|
|
4319
4355
|
}
|
|
4320
4356
|
|
|
4357
|
+
// src/service/ariaValidator.ts
|
|
4358
|
+
var ARIA_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
4359
|
+
// widget attributes
|
|
4360
|
+
"aria-autocomplete",
|
|
4361
|
+
"aria-checked",
|
|
4362
|
+
"aria-disabled",
|
|
4363
|
+
"aria-errormessage",
|
|
4364
|
+
"aria-expanded",
|
|
4365
|
+
"aria-haspopup",
|
|
4366
|
+
"aria-hidden",
|
|
4367
|
+
"aria-invalid",
|
|
4368
|
+
"aria-label",
|
|
4369
|
+
"aria-level",
|
|
4370
|
+
"aria-modal",
|
|
4371
|
+
"aria-multiline",
|
|
4372
|
+
"aria-multiselectable",
|
|
4373
|
+
"aria-orientation",
|
|
4374
|
+
"aria-placeholder",
|
|
4375
|
+
"aria-pressed",
|
|
4376
|
+
"aria-readonly",
|
|
4377
|
+
"aria-required",
|
|
4378
|
+
"aria-selected",
|
|
4379
|
+
"aria-sort",
|
|
4380
|
+
"aria-valuemax",
|
|
4381
|
+
"aria-valuemin",
|
|
4382
|
+
"aria-valuenow",
|
|
4383
|
+
"aria-valuetext",
|
|
4384
|
+
// live region attributes
|
|
4385
|
+
"aria-busy",
|
|
4386
|
+
"aria-live",
|
|
4387
|
+
"aria-relevant",
|
|
4388
|
+
"aria-atomic",
|
|
4389
|
+
// drag-and-drop (deprecated in 1.1, still valid names)
|
|
4390
|
+
"aria-dropeffect",
|
|
4391
|
+
"aria-grabbed",
|
|
4392
|
+
// relationship attributes
|
|
4393
|
+
"aria-activedescendant",
|
|
4394
|
+
"aria-colcount",
|
|
4395
|
+
"aria-colindex",
|
|
4396
|
+
"aria-colindextext",
|
|
4397
|
+
"aria-colspan",
|
|
4398
|
+
"aria-controls",
|
|
4399
|
+
"aria-describedby",
|
|
4400
|
+
"aria-details",
|
|
4401
|
+
"aria-flowto",
|
|
4402
|
+
"aria-labelledby",
|
|
4403
|
+
"aria-owns",
|
|
4404
|
+
"aria-posinset",
|
|
4405
|
+
"aria-rowcount",
|
|
4406
|
+
"aria-rowindex",
|
|
4407
|
+
"aria-rowindextext",
|
|
4408
|
+
"aria-rowspan",
|
|
4409
|
+
"aria-setsize",
|
|
4410
|
+
// global additions
|
|
4411
|
+
"aria-current",
|
|
4412
|
+
"aria-keyshortcuts",
|
|
4413
|
+
"aria-roledescription",
|
|
4414
|
+
// 1.3 additions with broad implementation
|
|
4415
|
+
"aria-braillelabel",
|
|
4416
|
+
"aria-brailleroledescription",
|
|
4417
|
+
"aria-description"
|
|
4418
|
+
]);
|
|
4419
|
+
function validateAriaAttributes(html, bindAttribute = "data-wcs", locale3) {
|
|
4420
|
+
const diagnostics = [];
|
|
4421
|
+
const msgs = getMessages(locale3);
|
|
4422
|
+
for (const attr of findAllBindAttributes(html, bindAttribute)) {
|
|
4423
|
+
let exprOffset = 0;
|
|
4424
|
+
for (const expr of splitBindingExpressions(attr.value)) {
|
|
4425
|
+
const exprStart = attr.valueStart + exprOffset;
|
|
4426
|
+
exprOffset += expr.length + 1;
|
|
4427
|
+
const property = parseBindingExpression(expr).property;
|
|
4428
|
+
if (!property) continue;
|
|
4429
|
+
const bare = property.split("#")[0];
|
|
4430
|
+
if (!bare.toLowerCase().startsWith("attr.aria-")) continue;
|
|
4431
|
+
const ariaName = bare.slice("attr.".length).toLowerCase();
|
|
4432
|
+
if (ARIA_ATTRIBUTES.has(ariaName)) continue;
|
|
4433
|
+
const propIndex = expr.indexOf(property);
|
|
4434
|
+
const start = propIndex === -1 ? exprStart : exprStart + propIndex;
|
|
4435
|
+
const end = propIndex === -1 ? exprStart + expr.length : start + property.length;
|
|
4436
|
+
diagnostics.push({
|
|
4437
|
+
code: WcsDiagnosticCode.AriaAttrUnknown,
|
|
4438
|
+
start,
|
|
4439
|
+
end,
|
|
4440
|
+
severity: "warning",
|
|
4441
|
+
member: ariaName,
|
|
4442
|
+
message: msgs.ariaAttrUnknown(ariaName) + suggestion(ariaName, [...ARIA_ATTRIBUTES], msgs)
|
|
4443
|
+
});
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
return diagnostics;
|
|
4447
|
+
}
|
|
4448
|
+
|
|
4321
4449
|
// src/service/documentEnvValidator.ts
|
|
4322
4450
|
function validateDocumentEnv(html, locale3) {
|
|
4323
4451
|
const diagnostics = [];
|
|
@@ -4863,12 +4991,12 @@ var fix2 = (options) => {
|
|
|
4863
4991
|
};
|
|
4864
4992
|
};
|
|
4865
4993
|
var locale2 = (options) => {
|
|
4866
|
-
const
|
|
4994
|
+
const explicit = options?.[0];
|
|
4867
4995
|
return (value) => {
|
|
4868
4996
|
if (typeof value !== "number") {
|
|
4869
4997
|
valueMustBeNumber2("locale");
|
|
4870
4998
|
}
|
|
4871
|
-
return value.toLocaleString(
|
|
4999
|
+
return value.toLocaleString(explicit ?? config2.locale);
|
|
4872
5000
|
};
|
|
4873
5001
|
};
|
|
4874
5002
|
var uc2 = (_options) => {
|
|
@@ -5048,30 +5176,30 @@ var truncate2 = (options) => {
|
|
|
5048
5176
|
};
|
|
5049
5177
|
};
|
|
5050
5178
|
var date2 = (options) => {
|
|
5051
|
-
const
|
|
5179
|
+
const explicit = options?.[0];
|
|
5052
5180
|
return (value) => {
|
|
5053
5181
|
if (!(value instanceof Date)) {
|
|
5054
5182
|
valueMustBeDate2("date");
|
|
5055
5183
|
}
|
|
5056
|
-
return value.toLocaleDateString(
|
|
5184
|
+
return value.toLocaleDateString(explicit ?? config2.locale);
|
|
5057
5185
|
};
|
|
5058
5186
|
};
|
|
5059
5187
|
var time2 = (options) => {
|
|
5060
|
-
const
|
|
5188
|
+
const explicit = options?.[0];
|
|
5061
5189
|
return (value) => {
|
|
5062
5190
|
if (!(value instanceof Date)) {
|
|
5063
5191
|
valueMustBeDate2("time");
|
|
5064
5192
|
}
|
|
5065
|
-
return value.toLocaleTimeString(
|
|
5193
|
+
return value.toLocaleTimeString(explicit ?? config2.locale);
|
|
5066
5194
|
};
|
|
5067
5195
|
};
|
|
5068
5196
|
var datetime2 = (options) => {
|
|
5069
|
-
const
|
|
5197
|
+
const explicit = options?.[0];
|
|
5070
5198
|
return (value) => {
|
|
5071
5199
|
if (!(value instanceof Date)) {
|
|
5072
5200
|
valueMustBeDate2("datetime");
|
|
5073
5201
|
}
|
|
5074
|
-
return value.toLocaleString(
|
|
5202
|
+
return value.toLocaleString(explicit ?? config2.locale);
|
|
5075
5203
|
};
|
|
5076
5204
|
};
|
|
5077
5205
|
var ymd2 = (options) => {
|
|
@@ -5663,7 +5791,7 @@ function buildReferenceIndex(html, options = {}) {
|
|
|
5663
5791
|
|
|
5664
5792
|
// src/service/semanticValidator.ts
|
|
5665
5793
|
var STATE_UPDATED_CALLBACK = "$updatedCallback";
|
|
5666
|
-
var API_CALL = /\.\s*\$(getAll|resolve)\s*\(/g;
|
|
5794
|
+
var API_CALL = /\.\s*\$(getAll|setAll|resolve)\s*\(/g;
|
|
5667
5795
|
var STRING_LITERAL = /^\s*(["'])((?:\\.|(?!\1)[^\\])*)\1\s*$/;
|
|
5668
5796
|
function splitCallArgs(source, open) {
|
|
5669
5797
|
const args = [];
|
|
@@ -5959,6 +6087,7 @@ function validateDocument(text, options = {}) {
|
|
|
5959
6087
|
out.push(...validateBindings(text, bindAttribute, stateTagName, locale3, fileReader));
|
|
5960
6088
|
out.push(...validateTemplateSyntax(text, stateTagName, bindAttribute, locale3, fileReader));
|
|
5961
6089
|
out.push(...validateIoNodes(text, bindAttribute, stateTagName, locale3, fileReader));
|
|
6090
|
+
out.push(...validateAriaAttributes(text, bindAttribute, locale3));
|
|
5962
6091
|
out.push(...validateDocumentEnv(text, locale3));
|
|
5963
6092
|
out.push(...validateSemantics(text, stateTagName, locale3, bindAttribute));
|
|
5964
6093
|
out.push(...validateArrayMutations(text, stateTagName, locale3));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/lint",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.32.0",
|
|
4
4
|
"description": "Static-contract validator CLI (wcs-validate) for wcstack data-wcs bindings and wcstack.manifest.json sidecars. Thin npm wrapper around the wcstack-intellisense validator core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|