@drskillissue/ganko 0.2.61 → 0.2.72
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.md +1 -1
- package/dist/{chunk-BK7TC7DN.js → chunk-MJKIL7DJ.js} +520 -339
- package/dist/chunk-MJKIL7DJ.js.map +1 -0
- package/dist/{chunk-5OEDGKHL.js → chunk-NFDA6LAI.js} +17 -15
- package/dist/chunk-NFDA6LAI.js.map +1 -0
- package/dist/eslint-plugin.cjs +500 -333
- package/dist/eslint-plugin.cjs.map +1 -1
- package/dist/eslint-plugin.js +1 -1
- package/dist/index.cjs +555 -373
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +24 -23
- package/dist/index.js.map +1 -1
- package/dist/rules-manifest.cjs +16 -14
- package/dist/rules-manifest.cjs.map +1 -1
- package/dist/rules-manifest.js +1 -1
- package/package.json +1 -2
- package/dist/chunk-5OEDGKHL.js.map +0 -1
- package/dist/chunk-BK7TC7DN.js.map +0 -1
|
@@ -67,9 +67,29 @@ function canonicalPath(path) {
|
|
|
67
67
|
return canonical;
|
|
68
68
|
}
|
|
69
69
|
var LOG_LEVELS = ["trace", "debug", "info", "warning", "error", "critical", "off"];
|
|
70
|
+
var Level = {
|
|
71
|
+
Trace: 0,
|
|
72
|
+
Debug: 1,
|
|
73
|
+
Info: 2,
|
|
74
|
+
Warning: 3,
|
|
75
|
+
Error: 4,
|
|
76
|
+
Critical: 5,
|
|
77
|
+
Off: 6
|
|
78
|
+
};
|
|
79
|
+
var LOG_LEVEL_ORDER = {
|
|
80
|
+
trace: Level.Trace,
|
|
81
|
+
debug: Level.Debug,
|
|
82
|
+
info: Level.Info,
|
|
83
|
+
warning: Level.Warning,
|
|
84
|
+
error: Level.Error,
|
|
85
|
+
critical: Level.Critical,
|
|
86
|
+
off: Level.Off
|
|
87
|
+
};
|
|
70
88
|
var noopLogger = {
|
|
71
|
-
enabled: false,
|
|
72
89
|
level: "off",
|
|
90
|
+
isLevelEnabled() {
|
|
91
|
+
return false;
|
|
92
|
+
},
|
|
73
93
|
trace() {
|
|
74
94
|
},
|
|
75
95
|
debug() {
|
|
@@ -3995,6 +4015,7 @@ function getStaticStringFromJSXValue(node) {
|
|
|
3995
4015
|
const expression = node.expression;
|
|
3996
4016
|
if (!expression) return null;
|
|
3997
4017
|
if (ts7.isStringLiteral(expression)) return expression.text;
|
|
4018
|
+
if (ts7.isNumericLiteral(expression)) return expression.text;
|
|
3998
4019
|
if (ts7.isNoSubstitutionTemplateLiteral(expression)) return expression.text;
|
|
3999
4020
|
if (ts7.isTemplateExpression(expression) && expression.templateSpans.length === 0) {
|
|
4000
4021
|
return expression.head.text;
|
|
@@ -4893,6 +4914,9 @@ function typeIncludesString(graph, node) {
|
|
|
4893
4914
|
function typeIsArray(graph, node) {
|
|
4894
4915
|
return graph.typeResolver.isArrayType(node);
|
|
4895
4916
|
}
|
|
4917
|
+
function typeIsStrictArray(graph, node) {
|
|
4918
|
+
return graph.typeResolver.isStrictArrayType(node);
|
|
4919
|
+
}
|
|
4896
4920
|
function getArrayElementKind(graph, node) {
|
|
4897
4921
|
return graph.typeResolver.getArrayElementKind(node);
|
|
4898
4922
|
}
|
|
@@ -15167,6 +15191,7 @@ var preferSetLookupInLoop = defineSolidRule({
|
|
|
15167
15191
|
options: options77,
|
|
15168
15192
|
check(graph, emit) {
|
|
15169
15193
|
const reported = /* @__PURE__ */ new Set();
|
|
15194
|
+
const graphHasTypes = hasTypeInfo(graph);
|
|
15170
15195
|
for (const method of LINEAR_SEARCH_METHODS) {
|
|
15171
15196
|
const calls = getCallsByMethodName(graph, method);
|
|
15172
15197
|
for (let i = 0, len = calls.length; i < len; i++) {
|
|
@@ -15184,6 +15209,7 @@ var preferSetLookupInLoop = defineSolidRule({
|
|
|
15184
15209
|
const loop = getEnclosingLoop(call.node);
|
|
15185
15210
|
if (!loop) continue;
|
|
15186
15211
|
if (!isDeclaredOutsideLoop2(loop, variable)) continue;
|
|
15212
|
+
if (graphHasTypes && !typeIsStrictArray(graph, callee.expression)) continue;
|
|
15187
15213
|
if (isStringLikeReceiver(graph, callee.expression, variable)) continue;
|
|
15188
15214
|
const key = `${loop.pos}:var:${variable.id}`;
|
|
15189
15215
|
if (reported.has(key)) continue;
|
|
@@ -18271,6 +18297,35 @@ var TypeResolver = class {
|
|
|
18271
18297
|
return false;
|
|
18272
18298
|
}
|
|
18273
18299
|
}
|
|
18300
|
+
/**
|
|
18301
|
+
* Strict array check: only matches Array<T>, T[], ReadonlyArray<T>, and tuples.
|
|
18302
|
+
* Does NOT match typed arrays (Uint8Array, Buffer, etc.) or other types with
|
|
18303
|
+
* a numeric index signature.
|
|
18304
|
+
*/
|
|
18305
|
+
isStrictArrayType(node) {
|
|
18306
|
+
try {
|
|
18307
|
+
const tsType = this.checker.getTypeAtLocation(node);
|
|
18308
|
+
return this.checkIsStrictArrayType(tsType);
|
|
18309
|
+
} catch {
|
|
18310
|
+
return false;
|
|
18311
|
+
}
|
|
18312
|
+
}
|
|
18313
|
+
checkIsStrictArrayType(tsType) {
|
|
18314
|
+
if (tsType.flags & 524288) {
|
|
18315
|
+
const objFlags = getObjectFlags(tsType);
|
|
18316
|
+
if (objFlags & 8) return true;
|
|
18317
|
+
if (objFlags & 4) {
|
|
18318
|
+
const name = tsType.getSymbol()?.getName();
|
|
18319
|
+
if (name === "Array" || name === "ReadonlyArray") return true;
|
|
18320
|
+
}
|
|
18321
|
+
}
|
|
18322
|
+
if (tsType.isUnion()) {
|
|
18323
|
+
for (const t of tsType.types) {
|
|
18324
|
+
if (this.checkIsStrictArrayType(t)) return true;
|
|
18325
|
+
}
|
|
18326
|
+
}
|
|
18327
|
+
return false;
|
|
18328
|
+
}
|
|
18274
18329
|
checkIsArrayType(tsType) {
|
|
18275
18330
|
if (tsType.flags & 524288) {
|
|
18276
18331
|
const objFlags = getObjectFlags(tsType);
|
|
@@ -18322,7 +18377,7 @@ var TypeResolver = class {
|
|
|
18322
18377
|
if (exprTsType.flags & ts101.TypeFlags.Any) return false;
|
|
18323
18378
|
if (targetTsType.flags & ts101.TypeFlags.Any) return false;
|
|
18324
18379
|
const result = this.checker.isTypeAssignableTo(exprTsType, targetTsType);
|
|
18325
|
-
if (this.logger.
|
|
18380
|
+
if (this.logger.isLevelEnabled(Level.Debug)) {
|
|
18326
18381
|
const exprStr = this.checker.typeToString(exprTsType);
|
|
18327
18382
|
const targetStr = this.checker.typeToString(targetTsType);
|
|
18328
18383
|
this.logger.debug(`isUnnecessaryCast: expr="${exprStr.slice(0, 120)}" target="${targetStr.slice(0, 120)}" assignable=${result} exprFlags=${exprTsType.flags} targetFlags=${targetTsType.flags}`);
|
|
@@ -25205,148 +25260,8 @@ function checkParagraphSpacing(graph, emit, policy, name) {
|
|
|
25205
25260
|
}
|
|
25206
25261
|
}
|
|
25207
25262
|
|
|
25208
|
-
// src/css/rules/a11y/css-policy-touch-target.ts
|
|
25209
|
-
var messages125 = {
|
|
25210
|
-
heightTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
25211
|
-
widthTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
25212
|
-
paddingTooSmall: "Horizontal padding `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`."
|
|
25213
|
-
};
|
|
25214
|
-
function classifyRule(rule) {
|
|
25215
|
-
if (rule.elementKinds.has("button")) return "button";
|
|
25216
|
-
if (rule.elementKinds.has("input")) return "input";
|
|
25217
|
-
return null;
|
|
25218
|
-
}
|
|
25219
|
-
var HEIGHT_PROPERTIES = /* @__PURE__ */ new Set(["height", "min-height"]);
|
|
25220
|
-
var WIDTH_PROPERTIES = /* @__PURE__ */ new Set(["width", "min-width"]);
|
|
25221
|
-
var HPADDING_PROPERTIES = /* @__PURE__ */ new Set(["padding-left", "padding-right", "padding-inline", "padding-inline-start", "padding-inline-end"]);
|
|
25222
|
-
var cssPolicyTouchTarget = defineCSSRule({
|
|
25223
|
-
id: "css-policy-touch-target",
|
|
25224
|
-
severity: "warn",
|
|
25225
|
-
messages: messages125,
|
|
25226
|
-
meta: {
|
|
25227
|
-
description: "Enforce minimum interactive element sizes per accessibility policy.",
|
|
25228
|
-
fixable: false,
|
|
25229
|
-
category: "css-a11y"
|
|
25230
|
-
},
|
|
25231
|
-
options: {},
|
|
25232
|
-
check(graph, emit) {
|
|
25233
|
-
const policy = getActivePolicy();
|
|
25234
|
-
if (policy === null) return;
|
|
25235
|
-
const name = getActivePolicyName() ?? "";
|
|
25236
|
-
const decls = graph.declarationsForProperties(
|
|
25237
|
-
"height",
|
|
25238
|
-
"min-height",
|
|
25239
|
-
"width",
|
|
25240
|
-
"min-width",
|
|
25241
|
-
"padding-left",
|
|
25242
|
-
"padding-right",
|
|
25243
|
-
"padding-inline",
|
|
25244
|
-
"padding-inline-start",
|
|
25245
|
-
"padding-inline-end"
|
|
25246
|
-
);
|
|
25247
|
-
for (let i = 0; i < decls.length; i++) {
|
|
25248
|
-
const d = decls[i];
|
|
25249
|
-
if (!d) continue;
|
|
25250
|
-
if (!d.rule) continue;
|
|
25251
|
-
const prop = d.property.toLowerCase();
|
|
25252
|
-
const kind = classifyRule(d.rule);
|
|
25253
|
-
if (!kind) continue;
|
|
25254
|
-
if (isVisuallyHiddenInput(d.rule)) continue;
|
|
25255
|
-
const px = parsePxValue(d.value);
|
|
25256
|
-
if (px === null) continue;
|
|
25257
|
-
if (HEIGHT_PROPERTIES.has(prop)) {
|
|
25258
|
-
const min = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
|
|
25259
|
-
if (px >= min) continue;
|
|
25260
|
-
emitCSSDiagnostic(
|
|
25261
|
-
emit,
|
|
25262
|
-
d.file.path,
|
|
25263
|
-
d.startLine,
|
|
25264
|
-
d.startColumn,
|
|
25265
|
-
cssPolicyTouchTarget,
|
|
25266
|
-
"heightTooSmall",
|
|
25267
|
-
resolveMessage(messages125.heightTooSmall, {
|
|
25268
|
-
property: d.property,
|
|
25269
|
-
value: d.value.trim(),
|
|
25270
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
25271
|
-
min: String(min),
|
|
25272
|
-
element: kind,
|
|
25273
|
-
policy: name
|
|
25274
|
-
})
|
|
25275
|
-
);
|
|
25276
|
-
continue;
|
|
25277
|
-
}
|
|
25278
|
-
if (WIDTH_PROPERTIES.has(prop)) {
|
|
25279
|
-
const min = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
|
|
25280
|
-
if (px >= min) continue;
|
|
25281
|
-
emitCSSDiagnostic(
|
|
25282
|
-
emit,
|
|
25283
|
-
d.file.path,
|
|
25284
|
-
d.startLine,
|
|
25285
|
-
d.startColumn,
|
|
25286
|
-
cssPolicyTouchTarget,
|
|
25287
|
-
"widthTooSmall",
|
|
25288
|
-
resolveMessage(messages125.widthTooSmall, {
|
|
25289
|
-
property: d.property,
|
|
25290
|
-
value: d.value.trim(),
|
|
25291
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
25292
|
-
min: String(min),
|
|
25293
|
-
element: kind,
|
|
25294
|
-
policy: name
|
|
25295
|
-
})
|
|
25296
|
-
);
|
|
25297
|
-
continue;
|
|
25298
|
-
}
|
|
25299
|
-
if (kind === "button" && HPADDING_PROPERTIES.has(prop)) {
|
|
25300
|
-
if (px >= policy.minButtonHorizontalPadding) continue;
|
|
25301
|
-
emitCSSDiagnostic(
|
|
25302
|
-
emit,
|
|
25303
|
-
d.file.path,
|
|
25304
|
-
d.startLine,
|
|
25305
|
-
d.startColumn,
|
|
25306
|
-
cssPolicyTouchTarget,
|
|
25307
|
-
"paddingTooSmall",
|
|
25308
|
-
resolveMessage(messages125.paddingTooSmall, {
|
|
25309
|
-
value: d.value.trim(),
|
|
25310
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
25311
|
-
min: String(policy.minButtonHorizontalPadding),
|
|
25312
|
-
element: kind,
|
|
25313
|
-
policy: name
|
|
25314
|
-
})
|
|
25315
|
-
);
|
|
25316
|
-
}
|
|
25317
|
-
}
|
|
25318
|
-
}
|
|
25319
|
-
});
|
|
25320
|
-
function isVisuallyHiddenInput(rule) {
|
|
25321
|
-
if (!hasPositionAbsoluteOrFixed(rule)) return false;
|
|
25322
|
-
if (!hasOpacityZero(rule)) return false;
|
|
25323
|
-
return true;
|
|
25324
|
-
}
|
|
25325
|
-
function hasPositionAbsoluteOrFixed(rule) {
|
|
25326
|
-
const positionDecls = rule.declarationIndex.get("position");
|
|
25327
|
-
if (!positionDecls || positionDecls.length === 0) return false;
|
|
25328
|
-
for (let i = 0; i < positionDecls.length; i++) {
|
|
25329
|
-
const decl = positionDecls[i];
|
|
25330
|
-
if (!decl) continue;
|
|
25331
|
-
const v = decl.value.trim().toLowerCase();
|
|
25332
|
-
if (v === "absolute" || v === "fixed") return true;
|
|
25333
|
-
}
|
|
25334
|
-
return false;
|
|
25335
|
-
}
|
|
25336
|
-
function hasOpacityZero(rule) {
|
|
25337
|
-
const opacityDecls = rule.declarationIndex.get("opacity");
|
|
25338
|
-
if (!opacityDecls || opacityDecls.length === 0) return false;
|
|
25339
|
-
for (let i = 0; i < opacityDecls.length; i++) {
|
|
25340
|
-
const decl = opacityDecls[i];
|
|
25341
|
-
if (!decl) continue;
|
|
25342
|
-
const v = decl.value.trim();
|
|
25343
|
-
if (v === "0") return true;
|
|
25344
|
-
}
|
|
25345
|
-
return false;
|
|
25346
|
-
}
|
|
25347
|
-
|
|
25348
25263
|
// src/css/rules/a11y/css-policy-typography.ts
|
|
25349
|
-
var
|
|
25264
|
+
var messages125 = {
|
|
25350
25265
|
fontTooSmall: "Font size `{{value}}` ({{resolved}}px) is below the `{{context}}` minimum of `{{min}}px` for policy `{{policy}}`.",
|
|
25351
25266
|
lineHeightTooSmall: "Line height `{{value}}` is below the `{{context}}` minimum of `{{min}}` for policy `{{policy}}`."
|
|
25352
25267
|
};
|
|
@@ -25382,7 +25297,7 @@ function resolveLineHeightContext(d, p) {
|
|
|
25382
25297
|
var cssPolicyTypography = defineCSSRule({
|
|
25383
25298
|
id: "css-policy-typography",
|
|
25384
25299
|
severity: "warn",
|
|
25385
|
-
messages:
|
|
25300
|
+
messages: messages125,
|
|
25386
25301
|
meta: {
|
|
25387
25302
|
description: "Enforce minimum font sizes and line heights per accessibility policy.",
|
|
25388
25303
|
fixable: false,
|
|
@@ -25409,7 +25324,7 @@ var cssPolicyTypography = defineCSSRule({
|
|
|
25409
25324
|
d.startColumn,
|
|
25410
25325
|
cssPolicyTypography,
|
|
25411
25326
|
"fontTooSmall",
|
|
25412
|
-
resolveMessage(
|
|
25327
|
+
resolveMessage(messages125.fontTooSmall, {
|
|
25413
25328
|
value: d.value.trim(),
|
|
25414
25329
|
resolved: String(Math.round(px * 100) / 100),
|
|
25415
25330
|
context,
|
|
@@ -25436,7 +25351,7 @@ var cssPolicyTypography = defineCSSRule({
|
|
|
25436
25351
|
d.startColumn,
|
|
25437
25352
|
cssPolicyTypography,
|
|
25438
25353
|
"lineHeightTooSmall",
|
|
25439
|
-
resolveMessage(
|
|
25354
|
+
resolveMessage(messages125.lineHeightTooSmall, {
|
|
25440
25355
|
value: d.value.trim(),
|
|
25441
25356
|
context,
|
|
25442
25357
|
min: String(min),
|
|
@@ -25454,7 +25369,7 @@ var ZERO_S = /(^|\s|,)0s($|\s|,)/;
|
|
|
25454
25369
|
var TIME_VALUE_G = /([0-9]*\.?[0-9]+)(ms|s)/g;
|
|
25455
25370
|
var AMPERSAND_G = /&/g;
|
|
25456
25371
|
var WHITESPACE_G = /\s+/g;
|
|
25457
|
-
var
|
|
25372
|
+
var messages126 = {
|
|
25458
25373
|
missingReducedMotion: "Animated selector `{{selector}}` lacks prefers-reduced-motion override."
|
|
25459
25374
|
};
|
|
25460
25375
|
function isAnimationDecl(p) {
|
|
@@ -25558,7 +25473,7 @@ function normalizeSelector(s) {
|
|
|
25558
25473
|
var cssRequireReducedMotionOverride = defineCSSRule({
|
|
25559
25474
|
id: "css-require-reduced-motion-override",
|
|
25560
25475
|
severity: "warn",
|
|
25561
|
-
messages:
|
|
25476
|
+
messages: messages126,
|
|
25562
25477
|
meta: {
|
|
25563
25478
|
description: "Require reduced-motion override for animated selectors.",
|
|
25564
25479
|
fixable: false,
|
|
@@ -25621,20 +25536,20 @@ var cssRequireReducedMotionOverride = defineCSSRule({
|
|
|
25621
25536
|
d.startColumn,
|
|
25622
25537
|
cssRequireReducedMotionOverride,
|
|
25623
25538
|
"missingReducedMotion",
|
|
25624
|
-
resolveMessage(
|
|
25539
|
+
resolveMessage(messages126.missingReducedMotion, { selector: r.selectorText })
|
|
25625
25540
|
);
|
|
25626
25541
|
}
|
|
25627
25542
|
}
|
|
25628
25543
|
});
|
|
25629
25544
|
|
|
25630
25545
|
// src/css/rules/structure/css-no-empty-rule.ts
|
|
25631
|
-
var
|
|
25546
|
+
var messages127 = {
|
|
25632
25547
|
emptyRule: "Empty rule `{{selector}}` should be removed."
|
|
25633
25548
|
};
|
|
25634
25549
|
var cssNoEmptyRule = defineCSSRule({
|
|
25635
25550
|
id: "css-no-empty-rule",
|
|
25636
25551
|
severity: "warn",
|
|
25637
|
-
messages:
|
|
25552
|
+
messages: messages127,
|
|
25638
25553
|
meta: {
|
|
25639
25554
|
description: "Disallow empty CSS rules.",
|
|
25640
25555
|
fixable: false,
|
|
@@ -25652,20 +25567,20 @@ var cssNoEmptyRule = defineCSSRule({
|
|
|
25652
25567
|
rule.startColumn,
|
|
25653
25568
|
cssNoEmptyRule,
|
|
25654
25569
|
"emptyRule",
|
|
25655
|
-
resolveMessage(
|
|
25570
|
+
resolveMessage(messages127.emptyRule, { selector: rule.selectorText })
|
|
25656
25571
|
);
|
|
25657
25572
|
}
|
|
25658
25573
|
}
|
|
25659
25574
|
});
|
|
25660
25575
|
|
|
25661
25576
|
// src/css/rules/structure/css-no-unknown-container-name.ts
|
|
25662
|
-
var
|
|
25577
|
+
var messages128 = {
|
|
25663
25578
|
unknownContainer: "Unknown container name `{{name}}` in @container query."
|
|
25664
25579
|
};
|
|
25665
25580
|
var cssNoUnknownContainerName = defineCSSRule({
|
|
25666
25581
|
id: "css-no-unknown-container-name",
|
|
25667
25582
|
severity: "error",
|
|
25668
|
-
messages:
|
|
25583
|
+
messages: messages128,
|
|
25669
25584
|
meta: {
|
|
25670
25585
|
description: "Disallow unknown named containers in @container queries.",
|
|
25671
25586
|
fixable: false,
|
|
@@ -25685,20 +25600,20 @@ var cssNoUnknownContainerName = defineCSSRule({
|
|
|
25685
25600
|
1,
|
|
25686
25601
|
cssNoUnknownContainerName,
|
|
25687
25602
|
"unknownContainer",
|
|
25688
|
-
resolveMessage(
|
|
25603
|
+
resolveMessage(messages128.unknownContainer, { name })
|
|
25689
25604
|
);
|
|
25690
25605
|
}
|
|
25691
25606
|
}
|
|
25692
25607
|
});
|
|
25693
25608
|
|
|
25694
25609
|
// src/css/rules/structure/css-no-unused-container-name.ts
|
|
25695
|
-
var
|
|
25610
|
+
var messages129 = {
|
|
25696
25611
|
unusedContainer: "Container name `{{name}}` is declared but never queried."
|
|
25697
25612
|
};
|
|
25698
25613
|
var cssNoUnusedContainerName = defineCSSRule({
|
|
25699
25614
|
id: "css-no-unused-container-name",
|
|
25700
25615
|
severity: "warn",
|
|
25701
|
-
messages:
|
|
25616
|
+
messages: messages129,
|
|
25702
25617
|
meta: {
|
|
25703
25618
|
description: "Disallow unused named containers.",
|
|
25704
25619
|
fixable: false,
|
|
@@ -25721,7 +25636,7 @@ var cssNoUnusedContainerName = defineCSSRule({
|
|
|
25721
25636
|
d.startColumn,
|
|
25722
25637
|
cssNoUnusedContainerName,
|
|
25723
25638
|
"unusedContainer",
|
|
25724
|
-
resolveMessage(
|
|
25639
|
+
resolveMessage(messages129.unusedContainer, { name })
|
|
25725
25640
|
);
|
|
25726
25641
|
}
|
|
25727
25642
|
}
|
|
@@ -25729,13 +25644,13 @@ var cssNoUnusedContainerName = defineCSSRule({
|
|
|
25729
25644
|
});
|
|
25730
25645
|
|
|
25731
25646
|
// src/css/rules/structure/layer-requirement-for-component-rules.ts
|
|
25732
|
-
var
|
|
25647
|
+
var messages130 = {
|
|
25733
25648
|
missingLayer: "Rule `{{selector}}` is not inside any @layer block while this file uses @layer. Place component rules inside an explicit layer."
|
|
25734
25649
|
};
|
|
25735
25650
|
var layerRequirementForComponentRules = defineCSSRule({
|
|
25736
25651
|
id: "layer-requirement-for-component-rules",
|
|
25737
25652
|
severity: "warn",
|
|
25738
|
-
messages:
|
|
25653
|
+
messages: messages130,
|
|
25739
25654
|
meta: {
|
|
25740
25655
|
description: "Require style rules to be inside @layer when the file defines layers.",
|
|
25741
25656
|
fixable: false,
|
|
@@ -25754,7 +25669,7 @@ var layerRequirementForComponentRules = defineCSSRule({
|
|
|
25754
25669
|
rule.startColumn,
|
|
25755
25670
|
layerRequirementForComponentRules,
|
|
25756
25671
|
"missingLayer",
|
|
25757
|
-
resolveMessage(
|
|
25672
|
+
resolveMessage(messages130.missingLayer, {
|
|
25758
25673
|
selector: rule.selectorText
|
|
25759
25674
|
})
|
|
25760
25675
|
);
|
|
@@ -25794,7 +25709,6 @@ var rules2 = [
|
|
|
25794
25709
|
selectorMaxAttributeAndUniversal,
|
|
25795
25710
|
selectorMaxSpecificity,
|
|
25796
25711
|
cssPolicyTypography,
|
|
25797
|
-
cssPolicyTouchTarget,
|
|
25798
25712
|
cssPolicySpacing,
|
|
25799
25713
|
cssPolicyContrast
|
|
25800
25714
|
];
|
|
@@ -30319,21 +30233,34 @@ function detectTailwindEntry(files) {
|
|
|
30319
30233
|
}
|
|
30320
30234
|
return themeOnlyFallback;
|
|
30321
30235
|
}
|
|
30322
|
-
async function resolveTailwindValidator(files) {
|
|
30236
|
+
async function resolveTailwindValidator(files, logger) {
|
|
30323
30237
|
const entry = detectTailwindEntry(files);
|
|
30324
|
-
if (!entry)
|
|
30238
|
+
if (!entry) {
|
|
30239
|
+
logger?.info('tailwind: no entry file detected (no @import "tailwindcss" or @theme block found in CSS files)');
|
|
30240
|
+
return null;
|
|
30241
|
+
}
|
|
30242
|
+
logger?.info(`tailwind: entry file detected: ${entry.path}`);
|
|
30325
30243
|
try {
|
|
30326
30244
|
const base = dirname2(entry.path);
|
|
30327
30245
|
const resolved = resolveTailwindNodePath(base);
|
|
30328
|
-
if (resolved === null)
|
|
30246
|
+
if (resolved === null) {
|
|
30247
|
+
logger?.warning(`tailwind: @tailwindcss/node not resolvable walking up from ${base}`);
|
|
30248
|
+
return null;
|
|
30249
|
+
}
|
|
30250
|
+
logger?.info(`tailwind: @tailwindcss/node resolved to ${resolved}`);
|
|
30329
30251
|
const mod = await import(resolved);
|
|
30330
|
-
if (typeof mod.__unstable__loadDesignSystem !== "function")
|
|
30252
|
+
if (typeof mod.__unstable__loadDesignSystem !== "function") {
|
|
30253
|
+
logger?.warning("tailwind: @tailwindcss/node module missing __unstable__loadDesignSystem export");
|
|
30254
|
+
return null;
|
|
30255
|
+
}
|
|
30331
30256
|
const design = await mod.__unstable__loadDesignSystem(
|
|
30332
30257
|
entry.content,
|
|
30333
30258
|
{ base }
|
|
30334
30259
|
);
|
|
30260
|
+
logger?.info("tailwind: design system loaded successfully");
|
|
30335
30261
|
return createLiveValidator(design);
|
|
30336
|
-
} catch {
|
|
30262
|
+
} catch (err) {
|
|
30263
|
+
logger?.warning(`tailwind: failed to load design system: ${err instanceof Error ? err.message : String(err)}`);
|
|
30337
30264
|
return null;
|
|
30338
30265
|
}
|
|
30339
30266
|
}
|
|
@@ -31201,7 +31128,7 @@ function publishLayoutPerfStatsForTest(stats) {
|
|
|
31201
31128
|
}
|
|
31202
31129
|
function maybeLogLayoutPerf(stats, log) {
|
|
31203
31130
|
if (process.env["SOLID_LINT_LAYOUT_PROFILE"] !== "1") return;
|
|
31204
|
-
if (!log || !log.
|
|
31131
|
+
if (!log || !log.isLevelEnabled(Level.Debug)) return;
|
|
31205
31132
|
const view = snapshotLayoutPerfStats(stats);
|
|
31206
31133
|
log.debug(
|
|
31207
31134
|
`[layout] elements=${view.elementsScanned} candidates=${view.selectorCandidatesChecked} compiledSelectors=${view.compiledSelectorCount} unsupportedSelectors=${view.selectorsRejectedUnsupported} conditionalSelectors=${view.selectorsGuardedConditional} ancestryChecks=${view.ancestryChecks} edges=${view.matchEdgesCreated} collected=${view.casesCollected} cases=${view.casesScored} rejectLowEvidence=${view.casesRejectedLowEvidence} rejectThreshold=${view.casesRejectedThreshold} rejectUndecidable=${view.casesRejectedUndecidable} rejectIdentifiability=${view.casesRejectedIdentifiability} undecidableInterval=${view.undecidableInterval} conditionalSignalRatio=${Math.round(view.conditionalSignalRatio * 1e3) / 1e3} conditionalSignals=${view.conditionalSignals} totalSignals=${view.totalSignals} cohortUnimodalFalse=${view.cohortUnimodalFalse} factorCoverageMean=${Math.round(view.factorCoverageMean * 1e3) / 1e3} posteriorWidthP95=${Math.round(view.posteriorWidthP95 * 1e3) / 1e3} uncertaintyEscalations=${view.uncertaintyEscalations} snapshots=${view.signalSnapshotsBuilt} snapshotHits=${view.signalSnapshotCacheHits} measurementIndexHits=${view.measurementIndexHits} contexts=${view.contextsClassified} diagnostics=${view.diagnosticsEmitted} selectorIndexMs=${Math.round(view.selectorIndexMs * 100) / 100} selectorMatchMs=${Math.round(view.selectorMatchMs * 100) / 100} cascadeBuildMs=${Math.round(view.cascadeBuildMs * 100) / 100} caseBuildMs=${Math.round(view.caseBuildMs * 100) / 100} scoringMs=${Math.round(view.scoringMs * 100) / 100} elapsedMs=${Math.round(view.elapsedMs * 100) / 100}`
|
|
@@ -31249,17 +31176,17 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31249
31176
|
if (cached !== void 0) return cached;
|
|
31250
31177
|
const binding = resolveTagBinding(normalizedFile, tag);
|
|
31251
31178
|
if (binding === null) {
|
|
31252
|
-
if (logger.
|
|
31179
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): binding=null`);
|
|
31253
31180
|
hostByTagCache.set(cacheKey, null);
|
|
31254
31181
|
return null;
|
|
31255
31182
|
}
|
|
31256
31183
|
if (binding.kind === "component") {
|
|
31257
|
-
if (logger.
|
|
31184
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): component, tagName=${binding.host.descriptor.tagName}, attrs=[${[...binding.host.descriptor.staticAttributes.keys()]}]`);
|
|
31258
31185
|
hostByTagCache.set(cacheKey, binding.host);
|
|
31259
31186
|
return binding.host;
|
|
31260
31187
|
}
|
|
31261
31188
|
const host = binding.base ? binding.base.host : null;
|
|
31262
|
-
if (logger.
|
|
31189
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): namespace, base=${host?.descriptor.tagName ?? "null"}`);
|
|
31263
31190
|
hostByTagCache.set(cacheKey, host);
|
|
31264
31191
|
return host;
|
|
31265
31192
|
},
|
|
@@ -31272,26 +31199,26 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31272
31199
|
}
|
|
31273
31200
|
};
|
|
31274
31201
|
function resolveComponentHostEntry(entry) {
|
|
31275
|
-
if (entry.resolution === "resolved")
|
|
31276
|
-
|
|
31202
|
+
if (entry.resolution === "resolved") {
|
|
31203
|
+
return { descriptor: entry.descriptor, hostElementRef: entry.hostElementRef };
|
|
31204
|
+
}
|
|
31205
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveComponentHostEntry: deferred innerTag=${entry.innerTag}, file=${entry.filePath}, attrs=[${[...entry.staticAttributes.keys()]}]`);
|
|
31277
31206
|
const innerBinding = resolveLocalIdentifierBinding(entry.filePath, entry.innerTag);
|
|
31278
|
-
if (logger.
|
|
31207
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] innerBinding=${innerBinding === null ? "null" : innerBinding.kind}`);
|
|
31279
31208
|
const innerHost = extractHostFromBinding(innerBinding);
|
|
31280
|
-
if (logger.
|
|
31281
|
-
let tagName = innerHost !== null ? innerHost.tagName : null;
|
|
31209
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] innerHost=${innerHost === null ? "null" : `tagName=${innerHost.descriptor.tagName}, attrs=[${[...innerHost.descriptor.staticAttributes.keys()]}]`}`);
|
|
31210
|
+
let tagName = innerHost !== null ? innerHost.descriptor.tagName : null;
|
|
31282
31211
|
if (tagName === null) {
|
|
31283
31212
|
tagName = resolveTagNameFromPolymorphicProp(entry.staticAttributes);
|
|
31284
|
-
if (logger.
|
|
31213
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] polymorphic fallback: tagName=${tagName}`);
|
|
31285
31214
|
}
|
|
31286
|
-
const staticAttributes = innerHost !== null ? mergeStaticAttributes(entry.staticAttributes, innerHost.staticAttributes) : entry.staticAttributes;
|
|
31287
|
-
const staticClassTokens = innerHost !== null ? mergeStaticClassTokens(entry.staticClassTokens, innerHost.staticClassTokens) : entry.staticClassTokens;
|
|
31288
|
-
const forwardsChildren = entry.forwardsChildren || innerHost !== null && innerHost.forwardsChildren;
|
|
31289
|
-
if (logger.
|
|
31215
|
+
const staticAttributes = innerHost !== null ? mergeStaticAttributes(entry.staticAttributes, innerHost.descriptor.staticAttributes) : entry.staticAttributes;
|
|
31216
|
+
const staticClassTokens = innerHost !== null ? mergeStaticClassTokens(entry.staticClassTokens, innerHost.descriptor.staticClassTokens) : entry.staticClassTokens;
|
|
31217
|
+
const forwardsChildren = entry.forwardsChildren || innerHost !== null && innerHost.descriptor.forwardsChildren;
|
|
31218
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolved: tagName=${tagName}, attrs=[${[...staticAttributes.keys()]}], classes=[${staticClassTokens}]`);
|
|
31290
31219
|
return {
|
|
31291
|
-
tagName,
|
|
31292
|
-
|
|
31293
|
-
staticClassTokens,
|
|
31294
|
-
forwardsChildren
|
|
31220
|
+
descriptor: { tagName, staticAttributes, staticClassTokens, forwardsChildren },
|
|
31221
|
+
hostElementRef: innerHost?.hostElementRef ?? null
|
|
31295
31222
|
};
|
|
31296
31223
|
}
|
|
31297
31224
|
function extractHostFromBinding(binding) {
|
|
@@ -31332,10 +31259,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31332
31259
|
if (hostEntry) {
|
|
31333
31260
|
const resolved = resolveComponentHostEntry(hostEntry);
|
|
31334
31261
|
if (resolved !== null) {
|
|
31335
|
-
const binding = {
|
|
31336
|
-
kind: "component",
|
|
31337
|
-
host: resolved
|
|
31338
|
-
};
|
|
31262
|
+
const binding = { kind: "component", host: resolved };
|
|
31339
31263
|
localBindingCache.set(key, binding);
|
|
31340
31264
|
resolvingLocal.delete(key);
|
|
31341
31265
|
return binding;
|
|
@@ -31396,7 +31320,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31396
31320
|
const baseExpression = toExpressionArgument(firstArg);
|
|
31397
31321
|
if (baseExpression === null) return null;
|
|
31398
31322
|
const baseBinding = resolveBindingFromExpression(filePath, baseExpression);
|
|
31399
|
-
if (logger.
|
|
31323
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] Object.assign base: ${baseBinding === null ? "null" : baseBinding.kind}${baseBinding?.kind === "component" ? `, tagName=${baseBinding.host.descriptor.tagName}` : ""}`);
|
|
31400
31324
|
let baseComponent = null;
|
|
31401
31325
|
const members = /* @__PURE__ */ new Map();
|
|
31402
31326
|
if (baseBinding && baseBinding.kind === "component") {
|
|
@@ -31422,7 +31346,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31422
31346
|
if (!ts123.isObjectLiteralExpression(argument)) continue;
|
|
31423
31347
|
appendObjectExpressionMembers(filePath, argument, members);
|
|
31424
31348
|
}
|
|
31425
|
-
if (logger.
|
|
31349
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] Object.assign result: base=${baseComponent === null ? "null" : `tagName=${baseComponent.host.descriptor.tagName}`}, members=[${[...members.keys()]}]`);
|
|
31426
31350
|
if (baseComponent === null && members.size === 0) return null;
|
|
31427
31351
|
return {
|
|
31428
31352
|
kind: "namespace",
|
|
@@ -31464,7 +31388,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31464
31388
|
}
|
|
31465
31389
|
function resolveBindingFromImport(filePath, importBinding) {
|
|
31466
31390
|
const resolvedModule = moduleResolver.resolveSolid(filePath, importBinding.source) ?? resolveAndIndexExternalModule(filePath, importBinding.source);
|
|
31467
|
-
if (logger.
|
|
31391
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveBindingFromImport: source=${importBinding.source}, kind=${importBinding.kind}, resolvedModule=${resolvedModule}`);
|
|
31468
31392
|
if (resolvedModule === null) return null;
|
|
31469
31393
|
const normalized = resolve4(resolvedModule);
|
|
31470
31394
|
if (importBinding.kind === "namespace") {
|
|
@@ -31473,7 +31397,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
31473
31397
|
const exportName = importBinding.kind === "default" ? "default" : importBinding.importedName;
|
|
31474
31398
|
if (exportName === null) return null;
|
|
31475
31399
|
const result = resolveExportBinding(normalized, exportName);
|
|
31476
|
-
if (logger.
|
|
31400
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] export ${exportName}: ${result === null ? "null" : result.kind}`);
|
|
31477
31401
|
return result;
|
|
31478
31402
|
}
|
|
31479
31403
|
function resolveAndIndexExternalModule(importerFile, importSource) {
|
|
@@ -31667,6 +31591,7 @@ function collectComponentHosts(graph) {
|
|
|
31667
31591
|
}
|
|
31668
31592
|
function resolveComponentHostEntryForFunction(graph, fn) {
|
|
31669
31593
|
let entry = null;
|
|
31594
|
+
let hostElementRefAgreed = true;
|
|
31670
31595
|
const bodyEntry = resolveHostEntryFromFunctionBody(graph, fn);
|
|
31671
31596
|
if (bodyEntry !== null) {
|
|
31672
31597
|
entry = bodyEntry;
|
|
@@ -31682,9 +31607,17 @@ function resolveComponentHostEntryForFunction(graph, fn) {
|
|
|
31682
31607
|
entry = returnEntry;
|
|
31683
31608
|
continue;
|
|
31684
31609
|
}
|
|
31685
|
-
if (areComponentHostEntriesEqual(entry, returnEntry))
|
|
31610
|
+
if (areComponentHostEntriesEqual(entry, returnEntry)) {
|
|
31611
|
+
if (hostElementRefAgreed && entry.resolution === "resolved" && returnEntry.resolution === "resolved" && entry.hostElementRef !== returnEntry.hostElementRef) {
|
|
31612
|
+
hostElementRefAgreed = false;
|
|
31613
|
+
}
|
|
31614
|
+
continue;
|
|
31615
|
+
}
|
|
31686
31616
|
return null;
|
|
31687
31617
|
}
|
|
31618
|
+
if (!hostElementRefAgreed && entry !== null && entry.resolution === "resolved") {
|
|
31619
|
+
return { resolution: "resolved", descriptor: entry.descriptor, hostElementRef: null };
|
|
31620
|
+
}
|
|
31688
31621
|
return entry;
|
|
31689
31622
|
}
|
|
31690
31623
|
function resolveHostEntryFromFunctionBody(graph, fn) {
|
|
@@ -31712,7 +31645,8 @@ function resolveHostEntryFromJSXElement(graph, node) {
|
|
|
31712
31645
|
staticAttributes: collectStaticAttributes(element),
|
|
31713
31646
|
staticClassTokens: getStaticClassTokensForElementEntity(graph, element),
|
|
31714
31647
|
forwardsChildren: detectChildrenForwarding(element)
|
|
31715
|
-
}
|
|
31648
|
+
},
|
|
31649
|
+
hostElementRef: { solid: graph, element }
|
|
31716
31650
|
};
|
|
31717
31651
|
}
|
|
31718
31652
|
if (isContextProviderTag(element.tag)) {
|
|
@@ -32881,7 +32815,7 @@ function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
|
|
|
32881
32815
|
ancestor = ancestor.parentElementNode;
|
|
32882
32816
|
}
|
|
32883
32817
|
if (fileRootElements !== null) {
|
|
32884
|
-
if (logger.
|
|
32818
|
+
if (logger.isLevelEnabled(Level.Trace)) {
|
|
32885
32819
|
const compoundDesc = describeCompound(targetCompound);
|
|
32886
32820
|
logger.trace(`[selector-match] fallback: node=${node.key} tag=${node.tagName} checking ${fileRootElements.length} roots for compound=${compoundDesc}`);
|
|
32887
32821
|
}
|
|
@@ -32892,11 +32826,11 @@ function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
|
|
|
32892
32826
|
if (root.solidFile !== node.solidFile) continue;
|
|
32893
32827
|
perf.ancestryChecks++;
|
|
32894
32828
|
const compoundResult = matchesCompound(root, targetCompound);
|
|
32895
|
-
if (logger.
|
|
32829
|
+
if (logger.isLevelEnabled(Level.Trace) && compoundResult === "no-match") {
|
|
32896
32830
|
logger.trace(`[selector-match] fallback MISS: root=${root.key} tag=${root.tagName} attrs=[${[...root.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}]`);
|
|
32897
32831
|
}
|
|
32898
32832
|
if (compoundResult !== "no-match") {
|
|
32899
|
-
if (logger.
|
|
32833
|
+
if (logger.isLevelEnabled(Level.Debug)) {
|
|
32900
32834
|
const compoundDesc = describeCompound(targetCompound);
|
|
32901
32835
|
logger.debug(`[selector-match] fallback HIT: node=${node.key} tag=${node.tagName} matched root=${root.key} tag=${root.tagName} compound=${compoundDesc} isFinal=${isFinal}`);
|
|
32902
32836
|
}
|
|
@@ -34019,6 +33953,9 @@ function readBaselineOffsetFacts(graph, node) {
|
|
|
34019
33953
|
function readElementRef(graph, node) {
|
|
34020
33954
|
return readElementRefById(graph, node.solidFile, node.elementId);
|
|
34021
33955
|
}
|
|
33956
|
+
function readHostElementRef(graph, node) {
|
|
33957
|
+
return graph.hostElementRefsByNode.get(node) ?? null;
|
|
33958
|
+
}
|
|
34022
33959
|
function readElementRefById(graph, solidFile, elementId) {
|
|
34023
33960
|
const refs = graph.elementRefsBySolidFileAndId.get(solidFile);
|
|
34024
33961
|
if (!refs) return null;
|
|
@@ -36717,7 +36654,7 @@ function appendMatchingEdgesFromSelectorIds(ctx, selectorIds, node, applies, app
|
|
|
36717
36654
|
};
|
|
36718
36655
|
applies.push(edge);
|
|
36719
36656
|
ctx.perf.matchEdgesCreated++;
|
|
36720
|
-
if (ctx.logger.
|
|
36657
|
+
if (ctx.logger.isLevelEnabled(Level.Trace)) {
|
|
36721
36658
|
ctx.logger.trace(
|
|
36722
36659
|
`[cascade] edge node=${node.key} selector=${selector.id} match=${matchResult} conditional=${edge.conditionalMatch} selector-raw=${selector.raw.slice(0, 80)}`
|
|
36723
36660
|
);
|
|
@@ -37160,7 +37097,7 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
37160
37097
|
if (!child) continue;
|
|
37161
37098
|
if (child.kind === "expression") {
|
|
37162
37099
|
if (isStructuralExpression(child.node)) {
|
|
37163
|
-
if (logger.
|
|
37100
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (structural expression child)`);
|
|
37164
37101
|
memo.set(element.id, 2 /* Unknown */);
|
|
37165
37102
|
return 2 /* Unknown */;
|
|
37166
37103
|
}
|
|
@@ -37182,11 +37119,11 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
37182
37119
|
if (!child.isDomElement) {
|
|
37183
37120
|
const childMeta = compositionMetaByElementId.get(child.id);
|
|
37184
37121
|
if (childMeta !== void 0 && isControlTag(childMeta.tagName)) {
|
|
37185
|
-
if (logger.
|
|
37122
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag}#${child.id} resolves to control tag=${childMeta.tagName}, skipping`);
|
|
37186
37123
|
continue;
|
|
37187
37124
|
}
|
|
37188
37125
|
if (childState !== 1 /* No */) {
|
|
37189
|
-
if (logger.
|
|
37126
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag ?? child.id}#${child.id} has state=${childState} \u2192 childHasUnknown`);
|
|
37190
37127
|
childHasUnknown = true;
|
|
37191
37128
|
}
|
|
37192
37129
|
continue;
|
|
@@ -37199,12 +37136,12 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
37199
37136
|
if (childState === 3 /* DynamicText */) childHasDynamicText = true;
|
|
37200
37137
|
}
|
|
37201
37138
|
if (childHasUnknown) {
|
|
37202
|
-
if (logger.
|
|
37139
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (child has unknown)`);
|
|
37203
37140
|
memo.set(element.id, 2 /* Unknown */);
|
|
37204
37141
|
return 2 /* Unknown */;
|
|
37205
37142
|
}
|
|
37206
37143
|
if (hasTextOnlyExpression || childHasDynamicText) {
|
|
37207
|
-
if (logger.
|
|
37144
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 dynamic-text`);
|
|
37208
37145
|
memo.set(element.id, 3 /* DynamicText */);
|
|
37209
37146
|
return 3 /* DynamicText */;
|
|
37210
37147
|
}
|
|
@@ -37226,15 +37163,16 @@ function collectLayoutElementRecordsForSolid(solid, selectorRequirements, inline
|
|
|
37226
37163
|
const meta = compositionMetaByElementId.get(element.id);
|
|
37227
37164
|
if (!meta || !meta.participates) continue;
|
|
37228
37165
|
const localClassTokens = selectorRequirements.needsClassTokens ? getStaticClassTokensForElementEntity(solid, element) : EMPTY_STRING_LIST3;
|
|
37229
|
-
const classTokens = mergeClassTokens(localClassTokens, meta.
|
|
37166
|
+
const classTokens = mergeClassTokens(localClassTokens, meta.resolvedHost?.descriptor.staticClassTokens);
|
|
37230
37167
|
const classTokenSet = classTokens.length === 0 ? EMPTY_CLASS_TOKEN_SET : createClassTokenSet(classTokens);
|
|
37231
37168
|
const inlineStyleKeys = getStaticStyleKeysForElement(solid, element.id);
|
|
37232
37169
|
const localAttributes = selectorRequirements.needsAttributes ? collectStaticAttributes(element) : EMPTY_ATTRIBUTES2;
|
|
37233
|
-
const attributes = mergeAttributes(localAttributes, meta.
|
|
37170
|
+
const attributes = mergeAttributes(localAttributes, meta.resolvedHost?.descriptor.staticAttributes);
|
|
37234
37171
|
const selectorDispatchKeys = buildSelectorDispatchKeys(attributes, classTokens);
|
|
37235
37172
|
const inlineStyleValues = inlineStyleValuesByElementId.get(element.id) ?? EMPTY_INLINE_STYLE_VALUES;
|
|
37236
37173
|
const textualContent = getTextualContentState(element, textContentMemo, compositionMetaByElementId, logger);
|
|
37237
37174
|
const parentElementId = resolveComposedParentElementId(element, compositionMetaByElementId);
|
|
37175
|
+
const hostElementRef = meta.resolvedHost?.hostElementRef ?? null;
|
|
37238
37176
|
out.push({
|
|
37239
37177
|
element,
|
|
37240
37178
|
key: toLayoutElementKey(solid.file, element.id),
|
|
@@ -37247,7 +37185,8 @@ function collectLayoutElementRecordsForSolid(solid, selectorRequirements, inline
|
|
|
37247
37185
|
selectorDispatchKeys,
|
|
37248
37186
|
inlineStyleValues,
|
|
37249
37187
|
textualContent,
|
|
37250
|
-
parentElementId
|
|
37188
|
+
parentElementId,
|
|
37189
|
+
hostElementRef
|
|
37251
37190
|
});
|
|
37252
37191
|
}
|
|
37253
37192
|
return out;
|
|
@@ -37257,7 +37196,7 @@ function collectCompositionMetaByElementId(solid, componentHostResolver) {
|
|
|
37257
37196
|
for (let i = 0; i < solid.jsxElements.length; i++) {
|
|
37258
37197
|
const element = solid.jsxElements[i];
|
|
37259
37198
|
if (!element) continue;
|
|
37260
|
-
const
|
|
37199
|
+
const resolvedHost = resolveHostForElement(
|
|
37261
37200
|
componentHostResolver,
|
|
37262
37201
|
solid.file,
|
|
37263
37202
|
element
|
|
@@ -37266,30 +37205,30 @@ function collectCompositionMetaByElementId(solid, componentHostResolver) {
|
|
|
37266
37205
|
componentHostResolver,
|
|
37267
37206
|
solid.file,
|
|
37268
37207
|
element,
|
|
37269
|
-
|
|
37208
|
+
resolvedHost
|
|
37270
37209
|
);
|
|
37271
37210
|
const participates = element.tag !== null && !isTransparentPrimitive;
|
|
37272
|
-
const tag = resolveEffectiveTag(element,
|
|
37211
|
+
const tag = resolveEffectiveTag(element, resolvedHost?.descriptor ?? null);
|
|
37273
37212
|
const tagName = tag ? tag.toLowerCase() : null;
|
|
37274
37213
|
out.set(element.id, {
|
|
37275
37214
|
element,
|
|
37276
37215
|
participates,
|
|
37277
37216
|
tag,
|
|
37278
37217
|
tagName,
|
|
37279
|
-
|
|
37218
|
+
resolvedHost
|
|
37280
37219
|
});
|
|
37281
37220
|
}
|
|
37282
37221
|
return out;
|
|
37283
37222
|
}
|
|
37284
|
-
function
|
|
37223
|
+
function resolveHostForElement(componentHostResolver, solidFile, element) {
|
|
37285
37224
|
if (element.tag === null) return null;
|
|
37286
37225
|
if (element.isDomElement) return null;
|
|
37287
37226
|
return componentHostResolver.resolveHost(solidFile, element.tag);
|
|
37288
37227
|
}
|
|
37289
|
-
function resolveTransparentPrimitiveStatus(componentHostResolver, solidFile, element,
|
|
37228
|
+
function resolveTransparentPrimitiveStatus(componentHostResolver, solidFile, element, resolvedHost) {
|
|
37290
37229
|
if (element.tag === null) return false;
|
|
37291
37230
|
if (element.isDomElement) return false;
|
|
37292
|
-
if (
|
|
37231
|
+
if (resolvedHost !== null) return false;
|
|
37293
37232
|
return componentHostResolver.isTransparentPrimitive(solidFile, element.tag);
|
|
37294
37233
|
}
|
|
37295
37234
|
function resolveEffectiveTag(element, hostDescriptor) {
|
|
@@ -37407,6 +37346,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37407
37346
|
const childrenByParentNodeMutable = /* @__PURE__ */ new Map();
|
|
37408
37347
|
const elementBySolidFileAndIdMutable = /* @__PURE__ */ new Map();
|
|
37409
37348
|
const elementRefsBySolidFileAndIdMutable = /* @__PURE__ */ new Map();
|
|
37349
|
+
const hostElementRefsByNodeMutable = /* @__PURE__ */ new Map();
|
|
37410
37350
|
const appliesByElementNodeMutable = /* @__PURE__ */ new Map();
|
|
37411
37351
|
const selectorsById = /* @__PURE__ */ new Map();
|
|
37412
37352
|
const monitoredDeclarationsBySelectorId = /* @__PURE__ */ new Map();
|
|
@@ -37443,7 +37383,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37443
37383
|
const moduleResolver = createLayoutModuleResolver(solids, css);
|
|
37444
37384
|
const componentHostResolver = createLayoutComponentHostResolver(solids, moduleResolver, logger);
|
|
37445
37385
|
const cssScopeBySolidFile = collectCSSScopeBySolidFile(solids, css, moduleResolver);
|
|
37446
|
-
if (logger.
|
|
37386
|
+
if (logger.isLevelEnabled(Level.Trace)) {
|
|
37447
37387
|
for (const [solidFile, scopePaths] of cssScopeBySolidFile) {
|
|
37448
37388
|
if (scopePaths.length > 0) {
|
|
37449
37389
|
let names = "";
|
|
@@ -37538,6 +37478,9 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37538
37478
|
isControl: isControlTag(record.tagName),
|
|
37539
37479
|
isReplaced: isReplacedTag(record.tagName)
|
|
37540
37480
|
};
|
|
37481
|
+
if (record.hostElementRef !== null) {
|
|
37482
|
+
hostElementRefsByNodeMutable.set(node, record.hostElementRef);
|
|
37483
|
+
}
|
|
37541
37484
|
elements.push(node);
|
|
37542
37485
|
elementById.set(record.element.id, node);
|
|
37543
37486
|
nodeByElementId.set(record.element.id, node);
|
|
@@ -37559,7 +37502,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37559
37502
|
}
|
|
37560
37503
|
}
|
|
37561
37504
|
}
|
|
37562
|
-
if (logger.
|
|
37505
|
+
if (logger.isLevelEnabled(Level.Debug)) {
|
|
37563
37506
|
for (const [file, roots] of rootElementsByFile) {
|
|
37564
37507
|
const descs = roots.map((r) => `${r.key}(tag=${r.tagName}, attrs=[${[...r.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}])`);
|
|
37565
37508
|
logger.debug(`[build] rootElementsByFile file=${file} count=${roots.length}: ${descs.join(", ")}`);
|
|
@@ -37602,7 +37545,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37602
37545
|
appliesByNode.set(node, edges);
|
|
37603
37546
|
}
|
|
37604
37547
|
perf.cascadeBuildMs = performance.now() - cascadeStartedAt;
|
|
37605
|
-
if (logger.
|
|
37548
|
+
if (logger.isLevelEnabled(Level.Trace)) {
|
|
37606
37549
|
for (let i = 0; i < elements.length; i++) {
|
|
37607
37550
|
const node = elements[i];
|
|
37608
37551
|
if (!node) continue;
|
|
@@ -37658,6 +37601,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37658
37601
|
childrenByParentNode: childrenByParentNodeMutable,
|
|
37659
37602
|
elementBySolidFileAndId: elementBySolidFileAndIdMutable,
|
|
37660
37603
|
elementRefsBySolidFileAndId: elementRefsBySolidFileAndIdMutable,
|
|
37604
|
+
hostElementRefsByNode: hostElementRefsByNodeMutable,
|
|
37661
37605
|
appliesByNode,
|
|
37662
37606
|
selectorCandidatesByNode,
|
|
37663
37607
|
selectorsById,
|
|
@@ -38058,7 +38002,7 @@ function computeFlowParticipationFact(snapshot) {
|
|
|
38058
38002
|
}
|
|
38059
38003
|
function buildContextIndex(childrenByParentNode, snapshotByElementNode, perf, logger) {
|
|
38060
38004
|
const out = /* @__PURE__ */ new Map();
|
|
38061
|
-
const trace = logger.
|
|
38005
|
+
const trace = logger.isLevelEnabled(Level.Trace);
|
|
38062
38006
|
for (const [parent, children] of childrenByParentNode) {
|
|
38063
38007
|
if (children.length < 2) continue;
|
|
38064
38008
|
const snapshot = snapshotByElementNode.get(parent);
|
|
@@ -38928,7 +38872,7 @@ function runLayoutDetector(context, detector) {
|
|
|
38928
38872
|
result.evidence.posteriorLower,
|
|
38929
38873
|
result.evidence.posteriorUpper
|
|
38930
38874
|
);
|
|
38931
|
-
if (log.
|
|
38875
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
38932
38876
|
log.debug(
|
|
38933
38877
|
`[${detector.id}] accept case=${i} severity=${result.evidence.severity.toFixed(2)} confidence=${result.evidence.confidence.toFixed(2)} posterior=[${result.evidence.posteriorLower.toFixed(3)},${result.evidence.posteriorUpper.toFixed(3)}] evidenceMass=${result.evidence.evidenceMass.toFixed(3)} context=${result.evidence.contextKind} offset=${result.evidence.estimatedOffsetPx?.toFixed(2) ?? "null"} topFactors=[${result.evidence.topFactors.join(",")}] causes=[${result.evidence.causes.join("; ")}]`
|
|
38934
38878
|
);
|
|
@@ -38937,7 +38881,7 @@ function runLayoutDetector(context, detector) {
|
|
|
38937
38881
|
continue;
|
|
38938
38882
|
}
|
|
38939
38883
|
recordPolicyMetrics(context, result.evidenceMass, result.posteriorLower, result.posteriorUpper);
|
|
38940
|
-
if (log.
|
|
38884
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
38941
38885
|
log.debug(
|
|
38942
38886
|
`[${detector.id}] reject case=${i} reason=${result.reason} detail=${result.detail ?? "none"} posterior=[${result.posteriorLower.toFixed(3)},${result.posteriorUpper.toFixed(3)}] evidenceMass=${result.evidenceMass.toFixed(3)}`
|
|
38943
38887
|
);
|
|
@@ -39121,13 +39065,13 @@ function emitLayoutDiagnostic(layout, node, emit, ruleId, messageId, template, s
|
|
|
39121
39065
|
}
|
|
39122
39066
|
|
|
39123
39067
|
// src/cross-file/rules/undefined-css-class.ts
|
|
39124
|
-
var
|
|
39068
|
+
var messages131 = {
|
|
39125
39069
|
undefinedClass: "CSS class '{{className}}' is not defined in project CSS files"
|
|
39126
39070
|
};
|
|
39127
39071
|
var jsxNoUndefinedCssClass = defineCrossRule({
|
|
39128
39072
|
id: "jsx-no-undefined-css-class",
|
|
39129
39073
|
severity: "error",
|
|
39130
|
-
messages:
|
|
39074
|
+
messages: messages131,
|
|
39131
39075
|
meta: {
|
|
39132
39076
|
description: "Detect undefined CSS class names in JSX",
|
|
39133
39077
|
fixable: false,
|
|
@@ -39146,7 +39090,7 @@ var jsxNoUndefinedCssClass = defineCrossRule({
|
|
|
39146
39090
|
ref.solid.sourceFile,
|
|
39147
39091
|
jsxNoUndefinedCssClass.id,
|
|
39148
39092
|
"undefinedClass",
|
|
39149
|
-
resolveMessage(
|
|
39093
|
+
resolveMessage(messages131.undefinedClass, { className: item.className }),
|
|
39150
39094
|
"error"
|
|
39151
39095
|
));
|
|
39152
39096
|
}
|
|
@@ -39154,13 +39098,13 @@ var jsxNoUndefinedCssClass = defineCrossRule({
|
|
|
39154
39098
|
});
|
|
39155
39099
|
|
|
39156
39100
|
// src/cross-file/rules/unreferenced-css-class.ts
|
|
39157
|
-
var
|
|
39101
|
+
var messages132 = {
|
|
39158
39102
|
unreferencedClass: "CSS class '{{className}}' is defined but not referenced by static JSX class attributes"
|
|
39159
39103
|
};
|
|
39160
39104
|
var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
39161
39105
|
id: "css-no-unreferenced-component-class",
|
|
39162
39106
|
severity: "warn",
|
|
39163
|
-
messages:
|
|
39107
|
+
messages: messages132,
|
|
39164
39108
|
meta: {
|
|
39165
39109
|
description: "Detect CSS classes that are never referenced by static JSX class attributes.",
|
|
39166
39110
|
fixable: false,
|
|
@@ -39184,7 +39128,7 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
|
39184
39128
|
},
|
|
39185
39129
|
cssNoUnreferencedComponentClass.id,
|
|
39186
39130
|
"unreferencedClass",
|
|
39187
|
-
resolveMessage(
|
|
39131
|
+
resolveMessage(messages132.unreferencedClass, { className }),
|
|
39188
39132
|
"warn"
|
|
39189
39133
|
)
|
|
39190
39134
|
);
|
|
@@ -39193,13 +39137,13 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
|
39193
39137
|
});
|
|
39194
39138
|
|
|
39195
39139
|
// src/cross-file/rules/jsx-no-duplicate-class-token-class-classlist.ts
|
|
39196
|
-
var
|
|
39140
|
+
var messages133 = {
|
|
39197
39141
|
duplicateClassToken: "Class token `{{name}}` appears in both class and classList."
|
|
39198
39142
|
};
|
|
39199
39143
|
var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
39200
39144
|
id: "jsx-no-duplicate-class-token-class-classlist",
|
|
39201
39145
|
severity: "warn",
|
|
39202
|
-
messages:
|
|
39146
|
+
messages: messages133,
|
|
39203
39147
|
meta: {
|
|
39204
39148
|
description: "Disallow duplicate class tokens between class and classList on the same JSX element.",
|
|
39205
39149
|
fixable: false,
|
|
@@ -39241,7 +39185,7 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
|
39241
39185
|
solid.sourceFile,
|
|
39242
39186
|
jsxNoDuplicateClassTokenClassClasslist.id,
|
|
39243
39187
|
"duplicateClassToken",
|
|
39244
|
-
resolveMessage(
|
|
39188
|
+
resolveMessage(messages133.duplicateClassToken, { name: token }),
|
|
39245
39189
|
"warn"
|
|
39246
39190
|
));
|
|
39247
39191
|
}
|
|
@@ -39252,13 +39196,13 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
|
39252
39196
|
|
|
39253
39197
|
// src/cross-file/rules/jsx-classlist-static-keys.ts
|
|
39254
39198
|
import ts126 from "typescript";
|
|
39255
|
-
var
|
|
39199
|
+
var messages134 = {
|
|
39256
39200
|
nonStaticKey: "classList key must be statically known for reliable class mapping."
|
|
39257
39201
|
};
|
|
39258
39202
|
var jsxClasslistStaticKeys = defineCrossRule({
|
|
39259
39203
|
id: "jsx-classlist-static-keys",
|
|
39260
39204
|
severity: "error",
|
|
39261
|
-
messages:
|
|
39205
|
+
messages: messages134,
|
|
39262
39206
|
meta: {
|
|
39263
39207
|
description: "Require classList keys to be static and non-computed.",
|
|
39264
39208
|
fixable: false,
|
|
@@ -39269,26 +39213,26 @@ var jsxClasslistStaticKeys = defineCrossRule({
|
|
|
39269
39213
|
forEachClassListPropertyAcross(solids, (solid, p) => {
|
|
39270
39214
|
if (ts126.isSpreadAssignment(p)) return;
|
|
39271
39215
|
if (!ts126.isPropertyAssignment(p)) {
|
|
39272
|
-
emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(
|
|
39216
|
+
emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
|
|
39273
39217
|
return;
|
|
39274
39218
|
}
|
|
39275
39219
|
if (ts126.isComputedPropertyName(p.name)) return;
|
|
39276
39220
|
if (ts126.isIdentifier(p.name)) return;
|
|
39277
39221
|
if (ts126.isStringLiteral(p.name)) return;
|
|
39278
|
-
emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(
|
|
39222
|
+
emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
|
|
39279
39223
|
});
|
|
39280
39224
|
}
|
|
39281
39225
|
});
|
|
39282
39226
|
|
|
39283
39227
|
// src/cross-file/rules/jsx-classlist-no-constant-literals.ts
|
|
39284
39228
|
import ts127 from "typescript";
|
|
39285
|
-
var
|
|
39229
|
+
var messages135 = {
|
|
39286
39230
|
constantEntry: "classList entry `{{name}}: {{value}}` is constant; move it to static class."
|
|
39287
39231
|
};
|
|
39288
39232
|
var jsxClasslistNoConstantLiterals = defineCrossRule({
|
|
39289
39233
|
id: "jsx-classlist-no-constant-literals",
|
|
39290
39234
|
severity: "warn",
|
|
39291
|
-
messages:
|
|
39235
|
+
messages: messages135,
|
|
39292
39236
|
meta: {
|
|
39293
39237
|
description: "Disallow classList entries with constant true/false values.",
|
|
39294
39238
|
fixable: false,
|
|
@@ -39308,7 +39252,7 @@ var jsxClasslistNoConstantLiterals = defineCrossRule({
|
|
|
39308
39252
|
solid.sourceFile,
|
|
39309
39253
|
jsxClasslistNoConstantLiterals.id,
|
|
39310
39254
|
"constantEntry",
|
|
39311
|
-
resolveMessage(
|
|
39255
|
+
resolveMessage(messages135.constantEntry, { name: n, value: val.kind === ts127.SyntaxKind.TrueKeyword ? "true" : "false" }),
|
|
39312
39256
|
"warn"
|
|
39313
39257
|
));
|
|
39314
39258
|
});
|
|
@@ -39343,13 +39287,13 @@ function isDefinitelyNonBooleanType(solid, node) {
|
|
|
39343
39287
|
}
|
|
39344
39288
|
|
|
39345
39289
|
// src/cross-file/rules/jsx-classlist-boolean-values.ts
|
|
39346
|
-
var
|
|
39290
|
+
var messages136 = {
|
|
39347
39291
|
nonBooleanValue: "classList value for `{{name}}` must be boolean."
|
|
39348
39292
|
};
|
|
39349
39293
|
var jsxClasslistBooleanValues = defineCrossRule({
|
|
39350
39294
|
id: "jsx-classlist-boolean-values",
|
|
39351
39295
|
severity: "error",
|
|
39352
|
-
messages:
|
|
39296
|
+
messages: messages136,
|
|
39353
39297
|
meta: {
|
|
39354
39298
|
description: "Require classList values to be boolean-like expressions.",
|
|
39355
39299
|
fixable: false,
|
|
@@ -39363,25 +39307,25 @@ var jsxClasslistBooleanValues = defineCrossRule({
|
|
|
39363
39307
|
if (!n) return;
|
|
39364
39308
|
if (isBooleanish(p.initializer)) return;
|
|
39365
39309
|
if (isDefinitelyNonBoolean(p.initializer)) {
|
|
39366
|
-
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(
|
|
39310
|
+
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
|
|
39367
39311
|
return;
|
|
39368
39312
|
}
|
|
39369
39313
|
if (isBooleanType(solid, p.initializer)) return;
|
|
39370
39314
|
if (!isDefinitelyNonBooleanType(solid, p.initializer)) return;
|
|
39371
|
-
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(
|
|
39315
|
+
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
|
|
39372
39316
|
});
|
|
39373
39317
|
}
|
|
39374
39318
|
});
|
|
39375
39319
|
|
|
39376
39320
|
// src/cross-file/rules/jsx-classlist-no-accessor-reference.ts
|
|
39377
39321
|
import ts129 from "typescript";
|
|
39378
|
-
var
|
|
39322
|
+
var messages137 = {
|
|
39379
39323
|
accessorReference: "Signal accessor `{{name}}` must be called in classList value (use {{name}}())."
|
|
39380
39324
|
};
|
|
39381
39325
|
var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
39382
39326
|
id: "jsx-classlist-no-accessor-reference",
|
|
39383
39327
|
severity: "error",
|
|
39384
|
-
messages:
|
|
39328
|
+
messages: messages137,
|
|
39385
39329
|
meta: {
|
|
39386
39330
|
description: "Disallow passing accessor references directly as classList values.",
|
|
39387
39331
|
fixable: false,
|
|
@@ -39413,7 +39357,7 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
|
39413
39357
|
solid.sourceFile,
|
|
39414
39358
|
jsxClasslistNoAccessorReference.id,
|
|
39415
39359
|
"accessorReference",
|
|
39416
|
-
resolveMessage(
|
|
39360
|
+
resolveMessage(messages137.accessorReference, { name: v.text }),
|
|
39417
39361
|
"error"
|
|
39418
39362
|
));
|
|
39419
39363
|
});
|
|
@@ -39422,13 +39366,13 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
|
39422
39366
|
|
|
39423
39367
|
// src/cross-file/rules/jsx-style-kebab-case-keys.ts
|
|
39424
39368
|
import ts130 from "typescript";
|
|
39425
|
-
var
|
|
39369
|
+
var messages138 = {
|
|
39426
39370
|
kebabStyleKey: "Style key `{{name}}` should be `{{kebab}}` in Solid style objects."
|
|
39427
39371
|
};
|
|
39428
39372
|
var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
39429
39373
|
id: "jsx-style-kebab-case-keys",
|
|
39430
39374
|
severity: "error",
|
|
39431
|
-
messages:
|
|
39375
|
+
messages: messages138,
|
|
39432
39376
|
meta: {
|
|
39433
39377
|
description: "Require kebab-case keys in JSX style object literals.",
|
|
39434
39378
|
fixable: false,
|
|
@@ -39449,7 +39393,7 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
|
39449
39393
|
solid.sourceFile,
|
|
39450
39394
|
jsxStyleKebabCaseKeys.id,
|
|
39451
39395
|
"kebabStyleKey",
|
|
39452
|
-
resolveMessage(
|
|
39396
|
+
resolveMessage(messages138.kebabStyleKey, { name: n, kebab }),
|
|
39453
39397
|
"error"
|
|
39454
39398
|
));
|
|
39455
39399
|
});
|
|
@@ -39458,13 +39402,13 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
|
39458
39402
|
|
|
39459
39403
|
// src/cross-file/rules/jsx-style-no-function-values.ts
|
|
39460
39404
|
import ts131 from "typescript";
|
|
39461
|
-
var
|
|
39405
|
+
var messages139 = {
|
|
39462
39406
|
functionStyleValue: "Style value for `{{name}}` is a function; pass computed value instead."
|
|
39463
39407
|
};
|
|
39464
39408
|
var jsxStyleNoFunctionValues = defineCrossRule({
|
|
39465
39409
|
id: "jsx-style-no-function-values",
|
|
39466
39410
|
severity: "error",
|
|
39467
|
-
messages:
|
|
39411
|
+
messages: messages139,
|
|
39468
39412
|
meta: {
|
|
39469
39413
|
description: "Disallow function values in JSX style objects.",
|
|
39470
39414
|
fixable: false,
|
|
@@ -39478,11 +39422,11 @@ var jsxStyleNoFunctionValues = defineCrossRule({
|
|
|
39478
39422
|
if (!n) return;
|
|
39479
39423
|
const v = p.initializer;
|
|
39480
39424
|
if (ts131.isArrowFunction(v) || ts131.isFunctionExpression(v)) {
|
|
39481
|
-
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(
|
|
39425
|
+
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
|
|
39482
39426
|
return;
|
|
39483
39427
|
}
|
|
39484
39428
|
if (ts131.isIdentifier(v) && solid.typeResolver.isCallableType(v)) {
|
|
39485
|
-
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(
|
|
39429
|
+
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
|
|
39486
39430
|
}
|
|
39487
39431
|
});
|
|
39488
39432
|
}
|
|
@@ -39490,13 +39434,13 @@ var jsxStyleNoFunctionValues = defineCrossRule({
|
|
|
39490
39434
|
|
|
39491
39435
|
// src/cross-file/rules/jsx-style-no-unused-custom-prop.ts
|
|
39492
39436
|
import ts132 from "typescript";
|
|
39493
|
-
var
|
|
39437
|
+
var messages140 = {
|
|
39494
39438
|
unusedInlineVar: "Inline custom property `{{name}}` is never read via var({{name}})."
|
|
39495
39439
|
};
|
|
39496
39440
|
var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
39497
39441
|
id: "jsx-style-no-unused-custom-prop",
|
|
39498
39442
|
severity: "warn",
|
|
39499
|
-
messages:
|
|
39443
|
+
messages: messages140,
|
|
39500
39444
|
meta: {
|
|
39501
39445
|
description: "Detect inline style custom properties that are never consumed by CSS var() references.",
|
|
39502
39446
|
fixable: false,
|
|
@@ -39537,7 +39481,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
|
39537
39481
|
solid.sourceFile,
|
|
39538
39482
|
jsxStyleNoUnusedCustomProp.id,
|
|
39539
39483
|
"unusedInlineVar",
|
|
39540
|
-
resolveMessage(
|
|
39484
|
+
resolveMessage(messages140.unusedInlineVar, { name: n }),
|
|
39541
39485
|
"warn"
|
|
39542
39486
|
));
|
|
39543
39487
|
}
|
|
@@ -39547,7 +39491,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
|
39547
39491
|
|
|
39548
39492
|
// src/cross-file/rules/jsx-style-policy.ts
|
|
39549
39493
|
import ts133 from "typescript";
|
|
39550
|
-
var
|
|
39494
|
+
var messages141 = {
|
|
39551
39495
|
fontTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for policy `{{policy}}`.",
|
|
39552
39496
|
lineHeightTooSmall: "Inline style `line-height: {{value}}` is below the minimum `{{min}}` for policy `{{policy}}`.",
|
|
39553
39497
|
heightTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`.",
|
|
@@ -39558,28 +39502,54 @@ var INLINE_TOUCH_TARGET_KEYS = /* @__PURE__ */ new Set([
|
|
|
39558
39502
|
"height",
|
|
39559
39503
|
"min-height",
|
|
39560
39504
|
"width",
|
|
39561
|
-
"min-width"
|
|
39562
|
-
|
|
39563
|
-
|
|
39564
|
-
|
|
39565
|
-
"
|
|
39566
|
-
"
|
|
39505
|
+
"min-width"
|
|
39506
|
+
]);
|
|
39507
|
+
var INTERACTIVE_HTML_TAGS = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
|
|
39508
|
+
var INTERACTIVE_ARIA_ROLES = /* @__PURE__ */ new Set([
|
|
39509
|
+
"button",
|
|
39510
|
+
"link",
|
|
39511
|
+
"checkbox",
|
|
39512
|
+
"radio",
|
|
39513
|
+
"combobox",
|
|
39514
|
+
"listbox",
|
|
39515
|
+
"menuitem",
|
|
39516
|
+
"menuitemcheckbox",
|
|
39517
|
+
"menuitemradio",
|
|
39518
|
+
"option",
|
|
39519
|
+
"switch",
|
|
39520
|
+
"tab"
|
|
39567
39521
|
]);
|
|
39522
|
+
function isInteractiveElement(solid, element, hostElementRef) {
|
|
39523
|
+
if (element.tagName !== null && INTERACTIVE_HTML_TAGS.has(element.tagName)) return true;
|
|
39524
|
+
const roleAttr = getJSXAttributeEntity(solid, element, "role");
|
|
39525
|
+
if (roleAttr !== null && roleAttr.valueNode !== null) {
|
|
39526
|
+
const role = getStaticStringFromJSXValue(roleAttr.valueNode);
|
|
39527
|
+
if (role !== null && INTERACTIVE_ARIA_ROLES.has(role)) return true;
|
|
39528
|
+
}
|
|
39529
|
+
if (hostElementRef !== null && hostElementRef.element.tagName !== null) {
|
|
39530
|
+
if (INTERACTIVE_HTML_TAGS.has(hostElementRef.element.tagName)) return true;
|
|
39531
|
+
}
|
|
39532
|
+
return false;
|
|
39533
|
+
}
|
|
39534
|
+
function readNodeHostElementRef(layout, solid, element) {
|
|
39535
|
+
const node = layout.elementBySolidFileAndId.get(solid.file)?.get(element.id) ?? null;
|
|
39536
|
+
return node !== null ? readHostElementRef(layout, node) : null;
|
|
39537
|
+
}
|
|
39568
39538
|
var jsxStylePolicy = defineCrossRule({
|
|
39569
39539
|
id: "jsx-style-policy",
|
|
39570
39540
|
severity: "warn",
|
|
39571
|
-
messages:
|
|
39541
|
+
messages: messages141,
|
|
39572
39542
|
meta: {
|
|
39573
39543
|
description: "Enforce accessibility policy thresholds on inline JSX style objects.",
|
|
39574
39544
|
fixable: false,
|
|
39575
39545
|
category: "css-jsx"
|
|
39576
39546
|
},
|
|
39577
39547
|
check(context, emit) {
|
|
39578
|
-
const { solids } = context;
|
|
39548
|
+
const { solids, layout } = context;
|
|
39579
39549
|
const policy = getActivePolicy();
|
|
39580
39550
|
if (policy === null) return;
|
|
39581
39551
|
const name = getActivePolicyName() ?? "";
|
|
39582
|
-
forEachStylePropertyAcross(solids, (solid, p) => {
|
|
39552
|
+
forEachStylePropertyAcross(solids, (solid, p, element) => {
|
|
39583
39553
|
if (!ts133.isPropertyAssignment(p)) return;
|
|
39584
39554
|
const key = objectKeyName(p.name);
|
|
39585
39555
|
if (!key) return;
|
|
@@ -39595,7 +39565,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39595
39565
|
solid.sourceFile,
|
|
39596
39566
|
jsxStylePolicy.id,
|
|
39597
39567
|
"fontTooSmall",
|
|
39598
|
-
resolveMessage(
|
|
39568
|
+
resolveMessage(messages141.fontTooSmall, {
|
|
39599
39569
|
prop: key,
|
|
39600
39570
|
value: strVal,
|
|
39601
39571
|
resolved: formatRounded(px),
|
|
@@ -39617,7 +39587,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39617
39587
|
solid.sourceFile,
|
|
39618
39588
|
jsxStylePolicy.id,
|
|
39619
39589
|
"lineHeightTooSmall",
|
|
39620
|
-
resolveMessage(
|
|
39590
|
+
resolveMessage(messages141.lineHeightTooSmall, {
|
|
39621
39591
|
value: String(lh),
|
|
39622
39592
|
min: String(policy.minLineHeight),
|
|
39623
39593
|
policy: name
|
|
@@ -39627,6 +39597,8 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39627
39597
|
return;
|
|
39628
39598
|
}
|
|
39629
39599
|
if (INLINE_TOUCH_TARGET_KEYS.has(normalizedKey)) {
|
|
39600
|
+
const hostRef = readNodeHostElementRef(layout, solid, element);
|
|
39601
|
+
if (!isInteractiveElement(solid, element, hostRef)) return;
|
|
39630
39602
|
const strVal = getStaticStringValue(p.initializer);
|
|
39631
39603
|
if (!strVal) return;
|
|
39632
39604
|
const px = parsePxValue(strVal);
|
|
@@ -39639,7 +39611,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39639
39611
|
solid.sourceFile,
|
|
39640
39612
|
jsxStylePolicy.id,
|
|
39641
39613
|
"heightTooSmall",
|
|
39642
|
-
resolveMessage(
|
|
39614
|
+
resolveMessage(messages141.heightTooSmall, {
|
|
39643
39615
|
prop: key,
|
|
39644
39616
|
value: strVal,
|
|
39645
39617
|
resolved: formatRounded(px),
|
|
@@ -39661,7 +39633,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39661
39633
|
solid.sourceFile,
|
|
39662
39634
|
jsxStylePolicy.id,
|
|
39663
39635
|
"letterSpacingTooSmall",
|
|
39664
|
-
resolveMessage(
|
|
39636
|
+
resolveMessage(messages141.letterSpacingTooSmall, {
|
|
39665
39637
|
value: strVal,
|
|
39666
39638
|
resolved: String(em),
|
|
39667
39639
|
min: String(policy.minLetterSpacing),
|
|
@@ -39682,7 +39654,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39682
39654
|
solid.sourceFile,
|
|
39683
39655
|
jsxStylePolicy.id,
|
|
39684
39656
|
"wordSpacingTooSmall",
|
|
39685
|
-
resolveMessage(
|
|
39657
|
+
resolveMessage(messages141.wordSpacingTooSmall, {
|
|
39686
39658
|
value: strVal,
|
|
39687
39659
|
resolved: String(em),
|
|
39688
39660
|
min: String(policy.minWordSpacing),
|
|
@@ -39696,7 +39668,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39696
39668
|
});
|
|
39697
39669
|
|
|
39698
39670
|
// src/cross-file/rules/css-layout-sibling-alignment-outlier.ts
|
|
39699
|
-
var
|
|
39671
|
+
var messages142 = {
|
|
39700
39672
|
misalignedSibling: "Vertically misaligned '{{subject}}' in '{{parent}}'.{{fix}}{{offsetClause}}"
|
|
39701
39673
|
};
|
|
39702
39674
|
var MIN_CONFIDENCE_THRESHOLD = 0.48;
|
|
@@ -39705,7 +39677,7 @@ var siblingAlignmentDetector = {
|
|
|
39705
39677
|
id: "sibling-alignment-outlier",
|
|
39706
39678
|
collect: collectAlignmentCases,
|
|
39707
39679
|
evaluate(input, context) {
|
|
39708
|
-
if (context.logger.
|
|
39680
|
+
if (context.logger.isLevelEnabled(Level.Trace)) {
|
|
39709
39681
|
const ctx = input.context;
|
|
39710
39682
|
context.logger.trace(
|
|
39711
39683
|
`[sibling-alignment] evaluate subject=${input.subject.elementKey} tag=${input.subject.tag} parent=${ctx.parentElementKey} parentTag=${ctx.parentTag} context.kind=${ctx.kind} certainty=${ctx.certainty} display=${ctx.parentDisplay} alignItems=${ctx.parentAlignItems} crossAxisIsBlockAxis=${ctx.crossAxisIsBlockAxis} crossAxisCertainty=${ctx.crossAxisIsBlockAxisCertainty} baseline=${ctx.baselineRelevance}`
|
|
@@ -39744,7 +39716,7 @@ var siblingAlignmentDetector = {
|
|
|
39744
39716
|
var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
39745
39717
|
id: "css-layout-sibling-alignment-outlier",
|
|
39746
39718
|
severity: "warn",
|
|
39747
|
-
messages:
|
|
39719
|
+
messages: messages142,
|
|
39748
39720
|
meta: {
|
|
39749
39721
|
description: "Detect vertical alignment outliers between sibling elements in shared layout containers.",
|
|
39750
39722
|
fixable: false,
|
|
@@ -39754,7 +39726,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39754
39726
|
const log = context.logger;
|
|
39755
39727
|
const detections = runLayoutDetector(context, siblingAlignmentDetector);
|
|
39756
39728
|
const uniqueDetections = dedupeDetectionsBySubject(detections);
|
|
39757
|
-
if (log.
|
|
39729
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39758
39730
|
log.debug(
|
|
39759
39731
|
`[sibling-alignment] raw=${detections.length} deduped=${uniqueDetections.length}`
|
|
39760
39732
|
);
|
|
@@ -39768,7 +39740,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39768
39740
|
const subjectId = detection.caseData.subject.elementId;
|
|
39769
39741
|
const logPrefix = `[sibling-alignment] <${subjectTag}> in <${parentTag}> (${subjectFile}#${subjectId})`;
|
|
39770
39742
|
if (detection.evidence.confidence < MIN_CONFIDENCE_THRESHOLD) {
|
|
39771
|
-
if (log.
|
|
39743
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39772
39744
|
log.debug(
|
|
39773
39745
|
`${logPrefix} SKIP: confidence=${detection.evidence.confidence.toFixed(2)} < threshold=${MIN_CONFIDENCE_THRESHOLD}`
|
|
39774
39746
|
);
|
|
@@ -39777,7 +39749,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39777
39749
|
}
|
|
39778
39750
|
const estimatedOffset = detection.evidence.estimatedOffsetPx;
|
|
39779
39751
|
if (estimatedOffset !== null && Math.abs(estimatedOffset) < MIN_OFFSET_PX_THRESHOLD && !hasNonOffsetPrimaryEvidence(detection.evidence.topFactors)) {
|
|
39780
|
-
if (log.
|
|
39752
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39781
39753
|
log.debug(
|
|
39782
39754
|
`${logPrefix} SKIP: offset=${estimatedOffset.toFixed(2)}px < ${MIN_OFFSET_PX_THRESHOLD}px (no non-offset primary evidence, topFactors=[${detection.evidence.topFactors.join(",")}])`
|
|
39783
39755
|
);
|
|
@@ -39789,7 +39761,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39789
39761
|
detection.caseData.cohort.parentElementKey,
|
|
39790
39762
|
detection.caseData.subject.solidFile
|
|
39791
39763
|
)) {
|
|
39792
|
-
if (log.
|
|
39764
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39793
39765
|
log.debug(`${logPrefix} SKIP: out-of-flow ancestor`);
|
|
39794
39766
|
}
|
|
39795
39767
|
continue;
|
|
@@ -39800,7 +39772,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39800
39772
|
detection.caseData.subject.elementId
|
|
39801
39773
|
);
|
|
39802
39774
|
if (!subjectRef) {
|
|
39803
|
-
if (log.
|
|
39775
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39804
39776
|
log.debug(`${logPrefix} SKIP: no node ref`);
|
|
39805
39777
|
}
|
|
39806
39778
|
continue;
|
|
@@ -39816,7 +39788,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39816
39788
|
const primaryFix = detection.evidence.primaryFix;
|
|
39817
39789
|
const firstChar = primaryFix.length > 0 ? primaryFix[0] : void 0;
|
|
39818
39790
|
const fix = firstChar !== void 0 ? ` ${firstChar.toUpperCase()}${primaryFix.slice(1)}.` : "";
|
|
39819
|
-
if (log.
|
|
39791
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39820
39792
|
log.debug(
|
|
39821
39793
|
`${logPrefix} EMIT: severity=${severity} confidence=${confidence} offset=${offset?.toFixed(2) ?? "null"} posterior=[${detection.evidence.posteriorLower.toFixed(3)},${detection.evidence.posteriorUpper.toFixed(3)}] evidenceMass=${detection.evidence.evidenceMass.toFixed(3)} topFactors=[${detection.evidence.topFactors.join(",")}] causes=[${causes}]`
|
|
39822
39794
|
);
|
|
@@ -39828,7 +39800,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39828
39800
|
subjectRef.solid.sourceFile,
|
|
39829
39801
|
cssLayoutSiblingAlignmentOutlier.id,
|
|
39830
39802
|
"misalignedSibling",
|
|
39831
|
-
resolveMessage(
|
|
39803
|
+
resolveMessage(messages142.misalignedSibling, {
|
|
39832
39804
|
subject,
|
|
39833
39805
|
parent,
|
|
39834
39806
|
fix,
|
|
@@ -39912,13 +39884,13 @@ function hasNonOffsetPrimaryEvidence(topFactors) {
|
|
|
39912
39884
|
}
|
|
39913
39885
|
|
|
39914
39886
|
// src/cross-file/rules/css-layout-transition-layout-property.ts
|
|
39915
|
-
var
|
|
39887
|
+
var messages143 = {
|
|
39916
39888
|
transitionLayoutProperty: "Transition '{{property}}' in '{{declaration}}' animates layout-affecting geometry. Prefer transform/opacity to avoid CLS."
|
|
39917
39889
|
};
|
|
39918
39890
|
var cssLayoutTransitionLayoutProperty = defineCrossRule({
|
|
39919
39891
|
id: "css-layout-transition-layout-property",
|
|
39920
39892
|
severity: "warn",
|
|
39921
|
-
messages:
|
|
39893
|
+
messages: messages143,
|
|
39922
39894
|
meta: {
|
|
39923
39895
|
description: "Disallow transitions that animate layout-affecting geometry properties.",
|
|
39924
39896
|
fixable: false,
|
|
@@ -39942,7 +39914,7 @@ var cssLayoutTransitionLayoutProperty = defineCrossRule({
|
|
|
39942
39914
|
},
|
|
39943
39915
|
cssLayoutTransitionLayoutProperty.id,
|
|
39944
39916
|
"transitionLayoutProperty",
|
|
39945
|
-
resolveMessage(
|
|
39917
|
+
resolveMessage(messages143.transitionLayoutProperty, {
|
|
39946
39918
|
property: target,
|
|
39947
39919
|
declaration: declaration.property
|
|
39948
39920
|
}),
|
|
@@ -39957,13 +39929,13 @@ function findLayoutTransitionTarget(raw) {
|
|
|
39957
39929
|
}
|
|
39958
39930
|
|
|
39959
39931
|
// src/cross-file/rules/css-layout-animation-layout-property.ts
|
|
39960
|
-
var
|
|
39932
|
+
var messages144 = {
|
|
39961
39933
|
animationLayoutProperty: "Animation '{{animation}}' mutates layout-affecting '{{property}}', which can trigger CLS. Prefer transform/opacity or reserve geometry."
|
|
39962
39934
|
};
|
|
39963
39935
|
var cssLayoutAnimationLayoutProperty = defineCrossRule({
|
|
39964
39936
|
id: "css-layout-animation-layout-property",
|
|
39965
39937
|
severity: "warn",
|
|
39966
|
-
messages:
|
|
39938
|
+
messages: messages144,
|
|
39967
39939
|
meta: {
|
|
39968
39940
|
description: "Disallow keyframe animations that mutate layout-affecting properties and can trigger CLS.",
|
|
39969
39941
|
fixable: false,
|
|
@@ -39991,7 +39963,7 @@ var cssLayoutAnimationLayoutProperty = defineCrossRule({
|
|
|
39991
39963
|
},
|
|
39992
39964
|
cssLayoutAnimationLayoutProperty.id,
|
|
39993
39965
|
"animationLayoutProperty",
|
|
39994
|
-
resolveMessage(
|
|
39966
|
+
resolveMessage(messages144.animationLayoutProperty, {
|
|
39995
39967
|
animation: match.name,
|
|
39996
39968
|
property: match.property
|
|
39997
39969
|
}),
|
|
@@ -40061,13 +40033,13 @@ function firstRiskyAnimationName(names, riskyKeyframes) {
|
|
|
40061
40033
|
}
|
|
40062
40034
|
|
|
40063
40035
|
// src/cross-file/rules/css-layout-stateful-box-model-shift.ts
|
|
40064
|
-
var
|
|
40036
|
+
var messages145 = {
|
|
40065
40037
|
statefulBoxModelShift: "State selector '{{selector}}' changes layout-affecting '{{property}}'. Keep geometry stable across states to avoid CLS."
|
|
40066
40038
|
};
|
|
40067
40039
|
var cssLayoutStatefulBoxModelShift = defineCrossRule({
|
|
40068
40040
|
id: "css-layout-stateful-box-model-shift",
|
|
40069
40041
|
severity: "warn",
|
|
40070
|
-
messages:
|
|
40042
|
+
messages: messages145,
|
|
40071
40043
|
meta: {
|
|
40072
40044
|
description: "Disallow stateful selector changes that alter element geometry and trigger layout shifts.",
|
|
40073
40045
|
fixable: false,
|
|
@@ -40108,7 +40080,7 @@ var cssLayoutStatefulBoxModelShift = defineCrossRule({
|
|
|
40108
40080
|
},
|
|
40109
40081
|
cssLayoutStatefulBoxModelShift.id,
|
|
40110
40082
|
"statefulBoxModelShift",
|
|
40111
|
-
resolveMessage(
|
|
40083
|
+
resolveMessage(messages145.statefulBoxModelShift, {
|
|
40112
40084
|
selector: match.raw,
|
|
40113
40085
|
property: declaration.property
|
|
40114
40086
|
}),
|
|
@@ -40202,14 +40174,14 @@ function lookupBaseByProperty(baseValueIndex, selectorKeys) {
|
|
|
40202
40174
|
|
|
40203
40175
|
// src/cross-file/rules/css-layout-unsized-replaced-element.ts
|
|
40204
40176
|
import ts134 from "typescript";
|
|
40205
|
-
var
|
|
40177
|
+
var messages146 = {
|
|
40206
40178
|
unsizedReplacedElement: "Replaced element '{{tag}}' has no stable reserved size (width/height or aspect-ratio with a dimension), which can cause CLS."
|
|
40207
40179
|
};
|
|
40208
40180
|
var REPLACED_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "iframe", "canvas", "svg"]);
|
|
40209
40181
|
var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
40210
40182
|
id: "css-layout-unsized-replaced-element",
|
|
40211
40183
|
severity: "warn",
|
|
40212
|
-
messages:
|
|
40184
|
+
messages: messages146,
|
|
40213
40185
|
meta: {
|
|
40214
40186
|
description: "Require stable reserved geometry for replaced media elements to prevent layout shifts.",
|
|
40215
40187
|
fixable: false,
|
|
@@ -40225,7 +40197,8 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
|
40225
40197
|
const ref = readNodeRef(context.layout, node);
|
|
40226
40198
|
if (!ref) continue;
|
|
40227
40199
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40228
|
-
|
|
40200
|
+
const hostRef = readHostElementRef(context.layout, node);
|
|
40201
|
+
if (hasReservedSize(ref.solid, node.attributes, ref.element, reservedSpace, hostRef)) continue;
|
|
40229
40202
|
emit(
|
|
40230
40203
|
createDiagnostic(
|
|
40231
40204
|
ref.solid.file,
|
|
@@ -40233,22 +40206,24 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
|
40233
40206
|
ref.solid.sourceFile,
|
|
40234
40207
|
cssLayoutUnsizedReplacedElement.id,
|
|
40235
40208
|
"unsizedReplacedElement",
|
|
40236
|
-
resolveMessage(
|
|
40209
|
+
resolveMessage(messages146.unsizedReplacedElement, { tag }),
|
|
40237
40210
|
"warn"
|
|
40238
40211
|
)
|
|
40239
40212
|
);
|
|
40240
40213
|
}
|
|
40241
40214
|
}
|
|
40242
40215
|
});
|
|
40243
|
-
function hasReservedSize(solid, attributes, element, reservedSpaceFact) {
|
|
40216
|
+
function hasReservedSize(solid, attributes, element, reservedSpaceFact, hostElementRef) {
|
|
40244
40217
|
if (reservedSpaceFact.hasReservedSpace) return true;
|
|
40245
40218
|
const attrWidth = parsePositiveLength(attributes.get("width"));
|
|
40246
40219
|
const attrHeight = parsePositiveLength(attributes.get("height"));
|
|
40247
40220
|
const jsxAttrWidth = readPositiveJsxAttribute(solid, element, "width");
|
|
40248
40221
|
const jsxAttrHeight = readPositiveJsxAttribute(solid, element, "height");
|
|
40249
|
-
|
|
40250
|
-
const
|
|
40251
|
-
|
|
40222
|
+
const hostJsxWidth = hostElementRef !== null ? readPositiveJsxAttribute(hostElementRef.solid, hostElementRef.element, "width") : false;
|
|
40223
|
+
const hostJsxHeight = hostElementRef !== null ? readPositiveJsxAttribute(hostElementRef.solid, hostElementRef.element, "height") : false;
|
|
40224
|
+
if (attrWidth && attrHeight || jsxAttrWidth && jsxAttrHeight || hostJsxWidth && hostJsxHeight) return true;
|
|
40225
|
+
const hasAnyWidth = attrWidth || jsxAttrWidth || hostJsxWidth || reservedSpaceFact.hasUsableInlineDimension;
|
|
40226
|
+
const hasAnyHeight = attrHeight || jsxAttrHeight || hostJsxHeight || reservedSpaceFact.hasUsableBlockDimension || reservedSpaceFact.hasContainIntrinsicSize;
|
|
40252
40227
|
if (reservedSpaceFact.hasUsableAspectRatio && (hasAnyWidth || hasAnyHeight)) return true;
|
|
40253
40228
|
if (reservedSpaceFact.hasContainIntrinsicSize && (hasAnyWidth || hasAnyHeight)) return true;
|
|
40254
40229
|
return false;
|
|
@@ -40284,7 +40259,7 @@ function readPositiveJsxAttribute(solid, element, name) {
|
|
|
40284
40259
|
}
|
|
40285
40260
|
|
|
40286
40261
|
// src/cross-file/rules/css-layout-dynamic-slot-no-reserved-space.ts
|
|
40287
|
-
var
|
|
40262
|
+
var messages147 = {
|
|
40288
40263
|
dynamicSlotNoReservedSpace: "Dynamic content container '{{tag}}' does not reserve block space (min-height/height/aspect-ratio/contain-intrinsic-size), which can cause CLS."
|
|
40289
40264
|
};
|
|
40290
40265
|
var INLINE_DISPLAYS = /* @__PURE__ */ new Set(["inline", "contents"]);
|
|
@@ -40306,7 +40281,7 @@ function hasOutOfFlowAncestor(layout, node) {
|
|
|
40306
40281
|
var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
|
|
40307
40282
|
id: "css-layout-dynamic-slot-no-reserved-space",
|
|
40308
40283
|
severity: "warn",
|
|
40309
|
-
messages:
|
|
40284
|
+
messages: messages147,
|
|
40310
40285
|
meta: {
|
|
40311
40286
|
description: "Require reserved block space for dynamic content containers to avoid layout shifts.",
|
|
40312
40287
|
fixable: false,
|
|
@@ -40329,19 +40304,19 @@ var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
|
|
|
40329
40304
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40330
40305
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40331
40306
|
if (hasBlockAxisPadding(snapshot)) continue;
|
|
40332
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace",
|
|
40307
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages147.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
|
|
40333
40308
|
}
|
|
40334
40309
|
}
|
|
40335
40310
|
});
|
|
40336
40311
|
|
|
40337
40312
|
// src/cross-file/rules/css-layout-scrollbar-gutter-instability.ts
|
|
40338
|
-
var
|
|
40313
|
+
var messages148 = {
|
|
40339
40314
|
missingScrollbarGutter: "Scrollable container '{{tag}}' uses overflow auto/scroll without `scrollbar-gutter: stable`, which can trigger CLS when scrollbars appear."
|
|
40340
40315
|
};
|
|
40341
40316
|
var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
40342
40317
|
id: "css-layout-scrollbar-gutter-instability",
|
|
40343
40318
|
severity: "warn",
|
|
40344
|
-
messages:
|
|
40319
|
+
messages: messages148,
|
|
40345
40320
|
meta: {
|
|
40346
40321
|
description: "Require stable scrollbar gutters for scrollable containers to reduce layout shifts.",
|
|
40347
40322
|
fixable: false,
|
|
@@ -40360,19 +40335,19 @@ var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
|
40360
40335
|
if (scrollbarWidth === "none") continue;
|
|
40361
40336
|
const gutter = readKnownNormalized(snapshot, "scrollbar-gutter");
|
|
40362
40337
|
if (gutter !== null && gutter.startsWith("stable")) continue;
|
|
40363
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter",
|
|
40338
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages148.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
|
|
40364
40339
|
}
|
|
40365
40340
|
}
|
|
40366
40341
|
});
|
|
40367
40342
|
|
|
40368
40343
|
// src/cross-file/rules/css-layout-overflow-anchor-instability.ts
|
|
40369
|
-
var
|
|
40344
|
+
var messages149 = {
|
|
40370
40345
|
unstableOverflowAnchor: "Element '{{tag}}' sets `overflow-anchor: none` on a {{context}} container; disabling scroll anchoring can amplify visible layout shifts."
|
|
40371
40346
|
};
|
|
40372
40347
|
var cssLayoutOverflowAnchorInstability = defineCrossRule({
|
|
40373
40348
|
id: "css-layout-overflow-anchor-instability",
|
|
40374
40349
|
severity: "warn",
|
|
40375
|
-
messages:
|
|
40350
|
+
messages: messages149,
|
|
40376
40351
|
meta: {
|
|
40377
40352
|
description: "Disallow overflow-anchor none on dynamic or scrollable containers prone to visible layout shifts.",
|
|
40378
40353
|
fixable: false,
|
|
@@ -40390,20 +40365,20 @@ var cssLayoutOverflowAnchorInstability = defineCrossRule({
|
|
|
40390
40365
|
const isDynamicContainer = isDynamicContainerLike(node);
|
|
40391
40366
|
if (!isScrollable && !isDynamicContainer) continue;
|
|
40392
40367
|
const containerContext = isScrollable ? "scrollable" : "dynamic";
|
|
40393
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor",
|
|
40368
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor", messages149.unstableOverflowAnchor, cssLayoutOverflowAnchorInstability.severity, { context: containerContext })) continue;
|
|
40394
40369
|
}
|
|
40395
40370
|
}
|
|
40396
40371
|
});
|
|
40397
40372
|
|
|
40398
40373
|
// src/cross-file/rules/css-layout-font-swap-instability.ts
|
|
40399
|
-
var
|
|
40374
|
+
var messages150 = {
|
|
40400
40375
|
unstableFontSwap: "`@font-face` for '{{family}}' uses `font-display: {{display}}` without metric overrides (for example `size-adjust`), which can cause CLS when the webfont swaps in."
|
|
40401
40376
|
};
|
|
40402
40377
|
var SWAP_DISPLAYS = /* @__PURE__ */ new Set(["swap", "fallback"]);
|
|
40403
40378
|
var cssLayoutFontSwapInstability = defineCrossRule({
|
|
40404
40379
|
id: "css-layout-font-swap-instability",
|
|
40405
40380
|
severity: "warn",
|
|
40406
|
-
messages:
|
|
40381
|
+
messages: messages150,
|
|
40407
40382
|
meta: {
|
|
40408
40383
|
description: "Require metric overrides for swapping webfonts to reduce layout shifts during font load.",
|
|
40409
40384
|
fixable: false,
|
|
@@ -40450,7 +40425,7 @@ var cssLayoutFontSwapInstability = defineCrossRule({
|
|
|
40450
40425
|
},
|
|
40451
40426
|
cssLayoutFontSwapInstability.id,
|
|
40452
40427
|
"unstableFontSwap",
|
|
40453
|
-
resolveMessage(
|
|
40428
|
+
resolveMessage(messages150.unstableFontSwap, {
|
|
40454
40429
|
family,
|
|
40455
40430
|
display: report.display
|
|
40456
40431
|
}),
|
|
@@ -40463,14 +40438,14 @@ var cssLayoutFontSwapInstability = defineCrossRule({
|
|
|
40463
40438
|
});
|
|
40464
40439
|
|
|
40465
40440
|
// src/cross-file/rules/css-layout-conditional-display-collapse.ts
|
|
40466
|
-
var
|
|
40441
|
+
var messages151 = {
|
|
40467
40442
|
conditionalDisplayCollapse: "Conditional display sets '{{display}}' on '{{tag}}' without stable reserved space, which can collapse/expand layout and cause CLS."
|
|
40468
40443
|
};
|
|
40469
40444
|
var COLLAPSING_DISPLAYS = /* @__PURE__ */ new Set(["none", "contents"]);
|
|
40470
40445
|
var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
40471
40446
|
id: "css-layout-conditional-display-collapse",
|
|
40472
40447
|
severity: "warn",
|
|
40473
|
-
messages:
|
|
40448
|
+
messages: messages151,
|
|
40474
40449
|
meta: {
|
|
40475
40450
|
description: "Disallow conditional display collapse in flow without reserved geometry.",
|
|
40476
40451
|
fixable: false,
|
|
@@ -40491,13 +40466,13 @@ var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
|
40491
40466
|
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
40492
40467
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40493
40468
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40494
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse",
|
|
40469
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages151.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
|
|
40495
40470
|
}
|
|
40496
40471
|
}
|
|
40497
40472
|
});
|
|
40498
40473
|
|
|
40499
40474
|
// src/cross-file/rules/css-layout-conditional-white-space-wrap-shift.ts
|
|
40500
|
-
var
|
|
40475
|
+
var messages152 = {
|
|
40501
40476
|
conditionalWhiteSpaceShift: "Conditional white-space '{{whiteSpace}}' on '{{tag}}' can reflow text and shift siblings; keep wrapping behavior stable or reserve geometry."
|
|
40502
40477
|
};
|
|
40503
40478
|
var WRAP_SHIFT_VALUES = /* @__PURE__ */ new Set(["nowrap", "pre"]);
|
|
@@ -40506,7 +40481,7 @@ var BLOCK_SIZE_PROPERTIES = ["height", "min-height"];
|
|
|
40506
40481
|
var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
40507
40482
|
id: "css-layout-conditional-white-space-wrap-shift",
|
|
40508
40483
|
severity: "warn",
|
|
40509
|
-
messages:
|
|
40484
|
+
messages: messages152,
|
|
40510
40485
|
meta: {
|
|
40511
40486
|
description: "Disallow conditional white-space wrapping mode toggles that can trigger CLS.",
|
|
40512
40487
|
fixable: false,
|
|
@@ -40529,7 +40504,7 @@ var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
|
40529
40504
|
if (!flow.inFlow) continue;
|
|
40530
40505
|
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
40531
40506
|
if (hasStableTextShell(snapshot)) continue;
|
|
40532
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift",
|
|
40507
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages152.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
|
|
40533
40508
|
}
|
|
40534
40509
|
}
|
|
40535
40510
|
});
|
|
@@ -40551,13 +40526,13 @@ function hasWrapShiftDelta(delta) {
|
|
|
40551
40526
|
}
|
|
40552
40527
|
|
|
40553
40528
|
// src/cross-file/rules/css-layout-overflow-mode-toggle-instability.ts
|
|
40554
|
-
var
|
|
40529
|
+
var messages153 = {
|
|
40555
40530
|
overflowModeToggle: "Conditional overflow mode changes scrolling ('{{overflow}}') on '{{tag}}' without `scrollbar-gutter: stable`, which can trigger CLS."
|
|
40556
40531
|
};
|
|
40557
40532
|
var cssLayoutOverflowModeToggleInstability = defineCrossRule({
|
|
40558
40533
|
id: "css-layout-overflow-mode-toggle-instability",
|
|
40559
40534
|
severity: "warn",
|
|
40560
|
-
messages:
|
|
40535
|
+
messages: messages153,
|
|
40561
40536
|
meta: {
|
|
40562
40537
|
description: "Disallow conditional overflow mode switches that can introduce scrollbar-induced layout shifts.",
|
|
40563
40538
|
fixable: false,
|
|
@@ -40582,7 +40557,7 @@ var cssLayoutOverflowModeToggleInstability = defineCrossRule({
|
|
|
40582
40557
|
const gutter = readKnownNormalizedWithGuard(snapshot, "scrollbar-gutter");
|
|
40583
40558
|
if (gutter !== null && gutter.startsWith("stable")) continue;
|
|
40584
40559
|
const overflowValue = scrollFact.overflowY ?? scrollFact.overflow ?? "auto";
|
|
40585
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle",
|
|
40560
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle", messages153.overflowModeToggle, cssLayoutOverflowModeToggleInstability.severity, { overflow: overflowValue })) continue;
|
|
40586
40561
|
}
|
|
40587
40562
|
}
|
|
40588
40563
|
});
|
|
@@ -40602,7 +40577,7 @@ function hasAnyScrollValue(delta) {
|
|
|
40602
40577
|
}
|
|
40603
40578
|
|
|
40604
40579
|
// src/cross-file/rules/css-layout-box-sizing-toggle-with-chrome.ts
|
|
40605
|
-
var
|
|
40580
|
+
var messages154 = {
|
|
40606
40581
|
boxSizingToggleWithChrome: "Conditional `box-sizing` toggle on '{{tag}}' combines with non-zero padding/border, which can shift layout and trigger CLS."
|
|
40607
40582
|
};
|
|
40608
40583
|
var BOX_SIZING_VALUES = /* @__PURE__ */ new Set(["content-box", "border-box"]);
|
|
@@ -40619,7 +40594,7 @@ var CHROME_PROPERTIES = [
|
|
|
40619
40594
|
var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
|
|
40620
40595
|
id: "css-layout-box-sizing-toggle-with-chrome",
|
|
40621
40596
|
severity: "warn",
|
|
40622
|
-
messages:
|
|
40597
|
+
messages: messages154,
|
|
40623
40598
|
meta: {
|
|
40624
40599
|
description: "Disallow conditional box-sizing mode toggles when box chrome contributes to geometry shifts.",
|
|
40625
40600
|
fixable: false,
|
|
@@ -40637,7 +40612,7 @@ var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
|
|
|
40637
40612
|
if (!boxSizingDelta.hasConditional) continue;
|
|
40638
40613
|
if (!boxSizingDelta.hasDelta) continue;
|
|
40639
40614
|
if (!hasNonZeroChrome(snapshot)) continue;
|
|
40640
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome",
|
|
40615
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages154.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
|
|
40641
40616
|
}
|
|
40642
40617
|
}
|
|
40643
40618
|
});
|
|
@@ -40646,13 +40621,13 @@ function hasNonZeroChrome(snapshot) {
|
|
|
40646
40621
|
}
|
|
40647
40622
|
|
|
40648
40623
|
// src/cross-file/rules/css-layout-content-visibility-no-intrinsic-size.ts
|
|
40649
|
-
var
|
|
40624
|
+
var messages155 = {
|
|
40650
40625
|
missingIntrinsicSize: "`content-visibility: auto` on '{{tag}}' lacks intrinsic size reservation (`contain-intrinsic-size`/min-height/height/aspect-ratio), which can cause CLS."
|
|
40651
40626
|
};
|
|
40652
40627
|
var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
40653
40628
|
id: "css-layout-content-visibility-no-intrinsic-size",
|
|
40654
40629
|
severity: "warn",
|
|
40655
|
-
messages:
|
|
40630
|
+
messages: messages155,
|
|
40656
40631
|
meta: {
|
|
40657
40632
|
description: "Require intrinsic size reservation when using content-visibility auto to avoid late layout shifts.",
|
|
40658
40633
|
fixable: false,
|
|
@@ -40667,19 +40642,19 @@ var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
|
40667
40642
|
if (!isDeferredContainerLike(node, snapshot.node.textualContent)) continue;
|
|
40668
40643
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40669
40644
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40670
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize",
|
|
40645
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages155.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
|
|
40671
40646
|
}
|
|
40672
40647
|
}
|
|
40673
40648
|
});
|
|
40674
40649
|
|
|
40675
40650
|
// src/cross-file/rules/css-layout-conditional-offset-shift.ts
|
|
40676
|
-
var
|
|
40651
|
+
var messages156 = {
|
|
40677
40652
|
conditionalOffsetShift: "Conditional style applies non-zero '{{property}}' offset ({{value}}), which can cause layout shifts when conditions toggle."
|
|
40678
40653
|
};
|
|
40679
40654
|
var cssLayoutConditionalOffsetShift = defineCrossRule({
|
|
40680
40655
|
id: "css-layout-conditional-offset-shift",
|
|
40681
40656
|
severity: "warn",
|
|
40682
|
-
messages:
|
|
40657
|
+
messages: messages156,
|
|
40683
40658
|
meta: {
|
|
40684
40659
|
description: "Disallow conditional non-zero block-axis offsets that can trigger layout shifts.",
|
|
40685
40660
|
fixable: false,
|
|
@@ -40705,7 +40680,7 @@ var cssLayoutConditionalOffsetShift = defineCrossRule({
|
|
|
40705
40680
|
ref.solid.sourceFile,
|
|
40706
40681
|
cssLayoutConditionalOffsetShift.id,
|
|
40707
40682
|
"conditionalOffsetShift",
|
|
40708
|
-
resolveMessage(
|
|
40683
|
+
resolveMessage(messages156.conditionalOffsetShift, {
|
|
40709
40684
|
property: match.property,
|
|
40710
40685
|
value: `${formatFixed(match.value)}px`
|
|
40711
40686
|
}),
|
|
@@ -40766,7 +40741,7 @@ function hasStableBaseline(baselineBySignal, property, expectedPx) {
|
|
|
40766
40741
|
|
|
40767
40742
|
// src/cross-file/rules/jsx-layout-unstable-style-toggle.ts
|
|
40768
40743
|
import ts135 from "typescript";
|
|
40769
|
-
var
|
|
40744
|
+
var messages157 = {
|
|
40770
40745
|
unstableLayoutStyleToggle: "Dynamic style value for '{{property}}' can toggle layout geometry at runtime and cause CLS."
|
|
40771
40746
|
};
|
|
40772
40747
|
var PX_NUMBER_PROPERTIES = /* @__PURE__ */ new Set([
|
|
@@ -40789,7 +40764,7 @@ var POSITIONED_OFFSET_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
40789
40764
|
var jsxLayoutUnstableStyleToggle = defineCrossRule({
|
|
40790
40765
|
id: "jsx-layout-unstable-style-toggle",
|
|
40791
40766
|
severity: "warn",
|
|
40792
|
-
messages:
|
|
40767
|
+
messages: messages157,
|
|
40793
40768
|
meta: {
|
|
40794
40769
|
description: "Flag dynamic inline style values on layout-sensitive properties that can trigger CLS.",
|
|
40795
40770
|
fixable: false,
|
|
@@ -40811,7 +40786,7 @@ var jsxLayoutUnstableStyleToggle = defineCrossRule({
|
|
|
40811
40786
|
solid.sourceFile,
|
|
40812
40787
|
jsxLayoutUnstableStyleToggle.id,
|
|
40813
40788
|
"unstableLayoutStyleToggle",
|
|
40814
|
-
resolveMessage(
|
|
40789
|
+
resolveMessage(messages157.unstableLayoutStyleToggle, { property: normalized }),
|
|
40815
40790
|
"warn"
|
|
40816
40791
|
)
|
|
40817
40792
|
);
|
|
@@ -40928,14 +40903,14 @@ function unwrapTypeWrapper(node) {
|
|
|
40928
40903
|
|
|
40929
40904
|
// src/cross-file/rules/jsx-layout-classlist-geometry-toggle.ts
|
|
40930
40905
|
import ts136 from "typescript";
|
|
40931
|
-
var
|
|
40906
|
+
var messages158 = {
|
|
40932
40907
|
classListGeometryToggle: "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS."
|
|
40933
40908
|
};
|
|
40934
40909
|
var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
|
|
40935
40910
|
var jsxLayoutClasslistGeometryToggle = defineCrossRule({
|
|
40936
40911
|
id: "jsx-layout-classlist-geometry-toggle",
|
|
40937
40912
|
severity: "warn",
|
|
40938
|
-
messages:
|
|
40913
|
+
messages: messages158,
|
|
40939
40914
|
meta: {
|
|
40940
40915
|
description: "Flag classList-driven class toggles that map to layout-affecting CSS geometry changes.",
|
|
40941
40916
|
fixable: false,
|
|
@@ -40961,7 +40936,7 @@ var jsxLayoutClasslistGeometryToggle = defineCrossRule({
|
|
|
40961
40936
|
solid.sourceFile,
|
|
40962
40937
|
jsxLayoutClasslistGeometryToggle.id,
|
|
40963
40938
|
"classListGeometryToggle",
|
|
40964
|
-
resolveMessage(
|
|
40939
|
+
resolveMessage(messages158.classListGeometryToggle, {
|
|
40965
40940
|
className,
|
|
40966
40941
|
property
|
|
40967
40942
|
}),
|
|
@@ -41010,14 +40985,14 @@ function isDynamicallyToggleable(node) {
|
|
|
41010
40985
|
}
|
|
41011
40986
|
|
|
41012
40987
|
// src/cross-file/rules/jsx-layout-picture-source-ratio-consistency.ts
|
|
41013
|
-
var
|
|
40988
|
+
var messages159 = {
|
|
41014
40989
|
inconsistentPictureRatio: "`<picture>` source ratio {{sourceRatio}} differs from fallback img ratio {{imgRatio}}, which can cause reserved-space mismatch and CLS."
|
|
41015
40990
|
};
|
|
41016
40991
|
var RATIO_DELTA_THRESHOLD = 0.02;
|
|
41017
40992
|
var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
|
|
41018
40993
|
id: "jsx-layout-picture-source-ratio-consistency",
|
|
41019
40994
|
severity: "warn",
|
|
41020
|
-
messages:
|
|
40995
|
+
messages: messages159,
|
|
41021
40996
|
meta: {
|
|
41022
40997
|
description: "Require consistent intrinsic aspect ratios across <picture> sources and fallback image.",
|
|
41023
40998
|
fixable: false,
|
|
@@ -41040,7 +41015,7 @@ var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
|
|
|
41040
41015
|
solid.sourceFile,
|
|
41041
41016
|
jsxLayoutPictureSourceRatioConsistency.id,
|
|
41042
41017
|
"inconsistentPictureRatio",
|
|
41043
|
-
resolveMessage(
|
|
41018
|
+
resolveMessage(messages159.inconsistentPictureRatio, {
|
|
41044
41019
|
sourceRatio: mismatch.sourceRatio,
|
|
41045
41020
|
imgRatio: mismatch.imgRatio
|
|
41046
41021
|
}),
|
|
@@ -41110,13 +41085,13 @@ function formatRatio(value2) {
|
|
|
41110
41085
|
}
|
|
41111
41086
|
|
|
41112
41087
|
// src/cross-file/rules/jsx-layout-fill-image-parent-must-be-sized.ts
|
|
41113
|
-
var
|
|
41088
|
+
var messages160 = {
|
|
41114
41089
|
unsizedFillParent: "Fill-image component '{{component}}' is inside a parent without stable size/position; add parent sizing (height/min-height/aspect-ratio) and non-static position to avoid CLS."
|
|
41115
41090
|
};
|
|
41116
41091
|
var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
41117
41092
|
id: "jsx-layout-fill-image-parent-must-be-sized",
|
|
41118
41093
|
severity: "warn",
|
|
41119
|
-
messages:
|
|
41094
|
+
messages: messages160,
|
|
41120
41095
|
meta: {
|
|
41121
41096
|
description: "Require stable parent size and positioning for fill-image component usage.",
|
|
41122
41097
|
fixable: false,
|
|
@@ -41146,7 +41121,7 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
|
41146
41121
|
solid.sourceFile,
|
|
41147
41122
|
jsxLayoutFillImageParentMustBeSized.id,
|
|
41148
41123
|
"unsizedFillParent",
|
|
41149
|
-
resolveMessage(
|
|
41124
|
+
resolveMessage(messages160.unsizedFillParent, {
|
|
41150
41125
|
component: element.tag ?? "Image"
|
|
41151
41126
|
}),
|
|
41152
41127
|
"warn"
|
|
@@ -41157,6 +41132,210 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
|
41157
41132
|
}
|
|
41158
41133
|
});
|
|
41159
41134
|
|
|
41135
|
+
// src/cross-file/rules/jsx-layout-policy-touch-target.ts
|
|
41136
|
+
var messages161 = {
|
|
41137
|
+
heightTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
41138
|
+
widthTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
41139
|
+
paddingTooSmall: "Horizontal padding `{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
41140
|
+
noReservedBlockSize: "Interactive element `<{{tag}}>` has no declared height (minimum `{{min}}px` required by policy `{{policy}}`). The element is content-sized and may not meet the touch-target threshold.",
|
|
41141
|
+
noReservedInlineSize: "Interactive element `<{{tag}}>` has no declared width (minimum `{{min}}px` required by policy `{{policy}}`). The element is content-sized and may not meet the touch-target threshold."
|
|
41142
|
+
};
|
|
41143
|
+
var INTERACTIVE_HTML_TAGS2 = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
|
|
41144
|
+
var INTERACTIVE_ARIA_ROLES2 = /* @__PURE__ */ new Set([
|
|
41145
|
+
"button",
|
|
41146
|
+
"link",
|
|
41147
|
+
"checkbox",
|
|
41148
|
+
"radio",
|
|
41149
|
+
"combobox",
|
|
41150
|
+
"listbox",
|
|
41151
|
+
"menuitem",
|
|
41152
|
+
"menuitemcheckbox",
|
|
41153
|
+
"menuitemradio",
|
|
41154
|
+
"option",
|
|
41155
|
+
"switch",
|
|
41156
|
+
"tab"
|
|
41157
|
+
]);
|
|
41158
|
+
function classifyInteractive(node, solid, element, layout) {
|
|
41159
|
+
const tag = node.tagName;
|
|
41160
|
+
if (tag !== null && INTERACTIVE_HTML_TAGS2.has(tag)) {
|
|
41161
|
+
if (tag === "input" || tag === "select" || tag === "textarea") return "input";
|
|
41162
|
+
return "button";
|
|
41163
|
+
}
|
|
41164
|
+
const roleAttr = getJSXAttributeEntity(solid, element, "role");
|
|
41165
|
+
if (roleAttr !== null && roleAttr.valueNode !== null) {
|
|
41166
|
+
const role = getStaticStringFromJSXValue(roleAttr.valueNode);
|
|
41167
|
+
if (role !== null && INTERACTIVE_ARIA_ROLES2.has(role)) return "button";
|
|
41168
|
+
}
|
|
41169
|
+
const hostRef = layout.hostElementRefsByNode.get(node) ?? null;
|
|
41170
|
+
if (hostRef !== null && hostRef.element.tagName !== null) {
|
|
41171
|
+
const hostTag = hostRef.element.tagName;
|
|
41172
|
+
if (INTERACTIVE_HTML_TAGS2.has(hostTag)) {
|
|
41173
|
+
if (hostTag === "input" || hostTag === "select" || hostTag === "textarea") return "input";
|
|
41174
|
+
return "button";
|
|
41175
|
+
}
|
|
41176
|
+
}
|
|
41177
|
+
return null;
|
|
41178
|
+
}
|
|
41179
|
+
function isVisuallyHidden(snapshot) {
|
|
41180
|
+
const position = readKnownNormalized(snapshot, "position");
|
|
41181
|
+
if (position !== "absolute" && position !== "fixed") return false;
|
|
41182
|
+
const node = snapshot.node;
|
|
41183
|
+
const opacityAttr = node.inlineStyleValues.get("opacity");
|
|
41184
|
+
if (opacityAttr === "0") return true;
|
|
41185
|
+
if (node.classTokenSet.has("opacity-0")) return true;
|
|
41186
|
+
return false;
|
|
41187
|
+
}
|
|
41188
|
+
var jsxLayoutPolicyTouchTarget = defineCrossRule({
|
|
41189
|
+
id: "jsx-layout-policy-touch-target",
|
|
41190
|
+
severity: "warn",
|
|
41191
|
+
messages: messages161,
|
|
41192
|
+
meta: {
|
|
41193
|
+
description: "Enforce minimum interactive element sizes per accessibility policy via resolved layout signals.",
|
|
41194
|
+
fixable: false,
|
|
41195
|
+
category: "css-a11y"
|
|
41196
|
+
},
|
|
41197
|
+
check(context, emit) {
|
|
41198
|
+
const policy = getActivePolicy();
|
|
41199
|
+
if (policy === null) return;
|
|
41200
|
+
const policyName = getActivePolicyName() ?? "";
|
|
41201
|
+
const { layout } = context;
|
|
41202
|
+
const elements = layout.elements;
|
|
41203
|
+
for (let i = 0; i < elements.length; i++) {
|
|
41204
|
+
const node = elements[i];
|
|
41205
|
+
if (!node) continue;
|
|
41206
|
+
const ref = readElementRef(layout, node);
|
|
41207
|
+
if (!ref) continue;
|
|
41208
|
+
const kind = classifyInteractive(node, ref.solid, ref.element, layout);
|
|
41209
|
+
if (kind === null) continue;
|
|
41210
|
+
const snapshot = collectSignalSnapshot(context, node);
|
|
41211
|
+
if (isVisuallyHidden(snapshot)) continue;
|
|
41212
|
+
const tag = node.tagName ?? node.tag ?? "element";
|
|
41213
|
+
checkDimension(
|
|
41214
|
+
snapshot,
|
|
41215
|
+
"height",
|
|
41216
|
+
kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
|
|
41217
|
+
layout,
|
|
41218
|
+
node,
|
|
41219
|
+
emit,
|
|
41220
|
+
"heightTooSmall",
|
|
41221
|
+
messages161.heightTooSmall,
|
|
41222
|
+
tag,
|
|
41223
|
+
policyName
|
|
41224
|
+
);
|
|
41225
|
+
checkDimension(
|
|
41226
|
+
snapshot,
|
|
41227
|
+
"min-height",
|
|
41228
|
+
kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
|
|
41229
|
+
layout,
|
|
41230
|
+
node,
|
|
41231
|
+
emit,
|
|
41232
|
+
"heightTooSmall",
|
|
41233
|
+
messages161.heightTooSmall,
|
|
41234
|
+
tag,
|
|
41235
|
+
policyName
|
|
41236
|
+
);
|
|
41237
|
+
checkDimension(
|
|
41238
|
+
snapshot,
|
|
41239
|
+
"width",
|
|
41240
|
+
kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
|
|
41241
|
+
layout,
|
|
41242
|
+
node,
|
|
41243
|
+
emit,
|
|
41244
|
+
"widthTooSmall",
|
|
41245
|
+
messages161.widthTooSmall,
|
|
41246
|
+
tag,
|
|
41247
|
+
policyName
|
|
41248
|
+
);
|
|
41249
|
+
checkDimension(
|
|
41250
|
+
snapshot,
|
|
41251
|
+
"min-width",
|
|
41252
|
+
kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
|
|
41253
|
+
layout,
|
|
41254
|
+
node,
|
|
41255
|
+
emit,
|
|
41256
|
+
"widthTooSmall",
|
|
41257
|
+
messages161.widthTooSmall,
|
|
41258
|
+
tag,
|
|
41259
|
+
policyName
|
|
41260
|
+
);
|
|
41261
|
+
if (kind === "button") {
|
|
41262
|
+
checkDimension(
|
|
41263
|
+
snapshot,
|
|
41264
|
+
"padding-left",
|
|
41265
|
+
policy.minButtonHorizontalPadding,
|
|
41266
|
+
layout,
|
|
41267
|
+
node,
|
|
41268
|
+
emit,
|
|
41269
|
+
"paddingTooSmall",
|
|
41270
|
+
messages161.paddingTooSmall,
|
|
41271
|
+
tag,
|
|
41272
|
+
policyName
|
|
41273
|
+
);
|
|
41274
|
+
checkDimension(
|
|
41275
|
+
snapshot,
|
|
41276
|
+
"padding-right",
|
|
41277
|
+
policy.minButtonHorizontalPadding,
|
|
41278
|
+
layout,
|
|
41279
|
+
node,
|
|
41280
|
+
emit,
|
|
41281
|
+
"paddingTooSmall",
|
|
41282
|
+
messages161.paddingTooSmall,
|
|
41283
|
+
tag,
|
|
41284
|
+
policyName
|
|
41285
|
+
);
|
|
41286
|
+
}
|
|
41287
|
+
const reservedSpace = readReservedSpaceFact(layout, node);
|
|
41288
|
+
const minBlock = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
|
|
41289
|
+
const minInline = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
|
|
41290
|
+
if (!reservedSpace.hasUsableBlockDimension) {
|
|
41291
|
+
emitLayoutDiagnostic(
|
|
41292
|
+
layout,
|
|
41293
|
+
node,
|
|
41294
|
+
emit,
|
|
41295
|
+
jsxLayoutPolicyTouchTarget.id,
|
|
41296
|
+
"noReservedBlockSize",
|
|
41297
|
+
messages161.noReservedBlockSize,
|
|
41298
|
+
"warn",
|
|
41299
|
+
{ tag, min: String(minBlock), policy: policyName }
|
|
41300
|
+
);
|
|
41301
|
+
}
|
|
41302
|
+
if (!reservedSpace.hasUsableInlineDimension) {
|
|
41303
|
+
emitLayoutDiagnostic(
|
|
41304
|
+
layout,
|
|
41305
|
+
node,
|
|
41306
|
+
emit,
|
|
41307
|
+
jsxLayoutPolicyTouchTarget.id,
|
|
41308
|
+
"noReservedInlineSize",
|
|
41309
|
+
messages161.noReservedInlineSize,
|
|
41310
|
+
"warn",
|
|
41311
|
+
{ tag, min: String(minInline), policy: policyName }
|
|
41312
|
+
);
|
|
41313
|
+
}
|
|
41314
|
+
}
|
|
41315
|
+
}
|
|
41316
|
+
});
|
|
41317
|
+
function checkDimension(snapshot, signal, min, layout, node, emit, messageId, template, tag, policyName) {
|
|
41318
|
+
const px = readKnownPx(snapshot, signal);
|
|
41319
|
+
if (px === null) return;
|
|
41320
|
+
if (px >= min) return;
|
|
41321
|
+
emitLayoutDiagnostic(
|
|
41322
|
+
layout,
|
|
41323
|
+
node,
|
|
41324
|
+
emit,
|
|
41325
|
+
jsxLayoutPolicyTouchTarget.id,
|
|
41326
|
+
messageId,
|
|
41327
|
+
template,
|
|
41328
|
+
"warn",
|
|
41329
|
+
{
|
|
41330
|
+
signal,
|
|
41331
|
+
value: formatRounded(px),
|
|
41332
|
+
min: String(min),
|
|
41333
|
+
tag,
|
|
41334
|
+
policy: policyName
|
|
41335
|
+
}
|
|
41336
|
+
);
|
|
41337
|
+
}
|
|
41338
|
+
|
|
41160
41339
|
// src/cross-file/rules/index.ts
|
|
41161
41340
|
var rules3 = [
|
|
41162
41341
|
jsxNoUndefinedCssClass,
|
|
@@ -41188,7 +41367,8 @@ var rules3 = [
|
|
|
41188
41367
|
cssLayoutOverflowModeToggleInstability,
|
|
41189
41368
|
cssLayoutBoxSizingToggleWithChrome,
|
|
41190
41369
|
cssLayoutContentVisibilityNoIntrinsicSize,
|
|
41191
|
-
cssLayoutConditionalOffsetShift
|
|
41370
|
+
cssLayoutConditionalOffsetShift,
|
|
41371
|
+
jsxLayoutPolicyTouchTarget
|
|
41192
41372
|
];
|
|
41193
41373
|
|
|
41194
41374
|
// src/cross-file/plugin.ts
|
|
@@ -41264,6 +41444,7 @@ export {
|
|
|
41264
41444
|
classifyFile,
|
|
41265
41445
|
extensionsToGlobs,
|
|
41266
41446
|
canonicalPath,
|
|
41447
|
+
Level,
|
|
41267
41448
|
noopLogger,
|
|
41268
41449
|
SolidGraph,
|
|
41269
41450
|
runPhases,
|
|
@@ -41284,4 +41465,4 @@ export {
|
|
|
41284
41465
|
rules3,
|
|
41285
41466
|
runCrossFileRules
|
|
41286
41467
|
};
|
|
41287
|
-
//# sourceMappingURL=chunk-
|
|
41468
|
+
//# sourceMappingURL=chunk-MJKIL7DJ.js.map
|