@drskillissue/ganko 0.2.71 → 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-SVX3WRFV.js → chunk-MJKIL7DJ.js} +341 -264
- 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 +322 -258
- package/dist/eslint-plugin.cjs.map +1 -1
- package/dist/eslint-plugin.js +1 -1
- package/dist/index.cjs +356 -277
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- 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 -1
- package/dist/chunk-5OEDGKHL.js.map +0 -1
- package/dist/chunk-SVX3WRFV.js.map +0 -1
|
@@ -25260,148 +25260,8 @@ function checkParagraphSpacing(graph, emit, policy, name) {
|
|
|
25260
25260
|
}
|
|
25261
25261
|
}
|
|
25262
25262
|
|
|
25263
|
-
// src/css/rules/a11y/css-policy-touch-target.ts
|
|
25264
|
-
var messages125 = {
|
|
25265
|
-
heightTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
25266
|
-
widthTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
25267
|
-
paddingTooSmall: "Horizontal padding `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`."
|
|
25268
|
-
};
|
|
25269
|
-
function classifyRule(rule) {
|
|
25270
|
-
if (rule.elementKinds.has("button")) return "button";
|
|
25271
|
-
if (rule.elementKinds.has("input")) return "input";
|
|
25272
|
-
return null;
|
|
25273
|
-
}
|
|
25274
|
-
var HEIGHT_PROPERTIES = /* @__PURE__ */ new Set(["height", "min-height"]);
|
|
25275
|
-
var WIDTH_PROPERTIES = /* @__PURE__ */ new Set(["width", "min-width"]);
|
|
25276
|
-
var HPADDING_PROPERTIES = /* @__PURE__ */ new Set(["padding-left", "padding-right", "padding-inline", "padding-inline-start", "padding-inline-end"]);
|
|
25277
|
-
var cssPolicyTouchTarget = defineCSSRule({
|
|
25278
|
-
id: "css-policy-touch-target",
|
|
25279
|
-
severity: "warn",
|
|
25280
|
-
messages: messages125,
|
|
25281
|
-
meta: {
|
|
25282
|
-
description: "Enforce minimum interactive element sizes per accessibility policy.",
|
|
25283
|
-
fixable: false,
|
|
25284
|
-
category: "css-a11y"
|
|
25285
|
-
},
|
|
25286
|
-
options: {},
|
|
25287
|
-
check(graph, emit) {
|
|
25288
|
-
const policy = getActivePolicy();
|
|
25289
|
-
if (policy === null) return;
|
|
25290
|
-
const name = getActivePolicyName() ?? "";
|
|
25291
|
-
const decls = graph.declarationsForProperties(
|
|
25292
|
-
"height",
|
|
25293
|
-
"min-height",
|
|
25294
|
-
"width",
|
|
25295
|
-
"min-width",
|
|
25296
|
-
"padding-left",
|
|
25297
|
-
"padding-right",
|
|
25298
|
-
"padding-inline",
|
|
25299
|
-
"padding-inline-start",
|
|
25300
|
-
"padding-inline-end"
|
|
25301
|
-
);
|
|
25302
|
-
for (let i = 0; i < decls.length; i++) {
|
|
25303
|
-
const d = decls[i];
|
|
25304
|
-
if (!d) continue;
|
|
25305
|
-
if (!d.rule) continue;
|
|
25306
|
-
const prop = d.property.toLowerCase();
|
|
25307
|
-
const kind = classifyRule(d.rule);
|
|
25308
|
-
if (!kind) continue;
|
|
25309
|
-
if (isVisuallyHiddenInput(d.rule)) continue;
|
|
25310
|
-
const px = parsePxValue(d.value);
|
|
25311
|
-
if (px === null) continue;
|
|
25312
|
-
if (HEIGHT_PROPERTIES.has(prop)) {
|
|
25313
|
-
const min = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
|
|
25314
|
-
if (px >= min) continue;
|
|
25315
|
-
emitCSSDiagnostic(
|
|
25316
|
-
emit,
|
|
25317
|
-
d.file.path,
|
|
25318
|
-
d.startLine,
|
|
25319
|
-
d.startColumn,
|
|
25320
|
-
cssPolicyTouchTarget,
|
|
25321
|
-
"heightTooSmall",
|
|
25322
|
-
resolveMessage(messages125.heightTooSmall, {
|
|
25323
|
-
property: d.property,
|
|
25324
|
-
value: d.value.trim(),
|
|
25325
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
25326
|
-
min: String(min),
|
|
25327
|
-
element: kind,
|
|
25328
|
-
policy: name
|
|
25329
|
-
})
|
|
25330
|
-
);
|
|
25331
|
-
continue;
|
|
25332
|
-
}
|
|
25333
|
-
if (WIDTH_PROPERTIES.has(prop)) {
|
|
25334
|
-
const min = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
|
|
25335
|
-
if (px >= min) continue;
|
|
25336
|
-
emitCSSDiagnostic(
|
|
25337
|
-
emit,
|
|
25338
|
-
d.file.path,
|
|
25339
|
-
d.startLine,
|
|
25340
|
-
d.startColumn,
|
|
25341
|
-
cssPolicyTouchTarget,
|
|
25342
|
-
"widthTooSmall",
|
|
25343
|
-
resolveMessage(messages125.widthTooSmall, {
|
|
25344
|
-
property: d.property,
|
|
25345
|
-
value: d.value.trim(),
|
|
25346
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
25347
|
-
min: String(min),
|
|
25348
|
-
element: kind,
|
|
25349
|
-
policy: name
|
|
25350
|
-
})
|
|
25351
|
-
);
|
|
25352
|
-
continue;
|
|
25353
|
-
}
|
|
25354
|
-
if (kind === "button" && HPADDING_PROPERTIES.has(prop)) {
|
|
25355
|
-
if (px >= policy.minButtonHorizontalPadding) continue;
|
|
25356
|
-
emitCSSDiagnostic(
|
|
25357
|
-
emit,
|
|
25358
|
-
d.file.path,
|
|
25359
|
-
d.startLine,
|
|
25360
|
-
d.startColumn,
|
|
25361
|
-
cssPolicyTouchTarget,
|
|
25362
|
-
"paddingTooSmall",
|
|
25363
|
-
resolveMessage(messages125.paddingTooSmall, {
|
|
25364
|
-
value: d.value.trim(),
|
|
25365
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
25366
|
-
min: String(policy.minButtonHorizontalPadding),
|
|
25367
|
-
element: kind,
|
|
25368
|
-
policy: name
|
|
25369
|
-
})
|
|
25370
|
-
);
|
|
25371
|
-
}
|
|
25372
|
-
}
|
|
25373
|
-
}
|
|
25374
|
-
});
|
|
25375
|
-
function isVisuallyHiddenInput(rule) {
|
|
25376
|
-
if (!hasPositionAbsoluteOrFixed(rule)) return false;
|
|
25377
|
-
if (!hasOpacityZero(rule)) return false;
|
|
25378
|
-
return true;
|
|
25379
|
-
}
|
|
25380
|
-
function hasPositionAbsoluteOrFixed(rule) {
|
|
25381
|
-
const positionDecls = rule.declarationIndex.get("position");
|
|
25382
|
-
if (!positionDecls || positionDecls.length === 0) return false;
|
|
25383
|
-
for (let i = 0; i < positionDecls.length; i++) {
|
|
25384
|
-
const decl = positionDecls[i];
|
|
25385
|
-
if (!decl) continue;
|
|
25386
|
-
const v = decl.value.trim().toLowerCase();
|
|
25387
|
-
if (v === "absolute" || v === "fixed") return true;
|
|
25388
|
-
}
|
|
25389
|
-
return false;
|
|
25390
|
-
}
|
|
25391
|
-
function hasOpacityZero(rule) {
|
|
25392
|
-
const opacityDecls = rule.declarationIndex.get("opacity");
|
|
25393
|
-
if (!opacityDecls || opacityDecls.length === 0) return false;
|
|
25394
|
-
for (let i = 0; i < opacityDecls.length; i++) {
|
|
25395
|
-
const decl = opacityDecls[i];
|
|
25396
|
-
if (!decl) continue;
|
|
25397
|
-
const v = decl.value.trim();
|
|
25398
|
-
if (v === "0") return true;
|
|
25399
|
-
}
|
|
25400
|
-
return false;
|
|
25401
|
-
}
|
|
25402
|
-
|
|
25403
25263
|
// src/css/rules/a11y/css-policy-typography.ts
|
|
25404
|
-
var
|
|
25264
|
+
var messages125 = {
|
|
25405
25265
|
fontTooSmall: "Font size `{{value}}` ({{resolved}}px) is below the `{{context}}` minimum of `{{min}}px` for policy `{{policy}}`.",
|
|
25406
25266
|
lineHeightTooSmall: "Line height `{{value}}` is below the `{{context}}` minimum of `{{min}}` for policy `{{policy}}`."
|
|
25407
25267
|
};
|
|
@@ -25437,7 +25297,7 @@ function resolveLineHeightContext(d, p) {
|
|
|
25437
25297
|
var cssPolicyTypography = defineCSSRule({
|
|
25438
25298
|
id: "css-policy-typography",
|
|
25439
25299
|
severity: "warn",
|
|
25440
|
-
messages:
|
|
25300
|
+
messages: messages125,
|
|
25441
25301
|
meta: {
|
|
25442
25302
|
description: "Enforce minimum font sizes and line heights per accessibility policy.",
|
|
25443
25303
|
fixable: false,
|
|
@@ -25464,7 +25324,7 @@ var cssPolicyTypography = defineCSSRule({
|
|
|
25464
25324
|
d.startColumn,
|
|
25465
25325
|
cssPolicyTypography,
|
|
25466
25326
|
"fontTooSmall",
|
|
25467
|
-
resolveMessage(
|
|
25327
|
+
resolveMessage(messages125.fontTooSmall, {
|
|
25468
25328
|
value: d.value.trim(),
|
|
25469
25329
|
resolved: String(Math.round(px * 100) / 100),
|
|
25470
25330
|
context,
|
|
@@ -25491,7 +25351,7 @@ var cssPolicyTypography = defineCSSRule({
|
|
|
25491
25351
|
d.startColumn,
|
|
25492
25352
|
cssPolicyTypography,
|
|
25493
25353
|
"lineHeightTooSmall",
|
|
25494
|
-
resolveMessage(
|
|
25354
|
+
resolveMessage(messages125.lineHeightTooSmall, {
|
|
25495
25355
|
value: d.value.trim(),
|
|
25496
25356
|
context,
|
|
25497
25357
|
min: String(min),
|
|
@@ -25509,7 +25369,7 @@ var ZERO_S = /(^|\s|,)0s($|\s|,)/;
|
|
|
25509
25369
|
var TIME_VALUE_G = /([0-9]*\.?[0-9]+)(ms|s)/g;
|
|
25510
25370
|
var AMPERSAND_G = /&/g;
|
|
25511
25371
|
var WHITESPACE_G = /\s+/g;
|
|
25512
|
-
var
|
|
25372
|
+
var messages126 = {
|
|
25513
25373
|
missingReducedMotion: "Animated selector `{{selector}}` lacks prefers-reduced-motion override."
|
|
25514
25374
|
};
|
|
25515
25375
|
function isAnimationDecl(p) {
|
|
@@ -25613,7 +25473,7 @@ function normalizeSelector(s) {
|
|
|
25613
25473
|
var cssRequireReducedMotionOverride = defineCSSRule({
|
|
25614
25474
|
id: "css-require-reduced-motion-override",
|
|
25615
25475
|
severity: "warn",
|
|
25616
|
-
messages:
|
|
25476
|
+
messages: messages126,
|
|
25617
25477
|
meta: {
|
|
25618
25478
|
description: "Require reduced-motion override for animated selectors.",
|
|
25619
25479
|
fixable: false,
|
|
@@ -25676,20 +25536,20 @@ var cssRequireReducedMotionOverride = defineCSSRule({
|
|
|
25676
25536
|
d.startColumn,
|
|
25677
25537
|
cssRequireReducedMotionOverride,
|
|
25678
25538
|
"missingReducedMotion",
|
|
25679
|
-
resolveMessage(
|
|
25539
|
+
resolveMessage(messages126.missingReducedMotion, { selector: r.selectorText })
|
|
25680
25540
|
);
|
|
25681
25541
|
}
|
|
25682
25542
|
}
|
|
25683
25543
|
});
|
|
25684
25544
|
|
|
25685
25545
|
// src/css/rules/structure/css-no-empty-rule.ts
|
|
25686
|
-
var
|
|
25546
|
+
var messages127 = {
|
|
25687
25547
|
emptyRule: "Empty rule `{{selector}}` should be removed."
|
|
25688
25548
|
};
|
|
25689
25549
|
var cssNoEmptyRule = defineCSSRule({
|
|
25690
25550
|
id: "css-no-empty-rule",
|
|
25691
25551
|
severity: "warn",
|
|
25692
|
-
messages:
|
|
25552
|
+
messages: messages127,
|
|
25693
25553
|
meta: {
|
|
25694
25554
|
description: "Disallow empty CSS rules.",
|
|
25695
25555
|
fixable: false,
|
|
@@ -25707,20 +25567,20 @@ var cssNoEmptyRule = defineCSSRule({
|
|
|
25707
25567
|
rule.startColumn,
|
|
25708
25568
|
cssNoEmptyRule,
|
|
25709
25569
|
"emptyRule",
|
|
25710
|
-
resolveMessage(
|
|
25570
|
+
resolveMessage(messages127.emptyRule, { selector: rule.selectorText })
|
|
25711
25571
|
);
|
|
25712
25572
|
}
|
|
25713
25573
|
}
|
|
25714
25574
|
});
|
|
25715
25575
|
|
|
25716
25576
|
// src/css/rules/structure/css-no-unknown-container-name.ts
|
|
25717
|
-
var
|
|
25577
|
+
var messages128 = {
|
|
25718
25578
|
unknownContainer: "Unknown container name `{{name}}` in @container query."
|
|
25719
25579
|
};
|
|
25720
25580
|
var cssNoUnknownContainerName = defineCSSRule({
|
|
25721
25581
|
id: "css-no-unknown-container-name",
|
|
25722
25582
|
severity: "error",
|
|
25723
|
-
messages:
|
|
25583
|
+
messages: messages128,
|
|
25724
25584
|
meta: {
|
|
25725
25585
|
description: "Disallow unknown named containers in @container queries.",
|
|
25726
25586
|
fixable: false,
|
|
@@ -25740,20 +25600,20 @@ var cssNoUnknownContainerName = defineCSSRule({
|
|
|
25740
25600
|
1,
|
|
25741
25601
|
cssNoUnknownContainerName,
|
|
25742
25602
|
"unknownContainer",
|
|
25743
|
-
resolveMessage(
|
|
25603
|
+
resolveMessage(messages128.unknownContainer, { name })
|
|
25744
25604
|
);
|
|
25745
25605
|
}
|
|
25746
25606
|
}
|
|
25747
25607
|
});
|
|
25748
25608
|
|
|
25749
25609
|
// src/css/rules/structure/css-no-unused-container-name.ts
|
|
25750
|
-
var
|
|
25610
|
+
var messages129 = {
|
|
25751
25611
|
unusedContainer: "Container name `{{name}}` is declared but never queried."
|
|
25752
25612
|
};
|
|
25753
25613
|
var cssNoUnusedContainerName = defineCSSRule({
|
|
25754
25614
|
id: "css-no-unused-container-name",
|
|
25755
25615
|
severity: "warn",
|
|
25756
|
-
messages:
|
|
25616
|
+
messages: messages129,
|
|
25757
25617
|
meta: {
|
|
25758
25618
|
description: "Disallow unused named containers.",
|
|
25759
25619
|
fixable: false,
|
|
@@ -25776,7 +25636,7 @@ var cssNoUnusedContainerName = defineCSSRule({
|
|
|
25776
25636
|
d.startColumn,
|
|
25777
25637
|
cssNoUnusedContainerName,
|
|
25778
25638
|
"unusedContainer",
|
|
25779
|
-
resolveMessage(
|
|
25639
|
+
resolveMessage(messages129.unusedContainer, { name })
|
|
25780
25640
|
);
|
|
25781
25641
|
}
|
|
25782
25642
|
}
|
|
@@ -25784,13 +25644,13 @@ var cssNoUnusedContainerName = defineCSSRule({
|
|
|
25784
25644
|
});
|
|
25785
25645
|
|
|
25786
25646
|
// src/css/rules/structure/layer-requirement-for-component-rules.ts
|
|
25787
|
-
var
|
|
25647
|
+
var messages130 = {
|
|
25788
25648
|
missingLayer: "Rule `{{selector}}` is not inside any @layer block while this file uses @layer. Place component rules inside an explicit layer."
|
|
25789
25649
|
};
|
|
25790
25650
|
var layerRequirementForComponentRules = defineCSSRule({
|
|
25791
25651
|
id: "layer-requirement-for-component-rules",
|
|
25792
25652
|
severity: "warn",
|
|
25793
|
-
messages:
|
|
25653
|
+
messages: messages130,
|
|
25794
25654
|
meta: {
|
|
25795
25655
|
description: "Require style rules to be inside @layer when the file defines layers.",
|
|
25796
25656
|
fixable: false,
|
|
@@ -25809,7 +25669,7 @@ var layerRequirementForComponentRules = defineCSSRule({
|
|
|
25809
25669
|
rule.startColumn,
|
|
25810
25670
|
layerRequirementForComponentRules,
|
|
25811
25671
|
"missingLayer",
|
|
25812
|
-
resolveMessage(
|
|
25672
|
+
resolveMessage(messages130.missingLayer, {
|
|
25813
25673
|
selector: rule.selectorText
|
|
25814
25674
|
})
|
|
25815
25675
|
);
|
|
@@ -25849,7 +25709,6 @@ var rules2 = [
|
|
|
25849
25709
|
selectorMaxAttributeAndUniversal,
|
|
25850
25710
|
selectorMaxSpecificity,
|
|
25851
25711
|
cssPolicyTypography,
|
|
25852
|
-
cssPolicyTouchTarget,
|
|
25853
25712
|
cssPolicySpacing,
|
|
25854
25713
|
cssPolicyContrast
|
|
25855
25714
|
];
|
|
@@ -30374,21 +30233,34 @@ function detectTailwindEntry(files) {
|
|
|
30374
30233
|
}
|
|
30375
30234
|
return themeOnlyFallback;
|
|
30376
30235
|
}
|
|
30377
|
-
async function resolveTailwindValidator(files) {
|
|
30236
|
+
async function resolveTailwindValidator(files, logger) {
|
|
30378
30237
|
const entry = detectTailwindEntry(files);
|
|
30379
|
-
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}`);
|
|
30380
30243
|
try {
|
|
30381
30244
|
const base = dirname2(entry.path);
|
|
30382
30245
|
const resolved = resolveTailwindNodePath(base);
|
|
30383
|
-
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}`);
|
|
30384
30251
|
const mod = await import(resolved);
|
|
30385
|
-
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
|
+
}
|
|
30386
30256
|
const design = await mod.__unstable__loadDesignSystem(
|
|
30387
30257
|
entry.content,
|
|
30388
30258
|
{ base }
|
|
30389
30259
|
);
|
|
30260
|
+
logger?.info("tailwind: design system loaded successfully");
|
|
30390
30261
|
return createLiveValidator(design);
|
|
30391
|
-
} catch {
|
|
30262
|
+
} catch (err) {
|
|
30263
|
+
logger?.warning(`tailwind: failed to load design system: ${err instanceof Error ? err.message : String(err)}`);
|
|
30392
30264
|
return null;
|
|
30393
30265
|
}
|
|
30394
30266
|
}
|
|
@@ -39193,13 +39065,13 @@ function emitLayoutDiagnostic(layout, node, emit, ruleId, messageId, template, s
|
|
|
39193
39065
|
}
|
|
39194
39066
|
|
|
39195
39067
|
// src/cross-file/rules/undefined-css-class.ts
|
|
39196
|
-
var
|
|
39068
|
+
var messages131 = {
|
|
39197
39069
|
undefinedClass: "CSS class '{{className}}' is not defined in project CSS files"
|
|
39198
39070
|
};
|
|
39199
39071
|
var jsxNoUndefinedCssClass = defineCrossRule({
|
|
39200
39072
|
id: "jsx-no-undefined-css-class",
|
|
39201
39073
|
severity: "error",
|
|
39202
|
-
messages:
|
|
39074
|
+
messages: messages131,
|
|
39203
39075
|
meta: {
|
|
39204
39076
|
description: "Detect undefined CSS class names in JSX",
|
|
39205
39077
|
fixable: false,
|
|
@@ -39218,7 +39090,7 @@ var jsxNoUndefinedCssClass = defineCrossRule({
|
|
|
39218
39090
|
ref.solid.sourceFile,
|
|
39219
39091
|
jsxNoUndefinedCssClass.id,
|
|
39220
39092
|
"undefinedClass",
|
|
39221
|
-
resolveMessage(
|
|
39093
|
+
resolveMessage(messages131.undefinedClass, { className: item.className }),
|
|
39222
39094
|
"error"
|
|
39223
39095
|
));
|
|
39224
39096
|
}
|
|
@@ -39226,13 +39098,13 @@ var jsxNoUndefinedCssClass = defineCrossRule({
|
|
|
39226
39098
|
});
|
|
39227
39099
|
|
|
39228
39100
|
// src/cross-file/rules/unreferenced-css-class.ts
|
|
39229
|
-
var
|
|
39101
|
+
var messages132 = {
|
|
39230
39102
|
unreferencedClass: "CSS class '{{className}}' is defined but not referenced by static JSX class attributes"
|
|
39231
39103
|
};
|
|
39232
39104
|
var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
39233
39105
|
id: "css-no-unreferenced-component-class",
|
|
39234
39106
|
severity: "warn",
|
|
39235
|
-
messages:
|
|
39107
|
+
messages: messages132,
|
|
39236
39108
|
meta: {
|
|
39237
39109
|
description: "Detect CSS classes that are never referenced by static JSX class attributes.",
|
|
39238
39110
|
fixable: false,
|
|
@@ -39256,7 +39128,7 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
|
39256
39128
|
},
|
|
39257
39129
|
cssNoUnreferencedComponentClass.id,
|
|
39258
39130
|
"unreferencedClass",
|
|
39259
|
-
resolveMessage(
|
|
39131
|
+
resolveMessage(messages132.unreferencedClass, { className }),
|
|
39260
39132
|
"warn"
|
|
39261
39133
|
)
|
|
39262
39134
|
);
|
|
@@ -39265,13 +39137,13 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
|
39265
39137
|
});
|
|
39266
39138
|
|
|
39267
39139
|
// src/cross-file/rules/jsx-no-duplicate-class-token-class-classlist.ts
|
|
39268
|
-
var
|
|
39140
|
+
var messages133 = {
|
|
39269
39141
|
duplicateClassToken: "Class token `{{name}}` appears in both class and classList."
|
|
39270
39142
|
};
|
|
39271
39143
|
var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
39272
39144
|
id: "jsx-no-duplicate-class-token-class-classlist",
|
|
39273
39145
|
severity: "warn",
|
|
39274
|
-
messages:
|
|
39146
|
+
messages: messages133,
|
|
39275
39147
|
meta: {
|
|
39276
39148
|
description: "Disallow duplicate class tokens between class and classList on the same JSX element.",
|
|
39277
39149
|
fixable: false,
|
|
@@ -39313,7 +39185,7 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
|
39313
39185
|
solid.sourceFile,
|
|
39314
39186
|
jsxNoDuplicateClassTokenClassClasslist.id,
|
|
39315
39187
|
"duplicateClassToken",
|
|
39316
|
-
resolveMessage(
|
|
39188
|
+
resolveMessage(messages133.duplicateClassToken, { name: token }),
|
|
39317
39189
|
"warn"
|
|
39318
39190
|
));
|
|
39319
39191
|
}
|
|
@@ -39324,13 +39196,13 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
|
39324
39196
|
|
|
39325
39197
|
// src/cross-file/rules/jsx-classlist-static-keys.ts
|
|
39326
39198
|
import ts126 from "typescript";
|
|
39327
|
-
var
|
|
39199
|
+
var messages134 = {
|
|
39328
39200
|
nonStaticKey: "classList key must be statically known for reliable class mapping."
|
|
39329
39201
|
};
|
|
39330
39202
|
var jsxClasslistStaticKeys = defineCrossRule({
|
|
39331
39203
|
id: "jsx-classlist-static-keys",
|
|
39332
39204
|
severity: "error",
|
|
39333
|
-
messages:
|
|
39205
|
+
messages: messages134,
|
|
39334
39206
|
meta: {
|
|
39335
39207
|
description: "Require classList keys to be static and non-computed.",
|
|
39336
39208
|
fixable: false,
|
|
@@ -39341,26 +39213,26 @@ var jsxClasslistStaticKeys = defineCrossRule({
|
|
|
39341
39213
|
forEachClassListPropertyAcross(solids, (solid, p) => {
|
|
39342
39214
|
if (ts126.isSpreadAssignment(p)) return;
|
|
39343
39215
|
if (!ts126.isPropertyAssignment(p)) {
|
|
39344
|
-
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"));
|
|
39345
39217
|
return;
|
|
39346
39218
|
}
|
|
39347
39219
|
if (ts126.isComputedPropertyName(p.name)) return;
|
|
39348
39220
|
if (ts126.isIdentifier(p.name)) return;
|
|
39349
39221
|
if (ts126.isStringLiteral(p.name)) return;
|
|
39350
|
-
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"));
|
|
39351
39223
|
});
|
|
39352
39224
|
}
|
|
39353
39225
|
});
|
|
39354
39226
|
|
|
39355
39227
|
// src/cross-file/rules/jsx-classlist-no-constant-literals.ts
|
|
39356
39228
|
import ts127 from "typescript";
|
|
39357
|
-
var
|
|
39229
|
+
var messages135 = {
|
|
39358
39230
|
constantEntry: "classList entry `{{name}}: {{value}}` is constant; move it to static class."
|
|
39359
39231
|
};
|
|
39360
39232
|
var jsxClasslistNoConstantLiterals = defineCrossRule({
|
|
39361
39233
|
id: "jsx-classlist-no-constant-literals",
|
|
39362
39234
|
severity: "warn",
|
|
39363
|
-
messages:
|
|
39235
|
+
messages: messages135,
|
|
39364
39236
|
meta: {
|
|
39365
39237
|
description: "Disallow classList entries with constant true/false values.",
|
|
39366
39238
|
fixable: false,
|
|
@@ -39380,7 +39252,7 @@ var jsxClasslistNoConstantLiterals = defineCrossRule({
|
|
|
39380
39252
|
solid.sourceFile,
|
|
39381
39253
|
jsxClasslistNoConstantLiterals.id,
|
|
39382
39254
|
"constantEntry",
|
|
39383
|
-
resolveMessage(
|
|
39255
|
+
resolveMessage(messages135.constantEntry, { name: n, value: val.kind === ts127.SyntaxKind.TrueKeyword ? "true" : "false" }),
|
|
39384
39256
|
"warn"
|
|
39385
39257
|
));
|
|
39386
39258
|
});
|
|
@@ -39415,13 +39287,13 @@ function isDefinitelyNonBooleanType(solid, node) {
|
|
|
39415
39287
|
}
|
|
39416
39288
|
|
|
39417
39289
|
// src/cross-file/rules/jsx-classlist-boolean-values.ts
|
|
39418
|
-
var
|
|
39290
|
+
var messages136 = {
|
|
39419
39291
|
nonBooleanValue: "classList value for `{{name}}` must be boolean."
|
|
39420
39292
|
};
|
|
39421
39293
|
var jsxClasslistBooleanValues = defineCrossRule({
|
|
39422
39294
|
id: "jsx-classlist-boolean-values",
|
|
39423
39295
|
severity: "error",
|
|
39424
|
-
messages:
|
|
39296
|
+
messages: messages136,
|
|
39425
39297
|
meta: {
|
|
39426
39298
|
description: "Require classList values to be boolean-like expressions.",
|
|
39427
39299
|
fixable: false,
|
|
@@ -39435,25 +39307,25 @@ var jsxClasslistBooleanValues = defineCrossRule({
|
|
|
39435
39307
|
if (!n) return;
|
|
39436
39308
|
if (isBooleanish(p.initializer)) return;
|
|
39437
39309
|
if (isDefinitelyNonBoolean(p.initializer)) {
|
|
39438
|
-
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"));
|
|
39439
39311
|
return;
|
|
39440
39312
|
}
|
|
39441
39313
|
if (isBooleanType(solid, p.initializer)) return;
|
|
39442
39314
|
if (!isDefinitelyNonBooleanType(solid, p.initializer)) return;
|
|
39443
|
-
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"));
|
|
39444
39316
|
});
|
|
39445
39317
|
}
|
|
39446
39318
|
});
|
|
39447
39319
|
|
|
39448
39320
|
// src/cross-file/rules/jsx-classlist-no-accessor-reference.ts
|
|
39449
39321
|
import ts129 from "typescript";
|
|
39450
|
-
var
|
|
39322
|
+
var messages137 = {
|
|
39451
39323
|
accessorReference: "Signal accessor `{{name}}` must be called in classList value (use {{name}}())."
|
|
39452
39324
|
};
|
|
39453
39325
|
var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
39454
39326
|
id: "jsx-classlist-no-accessor-reference",
|
|
39455
39327
|
severity: "error",
|
|
39456
|
-
messages:
|
|
39328
|
+
messages: messages137,
|
|
39457
39329
|
meta: {
|
|
39458
39330
|
description: "Disallow passing accessor references directly as classList values.",
|
|
39459
39331
|
fixable: false,
|
|
@@ -39485,7 +39357,7 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
|
39485
39357
|
solid.sourceFile,
|
|
39486
39358
|
jsxClasslistNoAccessorReference.id,
|
|
39487
39359
|
"accessorReference",
|
|
39488
|
-
resolveMessage(
|
|
39360
|
+
resolveMessage(messages137.accessorReference, { name: v.text }),
|
|
39489
39361
|
"error"
|
|
39490
39362
|
));
|
|
39491
39363
|
});
|
|
@@ -39494,13 +39366,13 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
|
39494
39366
|
|
|
39495
39367
|
// src/cross-file/rules/jsx-style-kebab-case-keys.ts
|
|
39496
39368
|
import ts130 from "typescript";
|
|
39497
|
-
var
|
|
39369
|
+
var messages138 = {
|
|
39498
39370
|
kebabStyleKey: "Style key `{{name}}` should be `{{kebab}}` in Solid style objects."
|
|
39499
39371
|
};
|
|
39500
39372
|
var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
39501
39373
|
id: "jsx-style-kebab-case-keys",
|
|
39502
39374
|
severity: "error",
|
|
39503
|
-
messages:
|
|
39375
|
+
messages: messages138,
|
|
39504
39376
|
meta: {
|
|
39505
39377
|
description: "Require kebab-case keys in JSX style object literals.",
|
|
39506
39378
|
fixable: false,
|
|
@@ -39521,7 +39393,7 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
|
39521
39393
|
solid.sourceFile,
|
|
39522
39394
|
jsxStyleKebabCaseKeys.id,
|
|
39523
39395
|
"kebabStyleKey",
|
|
39524
|
-
resolveMessage(
|
|
39396
|
+
resolveMessage(messages138.kebabStyleKey, { name: n, kebab }),
|
|
39525
39397
|
"error"
|
|
39526
39398
|
));
|
|
39527
39399
|
});
|
|
@@ -39530,13 +39402,13 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
|
39530
39402
|
|
|
39531
39403
|
// src/cross-file/rules/jsx-style-no-function-values.ts
|
|
39532
39404
|
import ts131 from "typescript";
|
|
39533
|
-
var
|
|
39405
|
+
var messages139 = {
|
|
39534
39406
|
functionStyleValue: "Style value for `{{name}}` is a function; pass computed value instead."
|
|
39535
39407
|
};
|
|
39536
39408
|
var jsxStyleNoFunctionValues = defineCrossRule({
|
|
39537
39409
|
id: "jsx-style-no-function-values",
|
|
39538
39410
|
severity: "error",
|
|
39539
|
-
messages:
|
|
39411
|
+
messages: messages139,
|
|
39540
39412
|
meta: {
|
|
39541
39413
|
description: "Disallow function values in JSX style objects.",
|
|
39542
39414
|
fixable: false,
|
|
@@ -39550,11 +39422,11 @@ var jsxStyleNoFunctionValues = defineCrossRule({
|
|
|
39550
39422
|
if (!n) return;
|
|
39551
39423
|
const v = p.initializer;
|
|
39552
39424
|
if (ts131.isArrowFunction(v) || ts131.isFunctionExpression(v)) {
|
|
39553
|
-
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"));
|
|
39554
39426
|
return;
|
|
39555
39427
|
}
|
|
39556
39428
|
if (ts131.isIdentifier(v) && solid.typeResolver.isCallableType(v)) {
|
|
39557
|
-
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"));
|
|
39558
39430
|
}
|
|
39559
39431
|
});
|
|
39560
39432
|
}
|
|
@@ -39562,13 +39434,13 @@ var jsxStyleNoFunctionValues = defineCrossRule({
|
|
|
39562
39434
|
|
|
39563
39435
|
// src/cross-file/rules/jsx-style-no-unused-custom-prop.ts
|
|
39564
39436
|
import ts132 from "typescript";
|
|
39565
|
-
var
|
|
39437
|
+
var messages140 = {
|
|
39566
39438
|
unusedInlineVar: "Inline custom property `{{name}}` is never read via var({{name}})."
|
|
39567
39439
|
};
|
|
39568
39440
|
var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
39569
39441
|
id: "jsx-style-no-unused-custom-prop",
|
|
39570
39442
|
severity: "warn",
|
|
39571
|
-
messages:
|
|
39443
|
+
messages: messages140,
|
|
39572
39444
|
meta: {
|
|
39573
39445
|
description: "Detect inline style custom properties that are never consumed by CSS var() references.",
|
|
39574
39446
|
fixable: false,
|
|
@@ -39609,7 +39481,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
|
39609
39481
|
solid.sourceFile,
|
|
39610
39482
|
jsxStyleNoUnusedCustomProp.id,
|
|
39611
39483
|
"unusedInlineVar",
|
|
39612
|
-
resolveMessage(
|
|
39484
|
+
resolveMessage(messages140.unusedInlineVar, { name: n }),
|
|
39613
39485
|
"warn"
|
|
39614
39486
|
));
|
|
39615
39487
|
}
|
|
@@ -39619,7 +39491,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
|
39619
39491
|
|
|
39620
39492
|
// src/cross-file/rules/jsx-style-policy.ts
|
|
39621
39493
|
import ts133 from "typescript";
|
|
39622
|
-
var
|
|
39494
|
+
var messages141 = {
|
|
39623
39495
|
fontTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for policy `{{policy}}`.",
|
|
39624
39496
|
lineHeightTooSmall: "Inline style `line-height: {{value}}` is below the minimum `{{min}}` for policy `{{policy}}`.",
|
|
39625
39497
|
heightTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`.",
|
|
@@ -39666,7 +39538,7 @@ function readNodeHostElementRef(layout, solid, element) {
|
|
|
39666
39538
|
var jsxStylePolicy = defineCrossRule({
|
|
39667
39539
|
id: "jsx-style-policy",
|
|
39668
39540
|
severity: "warn",
|
|
39669
|
-
messages:
|
|
39541
|
+
messages: messages141,
|
|
39670
39542
|
meta: {
|
|
39671
39543
|
description: "Enforce accessibility policy thresholds on inline JSX style objects.",
|
|
39672
39544
|
fixable: false,
|
|
@@ -39693,7 +39565,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39693
39565
|
solid.sourceFile,
|
|
39694
39566
|
jsxStylePolicy.id,
|
|
39695
39567
|
"fontTooSmall",
|
|
39696
|
-
resolveMessage(
|
|
39568
|
+
resolveMessage(messages141.fontTooSmall, {
|
|
39697
39569
|
prop: key,
|
|
39698
39570
|
value: strVal,
|
|
39699
39571
|
resolved: formatRounded(px),
|
|
@@ -39715,7 +39587,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39715
39587
|
solid.sourceFile,
|
|
39716
39588
|
jsxStylePolicy.id,
|
|
39717
39589
|
"lineHeightTooSmall",
|
|
39718
|
-
resolveMessage(
|
|
39590
|
+
resolveMessage(messages141.lineHeightTooSmall, {
|
|
39719
39591
|
value: String(lh),
|
|
39720
39592
|
min: String(policy.minLineHeight),
|
|
39721
39593
|
policy: name
|
|
@@ -39739,7 +39611,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39739
39611
|
solid.sourceFile,
|
|
39740
39612
|
jsxStylePolicy.id,
|
|
39741
39613
|
"heightTooSmall",
|
|
39742
|
-
resolveMessage(
|
|
39614
|
+
resolveMessage(messages141.heightTooSmall, {
|
|
39743
39615
|
prop: key,
|
|
39744
39616
|
value: strVal,
|
|
39745
39617
|
resolved: formatRounded(px),
|
|
@@ -39761,7 +39633,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39761
39633
|
solid.sourceFile,
|
|
39762
39634
|
jsxStylePolicy.id,
|
|
39763
39635
|
"letterSpacingTooSmall",
|
|
39764
|
-
resolveMessage(
|
|
39636
|
+
resolveMessage(messages141.letterSpacingTooSmall, {
|
|
39765
39637
|
value: strVal,
|
|
39766
39638
|
resolved: String(em),
|
|
39767
39639
|
min: String(policy.minLetterSpacing),
|
|
@@ -39782,7 +39654,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39782
39654
|
solid.sourceFile,
|
|
39783
39655
|
jsxStylePolicy.id,
|
|
39784
39656
|
"wordSpacingTooSmall",
|
|
39785
|
-
resolveMessage(
|
|
39657
|
+
resolveMessage(messages141.wordSpacingTooSmall, {
|
|
39786
39658
|
value: strVal,
|
|
39787
39659
|
resolved: String(em),
|
|
39788
39660
|
min: String(policy.minWordSpacing),
|
|
@@ -39796,7 +39668,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39796
39668
|
});
|
|
39797
39669
|
|
|
39798
39670
|
// src/cross-file/rules/css-layout-sibling-alignment-outlier.ts
|
|
39799
|
-
var
|
|
39671
|
+
var messages142 = {
|
|
39800
39672
|
misalignedSibling: "Vertically misaligned '{{subject}}' in '{{parent}}'.{{fix}}{{offsetClause}}"
|
|
39801
39673
|
};
|
|
39802
39674
|
var MIN_CONFIDENCE_THRESHOLD = 0.48;
|
|
@@ -39844,7 +39716,7 @@ var siblingAlignmentDetector = {
|
|
|
39844
39716
|
var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
39845
39717
|
id: "css-layout-sibling-alignment-outlier",
|
|
39846
39718
|
severity: "warn",
|
|
39847
|
-
messages:
|
|
39719
|
+
messages: messages142,
|
|
39848
39720
|
meta: {
|
|
39849
39721
|
description: "Detect vertical alignment outliers between sibling elements in shared layout containers.",
|
|
39850
39722
|
fixable: false,
|
|
@@ -39928,7 +39800,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39928
39800
|
subjectRef.solid.sourceFile,
|
|
39929
39801
|
cssLayoutSiblingAlignmentOutlier.id,
|
|
39930
39802
|
"misalignedSibling",
|
|
39931
|
-
resolveMessage(
|
|
39803
|
+
resolveMessage(messages142.misalignedSibling, {
|
|
39932
39804
|
subject,
|
|
39933
39805
|
parent,
|
|
39934
39806
|
fix,
|
|
@@ -40012,13 +39884,13 @@ function hasNonOffsetPrimaryEvidence(topFactors) {
|
|
|
40012
39884
|
}
|
|
40013
39885
|
|
|
40014
39886
|
// src/cross-file/rules/css-layout-transition-layout-property.ts
|
|
40015
|
-
var
|
|
39887
|
+
var messages143 = {
|
|
40016
39888
|
transitionLayoutProperty: "Transition '{{property}}' in '{{declaration}}' animates layout-affecting geometry. Prefer transform/opacity to avoid CLS."
|
|
40017
39889
|
};
|
|
40018
39890
|
var cssLayoutTransitionLayoutProperty = defineCrossRule({
|
|
40019
39891
|
id: "css-layout-transition-layout-property",
|
|
40020
39892
|
severity: "warn",
|
|
40021
|
-
messages:
|
|
39893
|
+
messages: messages143,
|
|
40022
39894
|
meta: {
|
|
40023
39895
|
description: "Disallow transitions that animate layout-affecting geometry properties.",
|
|
40024
39896
|
fixable: false,
|
|
@@ -40042,7 +39914,7 @@ var cssLayoutTransitionLayoutProperty = defineCrossRule({
|
|
|
40042
39914
|
},
|
|
40043
39915
|
cssLayoutTransitionLayoutProperty.id,
|
|
40044
39916
|
"transitionLayoutProperty",
|
|
40045
|
-
resolveMessage(
|
|
39917
|
+
resolveMessage(messages143.transitionLayoutProperty, {
|
|
40046
39918
|
property: target,
|
|
40047
39919
|
declaration: declaration.property
|
|
40048
39920
|
}),
|
|
@@ -40057,13 +39929,13 @@ function findLayoutTransitionTarget(raw) {
|
|
|
40057
39929
|
}
|
|
40058
39930
|
|
|
40059
39931
|
// src/cross-file/rules/css-layout-animation-layout-property.ts
|
|
40060
|
-
var
|
|
39932
|
+
var messages144 = {
|
|
40061
39933
|
animationLayoutProperty: "Animation '{{animation}}' mutates layout-affecting '{{property}}', which can trigger CLS. Prefer transform/opacity or reserve geometry."
|
|
40062
39934
|
};
|
|
40063
39935
|
var cssLayoutAnimationLayoutProperty = defineCrossRule({
|
|
40064
39936
|
id: "css-layout-animation-layout-property",
|
|
40065
39937
|
severity: "warn",
|
|
40066
|
-
messages:
|
|
39938
|
+
messages: messages144,
|
|
40067
39939
|
meta: {
|
|
40068
39940
|
description: "Disallow keyframe animations that mutate layout-affecting properties and can trigger CLS.",
|
|
40069
39941
|
fixable: false,
|
|
@@ -40091,7 +39963,7 @@ var cssLayoutAnimationLayoutProperty = defineCrossRule({
|
|
|
40091
39963
|
},
|
|
40092
39964
|
cssLayoutAnimationLayoutProperty.id,
|
|
40093
39965
|
"animationLayoutProperty",
|
|
40094
|
-
resolveMessage(
|
|
39966
|
+
resolveMessage(messages144.animationLayoutProperty, {
|
|
40095
39967
|
animation: match.name,
|
|
40096
39968
|
property: match.property
|
|
40097
39969
|
}),
|
|
@@ -40161,13 +40033,13 @@ function firstRiskyAnimationName(names, riskyKeyframes) {
|
|
|
40161
40033
|
}
|
|
40162
40034
|
|
|
40163
40035
|
// src/cross-file/rules/css-layout-stateful-box-model-shift.ts
|
|
40164
|
-
var
|
|
40036
|
+
var messages145 = {
|
|
40165
40037
|
statefulBoxModelShift: "State selector '{{selector}}' changes layout-affecting '{{property}}'. Keep geometry stable across states to avoid CLS."
|
|
40166
40038
|
};
|
|
40167
40039
|
var cssLayoutStatefulBoxModelShift = defineCrossRule({
|
|
40168
40040
|
id: "css-layout-stateful-box-model-shift",
|
|
40169
40041
|
severity: "warn",
|
|
40170
|
-
messages:
|
|
40042
|
+
messages: messages145,
|
|
40171
40043
|
meta: {
|
|
40172
40044
|
description: "Disallow stateful selector changes that alter element geometry and trigger layout shifts.",
|
|
40173
40045
|
fixable: false,
|
|
@@ -40208,7 +40080,7 @@ var cssLayoutStatefulBoxModelShift = defineCrossRule({
|
|
|
40208
40080
|
},
|
|
40209
40081
|
cssLayoutStatefulBoxModelShift.id,
|
|
40210
40082
|
"statefulBoxModelShift",
|
|
40211
|
-
resolveMessage(
|
|
40083
|
+
resolveMessage(messages145.statefulBoxModelShift, {
|
|
40212
40084
|
selector: match.raw,
|
|
40213
40085
|
property: declaration.property
|
|
40214
40086
|
}),
|
|
@@ -40302,14 +40174,14 @@ function lookupBaseByProperty(baseValueIndex, selectorKeys) {
|
|
|
40302
40174
|
|
|
40303
40175
|
// src/cross-file/rules/css-layout-unsized-replaced-element.ts
|
|
40304
40176
|
import ts134 from "typescript";
|
|
40305
|
-
var
|
|
40177
|
+
var messages146 = {
|
|
40306
40178
|
unsizedReplacedElement: "Replaced element '{{tag}}' has no stable reserved size (width/height or aspect-ratio with a dimension), which can cause CLS."
|
|
40307
40179
|
};
|
|
40308
40180
|
var REPLACED_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "iframe", "canvas", "svg"]);
|
|
40309
40181
|
var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
40310
40182
|
id: "css-layout-unsized-replaced-element",
|
|
40311
40183
|
severity: "warn",
|
|
40312
|
-
messages:
|
|
40184
|
+
messages: messages146,
|
|
40313
40185
|
meta: {
|
|
40314
40186
|
description: "Require stable reserved geometry for replaced media elements to prevent layout shifts.",
|
|
40315
40187
|
fixable: false,
|
|
@@ -40334,7 +40206,7 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
|
40334
40206
|
ref.solid.sourceFile,
|
|
40335
40207
|
cssLayoutUnsizedReplacedElement.id,
|
|
40336
40208
|
"unsizedReplacedElement",
|
|
40337
|
-
resolveMessage(
|
|
40209
|
+
resolveMessage(messages146.unsizedReplacedElement, { tag }),
|
|
40338
40210
|
"warn"
|
|
40339
40211
|
)
|
|
40340
40212
|
);
|
|
@@ -40387,7 +40259,7 @@ function readPositiveJsxAttribute(solid, element, name) {
|
|
|
40387
40259
|
}
|
|
40388
40260
|
|
|
40389
40261
|
// src/cross-file/rules/css-layout-dynamic-slot-no-reserved-space.ts
|
|
40390
|
-
var
|
|
40262
|
+
var messages147 = {
|
|
40391
40263
|
dynamicSlotNoReservedSpace: "Dynamic content container '{{tag}}' does not reserve block space (min-height/height/aspect-ratio/contain-intrinsic-size), which can cause CLS."
|
|
40392
40264
|
};
|
|
40393
40265
|
var INLINE_DISPLAYS = /* @__PURE__ */ new Set(["inline", "contents"]);
|
|
@@ -40409,7 +40281,7 @@ function hasOutOfFlowAncestor(layout, node) {
|
|
|
40409
40281
|
var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
|
|
40410
40282
|
id: "css-layout-dynamic-slot-no-reserved-space",
|
|
40411
40283
|
severity: "warn",
|
|
40412
|
-
messages:
|
|
40284
|
+
messages: messages147,
|
|
40413
40285
|
meta: {
|
|
40414
40286
|
description: "Require reserved block space for dynamic content containers to avoid layout shifts.",
|
|
40415
40287
|
fixable: false,
|
|
@@ -40432,19 +40304,19 @@ var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
|
|
|
40432
40304
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40433
40305
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40434
40306
|
if (hasBlockAxisPadding(snapshot)) continue;
|
|
40435
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace",
|
|
40307
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages147.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
|
|
40436
40308
|
}
|
|
40437
40309
|
}
|
|
40438
40310
|
});
|
|
40439
40311
|
|
|
40440
40312
|
// src/cross-file/rules/css-layout-scrollbar-gutter-instability.ts
|
|
40441
|
-
var
|
|
40313
|
+
var messages148 = {
|
|
40442
40314
|
missingScrollbarGutter: "Scrollable container '{{tag}}' uses overflow auto/scroll without `scrollbar-gutter: stable`, which can trigger CLS when scrollbars appear."
|
|
40443
40315
|
};
|
|
40444
40316
|
var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
40445
40317
|
id: "css-layout-scrollbar-gutter-instability",
|
|
40446
40318
|
severity: "warn",
|
|
40447
|
-
messages:
|
|
40319
|
+
messages: messages148,
|
|
40448
40320
|
meta: {
|
|
40449
40321
|
description: "Require stable scrollbar gutters for scrollable containers to reduce layout shifts.",
|
|
40450
40322
|
fixable: false,
|
|
@@ -40463,19 +40335,19 @@ var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
|
40463
40335
|
if (scrollbarWidth === "none") continue;
|
|
40464
40336
|
const gutter = readKnownNormalized(snapshot, "scrollbar-gutter");
|
|
40465
40337
|
if (gutter !== null && gutter.startsWith("stable")) continue;
|
|
40466
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter",
|
|
40338
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages148.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
|
|
40467
40339
|
}
|
|
40468
40340
|
}
|
|
40469
40341
|
});
|
|
40470
40342
|
|
|
40471
40343
|
// src/cross-file/rules/css-layout-overflow-anchor-instability.ts
|
|
40472
|
-
var
|
|
40344
|
+
var messages149 = {
|
|
40473
40345
|
unstableOverflowAnchor: "Element '{{tag}}' sets `overflow-anchor: none` on a {{context}} container; disabling scroll anchoring can amplify visible layout shifts."
|
|
40474
40346
|
};
|
|
40475
40347
|
var cssLayoutOverflowAnchorInstability = defineCrossRule({
|
|
40476
40348
|
id: "css-layout-overflow-anchor-instability",
|
|
40477
40349
|
severity: "warn",
|
|
40478
|
-
messages:
|
|
40350
|
+
messages: messages149,
|
|
40479
40351
|
meta: {
|
|
40480
40352
|
description: "Disallow overflow-anchor none on dynamic or scrollable containers prone to visible layout shifts.",
|
|
40481
40353
|
fixable: false,
|
|
@@ -40493,20 +40365,20 @@ var cssLayoutOverflowAnchorInstability = defineCrossRule({
|
|
|
40493
40365
|
const isDynamicContainer = isDynamicContainerLike(node);
|
|
40494
40366
|
if (!isScrollable && !isDynamicContainer) continue;
|
|
40495
40367
|
const containerContext = isScrollable ? "scrollable" : "dynamic";
|
|
40496
|
-
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;
|
|
40497
40369
|
}
|
|
40498
40370
|
}
|
|
40499
40371
|
});
|
|
40500
40372
|
|
|
40501
40373
|
// src/cross-file/rules/css-layout-font-swap-instability.ts
|
|
40502
|
-
var
|
|
40374
|
+
var messages150 = {
|
|
40503
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."
|
|
40504
40376
|
};
|
|
40505
40377
|
var SWAP_DISPLAYS = /* @__PURE__ */ new Set(["swap", "fallback"]);
|
|
40506
40378
|
var cssLayoutFontSwapInstability = defineCrossRule({
|
|
40507
40379
|
id: "css-layout-font-swap-instability",
|
|
40508
40380
|
severity: "warn",
|
|
40509
|
-
messages:
|
|
40381
|
+
messages: messages150,
|
|
40510
40382
|
meta: {
|
|
40511
40383
|
description: "Require metric overrides for swapping webfonts to reduce layout shifts during font load.",
|
|
40512
40384
|
fixable: false,
|
|
@@ -40553,7 +40425,7 @@ var cssLayoutFontSwapInstability = defineCrossRule({
|
|
|
40553
40425
|
},
|
|
40554
40426
|
cssLayoutFontSwapInstability.id,
|
|
40555
40427
|
"unstableFontSwap",
|
|
40556
|
-
resolveMessage(
|
|
40428
|
+
resolveMessage(messages150.unstableFontSwap, {
|
|
40557
40429
|
family,
|
|
40558
40430
|
display: report.display
|
|
40559
40431
|
}),
|
|
@@ -40566,14 +40438,14 @@ var cssLayoutFontSwapInstability = defineCrossRule({
|
|
|
40566
40438
|
});
|
|
40567
40439
|
|
|
40568
40440
|
// src/cross-file/rules/css-layout-conditional-display-collapse.ts
|
|
40569
|
-
var
|
|
40441
|
+
var messages151 = {
|
|
40570
40442
|
conditionalDisplayCollapse: "Conditional display sets '{{display}}' on '{{tag}}' without stable reserved space, which can collapse/expand layout and cause CLS."
|
|
40571
40443
|
};
|
|
40572
40444
|
var COLLAPSING_DISPLAYS = /* @__PURE__ */ new Set(["none", "contents"]);
|
|
40573
40445
|
var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
40574
40446
|
id: "css-layout-conditional-display-collapse",
|
|
40575
40447
|
severity: "warn",
|
|
40576
|
-
messages:
|
|
40448
|
+
messages: messages151,
|
|
40577
40449
|
meta: {
|
|
40578
40450
|
description: "Disallow conditional display collapse in flow without reserved geometry.",
|
|
40579
40451
|
fixable: false,
|
|
@@ -40594,13 +40466,13 @@ var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
|
40594
40466
|
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
40595
40467
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40596
40468
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40597
|
-
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;
|
|
40598
40470
|
}
|
|
40599
40471
|
}
|
|
40600
40472
|
});
|
|
40601
40473
|
|
|
40602
40474
|
// src/cross-file/rules/css-layout-conditional-white-space-wrap-shift.ts
|
|
40603
|
-
var
|
|
40475
|
+
var messages152 = {
|
|
40604
40476
|
conditionalWhiteSpaceShift: "Conditional white-space '{{whiteSpace}}' on '{{tag}}' can reflow text and shift siblings; keep wrapping behavior stable or reserve geometry."
|
|
40605
40477
|
};
|
|
40606
40478
|
var WRAP_SHIFT_VALUES = /* @__PURE__ */ new Set(["nowrap", "pre"]);
|
|
@@ -40609,7 +40481,7 @@ var BLOCK_SIZE_PROPERTIES = ["height", "min-height"];
|
|
|
40609
40481
|
var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
40610
40482
|
id: "css-layout-conditional-white-space-wrap-shift",
|
|
40611
40483
|
severity: "warn",
|
|
40612
|
-
messages:
|
|
40484
|
+
messages: messages152,
|
|
40613
40485
|
meta: {
|
|
40614
40486
|
description: "Disallow conditional white-space wrapping mode toggles that can trigger CLS.",
|
|
40615
40487
|
fixable: false,
|
|
@@ -40632,7 +40504,7 @@ var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
|
40632
40504
|
if (!flow.inFlow) continue;
|
|
40633
40505
|
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
40634
40506
|
if (hasStableTextShell(snapshot)) continue;
|
|
40635
|
-
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;
|
|
40636
40508
|
}
|
|
40637
40509
|
}
|
|
40638
40510
|
});
|
|
@@ -40654,13 +40526,13 @@ function hasWrapShiftDelta(delta) {
|
|
|
40654
40526
|
}
|
|
40655
40527
|
|
|
40656
40528
|
// src/cross-file/rules/css-layout-overflow-mode-toggle-instability.ts
|
|
40657
|
-
var
|
|
40529
|
+
var messages153 = {
|
|
40658
40530
|
overflowModeToggle: "Conditional overflow mode changes scrolling ('{{overflow}}') on '{{tag}}' without `scrollbar-gutter: stable`, which can trigger CLS."
|
|
40659
40531
|
};
|
|
40660
40532
|
var cssLayoutOverflowModeToggleInstability = defineCrossRule({
|
|
40661
40533
|
id: "css-layout-overflow-mode-toggle-instability",
|
|
40662
40534
|
severity: "warn",
|
|
40663
|
-
messages:
|
|
40535
|
+
messages: messages153,
|
|
40664
40536
|
meta: {
|
|
40665
40537
|
description: "Disallow conditional overflow mode switches that can introduce scrollbar-induced layout shifts.",
|
|
40666
40538
|
fixable: false,
|
|
@@ -40685,7 +40557,7 @@ var cssLayoutOverflowModeToggleInstability = defineCrossRule({
|
|
|
40685
40557
|
const gutter = readKnownNormalizedWithGuard(snapshot, "scrollbar-gutter");
|
|
40686
40558
|
if (gutter !== null && gutter.startsWith("stable")) continue;
|
|
40687
40559
|
const overflowValue = scrollFact.overflowY ?? scrollFact.overflow ?? "auto";
|
|
40688
|
-
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;
|
|
40689
40561
|
}
|
|
40690
40562
|
}
|
|
40691
40563
|
});
|
|
@@ -40705,7 +40577,7 @@ function hasAnyScrollValue(delta) {
|
|
|
40705
40577
|
}
|
|
40706
40578
|
|
|
40707
40579
|
// src/cross-file/rules/css-layout-box-sizing-toggle-with-chrome.ts
|
|
40708
|
-
var
|
|
40580
|
+
var messages154 = {
|
|
40709
40581
|
boxSizingToggleWithChrome: "Conditional `box-sizing` toggle on '{{tag}}' combines with non-zero padding/border, which can shift layout and trigger CLS."
|
|
40710
40582
|
};
|
|
40711
40583
|
var BOX_SIZING_VALUES = /* @__PURE__ */ new Set(["content-box", "border-box"]);
|
|
@@ -40722,7 +40594,7 @@ var CHROME_PROPERTIES = [
|
|
|
40722
40594
|
var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
|
|
40723
40595
|
id: "css-layout-box-sizing-toggle-with-chrome",
|
|
40724
40596
|
severity: "warn",
|
|
40725
|
-
messages:
|
|
40597
|
+
messages: messages154,
|
|
40726
40598
|
meta: {
|
|
40727
40599
|
description: "Disallow conditional box-sizing mode toggles when box chrome contributes to geometry shifts.",
|
|
40728
40600
|
fixable: false,
|
|
@@ -40740,7 +40612,7 @@ var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
|
|
|
40740
40612
|
if (!boxSizingDelta.hasConditional) continue;
|
|
40741
40613
|
if (!boxSizingDelta.hasDelta) continue;
|
|
40742
40614
|
if (!hasNonZeroChrome(snapshot)) continue;
|
|
40743
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome",
|
|
40615
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages154.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
|
|
40744
40616
|
}
|
|
40745
40617
|
}
|
|
40746
40618
|
});
|
|
@@ -40749,13 +40621,13 @@ function hasNonZeroChrome(snapshot) {
|
|
|
40749
40621
|
}
|
|
40750
40622
|
|
|
40751
40623
|
// src/cross-file/rules/css-layout-content-visibility-no-intrinsic-size.ts
|
|
40752
|
-
var
|
|
40624
|
+
var messages155 = {
|
|
40753
40625
|
missingIntrinsicSize: "`content-visibility: auto` on '{{tag}}' lacks intrinsic size reservation (`contain-intrinsic-size`/min-height/height/aspect-ratio), which can cause CLS."
|
|
40754
40626
|
};
|
|
40755
40627
|
var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
40756
40628
|
id: "css-layout-content-visibility-no-intrinsic-size",
|
|
40757
40629
|
severity: "warn",
|
|
40758
|
-
messages:
|
|
40630
|
+
messages: messages155,
|
|
40759
40631
|
meta: {
|
|
40760
40632
|
description: "Require intrinsic size reservation when using content-visibility auto to avoid late layout shifts.",
|
|
40761
40633
|
fixable: false,
|
|
@@ -40770,19 +40642,19 @@ var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
|
40770
40642
|
if (!isDeferredContainerLike(node, snapshot.node.textualContent)) continue;
|
|
40771
40643
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40772
40644
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40773
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize",
|
|
40645
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages155.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
|
|
40774
40646
|
}
|
|
40775
40647
|
}
|
|
40776
40648
|
});
|
|
40777
40649
|
|
|
40778
40650
|
// src/cross-file/rules/css-layout-conditional-offset-shift.ts
|
|
40779
|
-
var
|
|
40651
|
+
var messages156 = {
|
|
40780
40652
|
conditionalOffsetShift: "Conditional style applies non-zero '{{property}}' offset ({{value}}), which can cause layout shifts when conditions toggle."
|
|
40781
40653
|
};
|
|
40782
40654
|
var cssLayoutConditionalOffsetShift = defineCrossRule({
|
|
40783
40655
|
id: "css-layout-conditional-offset-shift",
|
|
40784
40656
|
severity: "warn",
|
|
40785
|
-
messages:
|
|
40657
|
+
messages: messages156,
|
|
40786
40658
|
meta: {
|
|
40787
40659
|
description: "Disallow conditional non-zero block-axis offsets that can trigger layout shifts.",
|
|
40788
40660
|
fixable: false,
|
|
@@ -40808,7 +40680,7 @@ var cssLayoutConditionalOffsetShift = defineCrossRule({
|
|
|
40808
40680
|
ref.solid.sourceFile,
|
|
40809
40681
|
cssLayoutConditionalOffsetShift.id,
|
|
40810
40682
|
"conditionalOffsetShift",
|
|
40811
|
-
resolveMessage(
|
|
40683
|
+
resolveMessage(messages156.conditionalOffsetShift, {
|
|
40812
40684
|
property: match.property,
|
|
40813
40685
|
value: `${formatFixed(match.value)}px`
|
|
40814
40686
|
}),
|
|
@@ -40869,7 +40741,7 @@ function hasStableBaseline(baselineBySignal, property, expectedPx) {
|
|
|
40869
40741
|
|
|
40870
40742
|
// src/cross-file/rules/jsx-layout-unstable-style-toggle.ts
|
|
40871
40743
|
import ts135 from "typescript";
|
|
40872
|
-
var
|
|
40744
|
+
var messages157 = {
|
|
40873
40745
|
unstableLayoutStyleToggle: "Dynamic style value for '{{property}}' can toggle layout geometry at runtime and cause CLS."
|
|
40874
40746
|
};
|
|
40875
40747
|
var PX_NUMBER_PROPERTIES = /* @__PURE__ */ new Set([
|
|
@@ -40892,7 +40764,7 @@ var POSITIONED_OFFSET_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
40892
40764
|
var jsxLayoutUnstableStyleToggle = defineCrossRule({
|
|
40893
40765
|
id: "jsx-layout-unstable-style-toggle",
|
|
40894
40766
|
severity: "warn",
|
|
40895
|
-
messages:
|
|
40767
|
+
messages: messages157,
|
|
40896
40768
|
meta: {
|
|
40897
40769
|
description: "Flag dynamic inline style values on layout-sensitive properties that can trigger CLS.",
|
|
40898
40770
|
fixable: false,
|
|
@@ -40914,7 +40786,7 @@ var jsxLayoutUnstableStyleToggle = defineCrossRule({
|
|
|
40914
40786
|
solid.sourceFile,
|
|
40915
40787
|
jsxLayoutUnstableStyleToggle.id,
|
|
40916
40788
|
"unstableLayoutStyleToggle",
|
|
40917
|
-
resolveMessage(
|
|
40789
|
+
resolveMessage(messages157.unstableLayoutStyleToggle, { property: normalized }),
|
|
40918
40790
|
"warn"
|
|
40919
40791
|
)
|
|
40920
40792
|
);
|
|
@@ -41031,14 +40903,14 @@ function unwrapTypeWrapper(node) {
|
|
|
41031
40903
|
|
|
41032
40904
|
// src/cross-file/rules/jsx-layout-classlist-geometry-toggle.ts
|
|
41033
40905
|
import ts136 from "typescript";
|
|
41034
|
-
var
|
|
40906
|
+
var messages158 = {
|
|
41035
40907
|
classListGeometryToggle: "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS."
|
|
41036
40908
|
};
|
|
41037
40909
|
var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
|
|
41038
40910
|
var jsxLayoutClasslistGeometryToggle = defineCrossRule({
|
|
41039
40911
|
id: "jsx-layout-classlist-geometry-toggle",
|
|
41040
40912
|
severity: "warn",
|
|
41041
|
-
messages:
|
|
40913
|
+
messages: messages158,
|
|
41042
40914
|
meta: {
|
|
41043
40915
|
description: "Flag classList-driven class toggles that map to layout-affecting CSS geometry changes.",
|
|
41044
40916
|
fixable: false,
|
|
@@ -41064,7 +40936,7 @@ var jsxLayoutClasslistGeometryToggle = defineCrossRule({
|
|
|
41064
40936
|
solid.sourceFile,
|
|
41065
40937
|
jsxLayoutClasslistGeometryToggle.id,
|
|
41066
40938
|
"classListGeometryToggle",
|
|
41067
|
-
resolveMessage(
|
|
40939
|
+
resolveMessage(messages158.classListGeometryToggle, {
|
|
41068
40940
|
className,
|
|
41069
40941
|
property
|
|
41070
40942
|
}),
|
|
@@ -41113,14 +40985,14 @@ function isDynamicallyToggleable(node) {
|
|
|
41113
40985
|
}
|
|
41114
40986
|
|
|
41115
40987
|
// src/cross-file/rules/jsx-layout-picture-source-ratio-consistency.ts
|
|
41116
|
-
var
|
|
40988
|
+
var messages159 = {
|
|
41117
40989
|
inconsistentPictureRatio: "`<picture>` source ratio {{sourceRatio}} differs from fallback img ratio {{imgRatio}}, which can cause reserved-space mismatch and CLS."
|
|
41118
40990
|
};
|
|
41119
40991
|
var RATIO_DELTA_THRESHOLD = 0.02;
|
|
41120
40992
|
var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
|
|
41121
40993
|
id: "jsx-layout-picture-source-ratio-consistency",
|
|
41122
40994
|
severity: "warn",
|
|
41123
|
-
messages:
|
|
40995
|
+
messages: messages159,
|
|
41124
40996
|
meta: {
|
|
41125
40997
|
description: "Require consistent intrinsic aspect ratios across <picture> sources and fallback image.",
|
|
41126
40998
|
fixable: false,
|
|
@@ -41143,7 +41015,7 @@ var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
|
|
|
41143
41015
|
solid.sourceFile,
|
|
41144
41016
|
jsxLayoutPictureSourceRatioConsistency.id,
|
|
41145
41017
|
"inconsistentPictureRatio",
|
|
41146
|
-
resolveMessage(
|
|
41018
|
+
resolveMessage(messages159.inconsistentPictureRatio, {
|
|
41147
41019
|
sourceRatio: mismatch.sourceRatio,
|
|
41148
41020
|
imgRatio: mismatch.imgRatio
|
|
41149
41021
|
}),
|
|
@@ -41213,13 +41085,13 @@ function formatRatio(value2) {
|
|
|
41213
41085
|
}
|
|
41214
41086
|
|
|
41215
41087
|
// src/cross-file/rules/jsx-layout-fill-image-parent-must-be-sized.ts
|
|
41216
|
-
var
|
|
41088
|
+
var messages160 = {
|
|
41217
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."
|
|
41218
41090
|
};
|
|
41219
41091
|
var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
41220
41092
|
id: "jsx-layout-fill-image-parent-must-be-sized",
|
|
41221
41093
|
severity: "warn",
|
|
41222
|
-
messages:
|
|
41094
|
+
messages: messages160,
|
|
41223
41095
|
meta: {
|
|
41224
41096
|
description: "Require stable parent size and positioning for fill-image component usage.",
|
|
41225
41097
|
fixable: false,
|
|
@@ -41249,7 +41121,7 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
|
41249
41121
|
solid.sourceFile,
|
|
41250
41122
|
jsxLayoutFillImageParentMustBeSized.id,
|
|
41251
41123
|
"unsizedFillParent",
|
|
41252
|
-
resolveMessage(
|
|
41124
|
+
resolveMessage(messages160.unsizedFillParent, {
|
|
41253
41125
|
component: element.tag ?? "Image"
|
|
41254
41126
|
}),
|
|
41255
41127
|
"warn"
|
|
@@ -41260,6 +41132,210 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
|
41260
41132
|
}
|
|
41261
41133
|
});
|
|
41262
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
|
+
|
|
41263
41339
|
// src/cross-file/rules/index.ts
|
|
41264
41340
|
var rules3 = [
|
|
41265
41341
|
jsxNoUndefinedCssClass,
|
|
@@ -41291,7 +41367,8 @@ var rules3 = [
|
|
|
41291
41367
|
cssLayoutOverflowModeToggleInstability,
|
|
41292
41368
|
cssLayoutBoxSizingToggleWithChrome,
|
|
41293
41369
|
cssLayoutContentVisibilityNoIntrinsicSize,
|
|
41294
|
-
cssLayoutConditionalOffsetShift
|
|
41370
|
+
cssLayoutConditionalOffsetShift,
|
|
41371
|
+
jsxLayoutPolicyTouchTarget
|
|
41295
41372
|
];
|
|
41296
41373
|
|
|
41297
41374
|
// src/cross-file/plugin.ts
|
|
@@ -41388,4 +41465,4 @@ export {
|
|
|
41388
41465
|
rules3,
|
|
41389
41466
|
runCrossFileRules
|
|
41390
41467
|
};
|
|
41391
|
-
//# sourceMappingURL=chunk-
|
|
41468
|
+
//# sourceMappingURL=chunk-MJKIL7DJ.js.map
|