@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
package/dist/eslint-plugin.cjs
CHANGED
|
@@ -142,9 +142,29 @@ function canonicalPath(path) {
|
|
|
142
142
|
return canonical;
|
|
143
143
|
}
|
|
144
144
|
var LOG_LEVELS = ["trace", "debug", "info", "warning", "error", "critical", "off"];
|
|
145
|
+
var Level = {
|
|
146
|
+
Trace: 0,
|
|
147
|
+
Debug: 1,
|
|
148
|
+
Info: 2,
|
|
149
|
+
Warning: 3,
|
|
150
|
+
Error: 4,
|
|
151
|
+
Critical: 5,
|
|
152
|
+
Off: 6
|
|
153
|
+
};
|
|
154
|
+
var LOG_LEVEL_ORDER = {
|
|
155
|
+
trace: Level.Trace,
|
|
156
|
+
debug: Level.Debug,
|
|
157
|
+
info: Level.Info,
|
|
158
|
+
warning: Level.Warning,
|
|
159
|
+
error: Level.Error,
|
|
160
|
+
critical: Level.Critical,
|
|
161
|
+
off: Level.Off
|
|
162
|
+
};
|
|
145
163
|
var noopLogger = {
|
|
146
|
-
enabled: false,
|
|
147
164
|
level: "off",
|
|
165
|
+
isLevelEnabled() {
|
|
166
|
+
return false;
|
|
167
|
+
},
|
|
148
168
|
trace() {
|
|
149
169
|
},
|
|
150
170
|
debug() {
|
|
@@ -2913,6 +2933,35 @@ var TypeResolver = class {
|
|
|
2913
2933
|
return false;
|
|
2914
2934
|
}
|
|
2915
2935
|
}
|
|
2936
|
+
/**
|
|
2937
|
+
* Strict array check: only matches Array<T>, T[], ReadonlyArray<T>, and tuples.
|
|
2938
|
+
* Does NOT match typed arrays (Uint8Array, Buffer, etc.) or other types with
|
|
2939
|
+
* a numeric index signature.
|
|
2940
|
+
*/
|
|
2941
|
+
isStrictArrayType(node) {
|
|
2942
|
+
try {
|
|
2943
|
+
const tsType = this.checker.getTypeAtLocation(node);
|
|
2944
|
+
return this.checkIsStrictArrayType(tsType);
|
|
2945
|
+
} catch {
|
|
2946
|
+
return false;
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
checkIsStrictArrayType(tsType) {
|
|
2950
|
+
if (tsType.flags & 524288) {
|
|
2951
|
+
const objFlags = getObjectFlags(tsType);
|
|
2952
|
+
if (objFlags & 8) return true;
|
|
2953
|
+
if (objFlags & 4) {
|
|
2954
|
+
const name = tsType.getSymbol()?.getName();
|
|
2955
|
+
if (name === "Array" || name === "ReadonlyArray") return true;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
if (tsType.isUnion()) {
|
|
2959
|
+
for (const t of tsType.types) {
|
|
2960
|
+
if (this.checkIsStrictArrayType(t)) return true;
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
return false;
|
|
2964
|
+
}
|
|
2916
2965
|
checkIsArrayType(tsType) {
|
|
2917
2966
|
if (tsType.flags & 524288) {
|
|
2918
2967
|
const objFlags = getObjectFlags(tsType);
|
|
@@ -2964,7 +3013,7 @@ var TypeResolver = class {
|
|
|
2964
3013
|
if (exprTsType.flags & import_typescript2.default.TypeFlags.Any) return false;
|
|
2965
3014
|
if (targetTsType.flags & import_typescript2.default.TypeFlags.Any) return false;
|
|
2966
3015
|
const result = this.checker.isTypeAssignableTo(exprTsType, targetTsType);
|
|
2967
|
-
if (this.logger.
|
|
3016
|
+
if (this.logger.isLevelEnabled(Level.Debug)) {
|
|
2968
3017
|
const exprStr = this.checker.typeToString(exprTsType);
|
|
2969
3018
|
const targetStr = this.checker.typeToString(targetTsType);
|
|
2970
3019
|
this.logger.debug(`isUnnecessaryCast: expr="${exprStr.slice(0, 120)}" target="${targetStr.slice(0, 120)}" assignable=${result} exprFlags=${exprTsType.flags} targetFlags=${targetTsType.flags}`);
|
|
@@ -3481,6 +3530,7 @@ function getStaticStringFromJSXValue(node) {
|
|
|
3481
3530
|
const expression = node.expression;
|
|
3482
3531
|
if (!expression) return null;
|
|
3483
3532
|
if (import_typescript4.default.isStringLiteral(expression)) return expression.text;
|
|
3533
|
+
if (import_typescript4.default.isNumericLiteral(expression)) return expression.text;
|
|
3484
3534
|
if (import_typescript4.default.isNoSubstitutionTemplateLiteral(expression)) return expression.text;
|
|
3485
3535
|
if (import_typescript4.default.isTemplateExpression(expression) && expression.templateSpans.length === 0) {
|
|
3486
3536
|
return expression.head.text;
|
|
@@ -9928,6 +9978,9 @@ function typeIncludesString(graph, node) {
|
|
|
9928
9978
|
function typeIsArray(graph, node) {
|
|
9929
9979
|
return graph.typeResolver.isArrayType(node);
|
|
9930
9980
|
}
|
|
9981
|
+
function typeIsStrictArray(graph, node) {
|
|
9982
|
+
return graph.typeResolver.isStrictArrayType(node);
|
|
9983
|
+
}
|
|
9931
9984
|
function getArrayElementKind(graph, node) {
|
|
9932
9985
|
return graph.typeResolver.getArrayElementKind(node);
|
|
9933
9986
|
}
|
|
@@ -19723,6 +19776,7 @@ var preferSetLookupInLoop = defineSolidRule({
|
|
|
19723
19776
|
options: options77,
|
|
19724
19777
|
check(graph, emit) {
|
|
19725
19778
|
const reported = /* @__PURE__ */ new Set();
|
|
19779
|
+
const graphHasTypes = hasTypeInfo(graph);
|
|
19726
19780
|
for (const method of LINEAR_SEARCH_METHODS) {
|
|
19727
19781
|
const calls = getCallsByMethodName(graph, method);
|
|
19728
19782
|
for (let i = 0, len = calls.length; i < len; i++) {
|
|
@@ -19740,6 +19794,7 @@ var preferSetLookupInLoop = defineSolidRule({
|
|
|
19740
19794
|
const loop = getEnclosingLoop(call.node);
|
|
19741
19795
|
if (!loop) continue;
|
|
19742
19796
|
if (!isDeclaredOutsideLoop2(loop, variable)) continue;
|
|
19797
|
+
if (graphHasTypes && !typeIsStrictArray(graph, callee.expression)) continue;
|
|
19743
19798
|
if (isStringLikeReceiver(graph, callee.expression, variable)) continue;
|
|
19744
19799
|
const key = `${loop.pos}:var:${variable.id}`;
|
|
19745
19800
|
if (reported.has(key)) continue;
|
|
@@ -29483,148 +29538,8 @@ function checkParagraphSpacing(graph, emit, policy, name) {
|
|
|
29483
29538
|
}
|
|
29484
29539
|
}
|
|
29485
29540
|
|
|
29486
|
-
// src/css/rules/a11y/css-policy-touch-target.ts
|
|
29487
|
-
var messages125 = {
|
|
29488
|
-
heightTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
29489
|
-
widthTooSmall: "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
29490
|
-
paddingTooSmall: "Horizontal padding `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`."
|
|
29491
|
-
};
|
|
29492
|
-
function classifyRule(rule) {
|
|
29493
|
-
if (rule.elementKinds.has("button")) return "button";
|
|
29494
|
-
if (rule.elementKinds.has("input")) return "input";
|
|
29495
|
-
return null;
|
|
29496
|
-
}
|
|
29497
|
-
var HEIGHT_PROPERTIES = /* @__PURE__ */ new Set(["height", "min-height"]);
|
|
29498
|
-
var WIDTH_PROPERTIES = /* @__PURE__ */ new Set(["width", "min-width"]);
|
|
29499
|
-
var HPADDING_PROPERTIES = /* @__PURE__ */ new Set(["padding-left", "padding-right", "padding-inline", "padding-inline-start", "padding-inline-end"]);
|
|
29500
|
-
var cssPolicyTouchTarget = defineCSSRule({
|
|
29501
|
-
id: "css-policy-touch-target",
|
|
29502
|
-
severity: "warn",
|
|
29503
|
-
messages: messages125,
|
|
29504
|
-
meta: {
|
|
29505
|
-
description: "Enforce minimum interactive element sizes per accessibility policy.",
|
|
29506
|
-
fixable: false,
|
|
29507
|
-
category: "css-a11y"
|
|
29508
|
-
},
|
|
29509
|
-
options: {},
|
|
29510
|
-
check(graph, emit) {
|
|
29511
|
-
const policy = getActivePolicy();
|
|
29512
|
-
if (policy === null) return;
|
|
29513
|
-
const name = getActivePolicyName() ?? "";
|
|
29514
|
-
const decls = graph.declarationsForProperties(
|
|
29515
|
-
"height",
|
|
29516
|
-
"min-height",
|
|
29517
|
-
"width",
|
|
29518
|
-
"min-width",
|
|
29519
|
-
"padding-left",
|
|
29520
|
-
"padding-right",
|
|
29521
|
-
"padding-inline",
|
|
29522
|
-
"padding-inline-start",
|
|
29523
|
-
"padding-inline-end"
|
|
29524
|
-
);
|
|
29525
|
-
for (let i = 0; i < decls.length; i++) {
|
|
29526
|
-
const d = decls[i];
|
|
29527
|
-
if (!d) continue;
|
|
29528
|
-
if (!d.rule) continue;
|
|
29529
|
-
const prop = d.property.toLowerCase();
|
|
29530
|
-
const kind = classifyRule(d.rule);
|
|
29531
|
-
if (!kind) continue;
|
|
29532
|
-
if (isVisuallyHiddenInput(d.rule)) continue;
|
|
29533
|
-
const px = parsePxValue(d.value);
|
|
29534
|
-
if (px === null) continue;
|
|
29535
|
-
if (HEIGHT_PROPERTIES.has(prop)) {
|
|
29536
|
-
const min = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
|
|
29537
|
-
if (px >= min) continue;
|
|
29538
|
-
emitCSSDiagnostic(
|
|
29539
|
-
emit,
|
|
29540
|
-
d.file.path,
|
|
29541
|
-
d.startLine,
|
|
29542
|
-
d.startColumn,
|
|
29543
|
-
cssPolicyTouchTarget,
|
|
29544
|
-
"heightTooSmall",
|
|
29545
|
-
resolveMessage(messages125.heightTooSmall, {
|
|
29546
|
-
property: d.property,
|
|
29547
|
-
value: d.value.trim(),
|
|
29548
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
29549
|
-
min: String(min),
|
|
29550
|
-
element: kind,
|
|
29551
|
-
policy: name
|
|
29552
|
-
})
|
|
29553
|
-
);
|
|
29554
|
-
continue;
|
|
29555
|
-
}
|
|
29556
|
-
if (WIDTH_PROPERTIES.has(prop)) {
|
|
29557
|
-
const min = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
|
|
29558
|
-
if (px >= min) continue;
|
|
29559
|
-
emitCSSDiagnostic(
|
|
29560
|
-
emit,
|
|
29561
|
-
d.file.path,
|
|
29562
|
-
d.startLine,
|
|
29563
|
-
d.startColumn,
|
|
29564
|
-
cssPolicyTouchTarget,
|
|
29565
|
-
"widthTooSmall",
|
|
29566
|
-
resolveMessage(messages125.widthTooSmall, {
|
|
29567
|
-
property: d.property,
|
|
29568
|
-
value: d.value.trim(),
|
|
29569
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
29570
|
-
min: String(min),
|
|
29571
|
-
element: kind,
|
|
29572
|
-
policy: name
|
|
29573
|
-
})
|
|
29574
|
-
);
|
|
29575
|
-
continue;
|
|
29576
|
-
}
|
|
29577
|
-
if (kind === "button" && HPADDING_PROPERTIES.has(prop)) {
|
|
29578
|
-
if (px >= policy.minButtonHorizontalPadding) continue;
|
|
29579
|
-
emitCSSDiagnostic(
|
|
29580
|
-
emit,
|
|
29581
|
-
d.file.path,
|
|
29582
|
-
d.startLine,
|
|
29583
|
-
d.startColumn,
|
|
29584
|
-
cssPolicyTouchTarget,
|
|
29585
|
-
"paddingTooSmall",
|
|
29586
|
-
resolveMessage(messages125.paddingTooSmall, {
|
|
29587
|
-
value: d.value.trim(),
|
|
29588
|
-
resolved: String(Math.round(px * 100) / 100),
|
|
29589
|
-
min: String(policy.minButtonHorizontalPadding),
|
|
29590
|
-
element: kind,
|
|
29591
|
-
policy: name
|
|
29592
|
-
})
|
|
29593
|
-
);
|
|
29594
|
-
}
|
|
29595
|
-
}
|
|
29596
|
-
}
|
|
29597
|
-
});
|
|
29598
|
-
function isVisuallyHiddenInput(rule) {
|
|
29599
|
-
if (!hasPositionAbsoluteOrFixed(rule)) return false;
|
|
29600
|
-
if (!hasOpacityZero(rule)) return false;
|
|
29601
|
-
return true;
|
|
29602
|
-
}
|
|
29603
|
-
function hasPositionAbsoluteOrFixed(rule) {
|
|
29604
|
-
const positionDecls = rule.declarationIndex.get("position");
|
|
29605
|
-
if (!positionDecls || positionDecls.length === 0) return false;
|
|
29606
|
-
for (let i = 0; i < positionDecls.length; i++) {
|
|
29607
|
-
const decl = positionDecls[i];
|
|
29608
|
-
if (!decl) continue;
|
|
29609
|
-
const v = decl.value.trim().toLowerCase();
|
|
29610
|
-
if (v === "absolute" || v === "fixed") return true;
|
|
29611
|
-
}
|
|
29612
|
-
return false;
|
|
29613
|
-
}
|
|
29614
|
-
function hasOpacityZero(rule) {
|
|
29615
|
-
const opacityDecls = rule.declarationIndex.get("opacity");
|
|
29616
|
-
if (!opacityDecls || opacityDecls.length === 0) return false;
|
|
29617
|
-
for (let i = 0; i < opacityDecls.length; i++) {
|
|
29618
|
-
const decl = opacityDecls[i];
|
|
29619
|
-
if (!decl) continue;
|
|
29620
|
-
const v = decl.value.trim();
|
|
29621
|
-
if (v === "0") return true;
|
|
29622
|
-
}
|
|
29623
|
-
return false;
|
|
29624
|
-
}
|
|
29625
|
-
|
|
29626
29541
|
// src/css/rules/a11y/css-policy-typography.ts
|
|
29627
|
-
var
|
|
29542
|
+
var messages125 = {
|
|
29628
29543
|
fontTooSmall: "Font size `{{value}}` ({{resolved}}px) is below the `{{context}}` minimum of `{{min}}px` for policy `{{policy}}`.",
|
|
29629
29544
|
lineHeightTooSmall: "Line height `{{value}}` is below the `{{context}}` minimum of `{{min}}` for policy `{{policy}}`."
|
|
29630
29545
|
};
|
|
@@ -29660,7 +29575,7 @@ function resolveLineHeightContext(d, p) {
|
|
|
29660
29575
|
var cssPolicyTypography = defineCSSRule({
|
|
29661
29576
|
id: "css-policy-typography",
|
|
29662
29577
|
severity: "warn",
|
|
29663
|
-
messages:
|
|
29578
|
+
messages: messages125,
|
|
29664
29579
|
meta: {
|
|
29665
29580
|
description: "Enforce minimum font sizes and line heights per accessibility policy.",
|
|
29666
29581
|
fixable: false,
|
|
@@ -29687,7 +29602,7 @@ var cssPolicyTypography = defineCSSRule({
|
|
|
29687
29602
|
d.startColumn,
|
|
29688
29603
|
cssPolicyTypography,
|
|
29689
29604
|
"fontTooSmall",
|
|
29690
|
-
resolveMessage(
|
|
29605
|
+
resolveMessage(messages125.fontTooSmall, {
|
|
29691
29606
|
value: d.value.trim(),
|
|
29692
29607
|
resolved: String(Math.round(px * 100) / 100),
|
|
29693
29608
|
context,
|
|
@@ -29714,7 +29629,7 @@ var cssPolicyTypography = defineCSSRule({
|
|
|
29714
29629
|
d.startColumn,
|
|
29715
29630
|
cssPolicyTypography,
|
|
29716
29631
|
"lineHeightTooSmall",
|
|
29717
|
-
resolveMessage(
|
|
29632
|
+
resolveMessage(messages125.lineHeightTooSmall, {
|
|
29718
29633
|
value: d.value.trim(),
|
|
29719
29634
|
context,
|
|
29720
29635
|
min: String(min),
|
|
@@ -29732,7 +29647,7 @@ var ZERO_S = /(^|\s|,)0s($|\s|,)/;
|
|
|
29732
29647
|
var TIME_VALUE_G = /([0-9]*\.?[0-9]+)(ms|s)/g;
|
|
29733
29648
|
var AMPERSAND_G = /&/g;
|
|
29734
29649
|
var WHITESPACE_G = /\s+/g;
|
|
29735
|
-
var
|
|
29650
|
+
var messages126 = {
|
|
29736
29651
|
missingReducedMotion: "Animated selector `{{selector}}` lacks prefers-reduced-motion override."
|
|
29737
29652
|
};
|
|
29738
29653
|
function isAnimationDecl(p) {
|
|
@@ -29836,7 +29751,7 @@ function normalizeSelector2(s) {
|
|
|
29836
29751
|
var cssRequireReducedMotionOverride = defineCSSRule({
|
|
29837
29752
|
id: "css-require-reduced-motion-override",
|
|
29838
29753
|
severity: "warn",
|
|
29839
|
-
messages:
|
|
29754
|
+
messages: messages126,
|
|
29840
29755
|
meta: {
|
|
29841
29756
|
description: "Require reduced-motion override for animated selectors.",
|
|
29842
29757
|
fixable: false,
|
|
@@ -29899,20 +29814,20 @@ var cssRequireReducedMotionOverride = defineCSSRule({
|
|
|
29899
29814
|
d.startColumn,
|
|
29900
29815
|
cssRequireReducedMotionOverride,
|
|
29901
29816
|
"missingReducedMotion",
|
|
29902
|
-
resolveMessage(
|
|
29817
|
+
resolveMessage(messages126.missingReducedMotion, { selector: r.selectorText })
|
|
29903
29818
|
);
|
|
29904
29819
|
}
|
|
29905
29820
|
}
|
|
29906
29821
|
});
|
|
29907
29822
|
|
|
29908
29823
|
// src/css/rules/structure/css-no-empty-rule.ts
|
|
29909
|
-
var
|
|
29824
|
+
var messages127 = {
|
|
29910
29825
|
emptyRule: "Empty rule `{{selector}}` should be removed."
|
|
29911
29826
|
};
|
|
29912
29827
|
var cssNoEmptyRule = defineCSSRule({
|
|
29913
29828
|
id: "css-no-empty-rule",
|
|
29914
29829
|
severity: "warn",
|
|
29915
|
-
messages:
|
|
29830
|
+
messages: messages127,
|
|
29916
29831
|
meta: {
|
|
29917
29832
|
description: "Disallow empty CSS rules.",
|
|
29918
29833
|
fixable: false,
|
|
@@ -29930,20 +29845,20 @@ var cssNoEmptyRule = defineCSSRule({
|
|
|
29930
29845
|
rule.startColumn,
|
|
29931
29846
|
cssNoEmptyRule,
|
|
29932
29847
|
"emptyRule",
|
|
29933
|
-
resolveMessage(
|
|
29848
|
+
resolveMessage(messages127.emptyRule, { selector: rule.selectorText })
|
|
29934
29849
|
);
|
|
29935
29850
|
}
|
|
29936
29851
|
}
|
|
29937
29852
|
});
|
|
29938
29853
|
|
|
29939
29854
|
// src/css/rules/structure/css-no-unknown-container-name.ts
|
|
29940
|
-
var
|
|
29855
|
+
var messages128 = {
|
|
29941
29856
|
unknownContainer: "Unknown container name `{{name}}` in @container query."
|
|
29942
29857
|
};
|
|
29943
29858
|
var cssNoUnknownContainerName = defineCSSRule({
|
|
29944
29859
|
id: "css-no-unknown-container-name",
|
|
29945
29860
|
severity: "error",
|
|
29946
|
-
messages:
|
|
29861
|
+
messages: messages128,
|
|
29947
29862
|
meta: {
|
|
29948
29863
|
description: "Disallow unknown named containers in @container queries.",
|
|
29949
29864
|
fixable: false,
|
|
@@ -29963,20 +29878,20 @@ var cssNoUnknownContainerName = defineCSSRule({
|
|
|
29963
29878
|
1,
|
|
29964
29879
|
cssNoUnknownContainerName,
|
|
29965
29880
|
"unknownContainer",
|
|
29966
|
-
resolveMessage(
|
|
29881
|
+
resolveMessage(messages128.unknownContainer, { name })
|
|
29967
29882
|
);
|
|
29968
29883
|
}
|
|
29969
29884
|
}
|
|
29970
29885
|
});
|
|
29971
29886
|
|
|
29972
29887
|
// src/css/rules/structure/css-no-unused-container-name.ts
|
|
29973
|
-
var
|
|
29888
|
+
var messages129 = {
|
|
29974
29889
|
unusedContainer: "Container name `{{name}}` is declared but never queried."
|
|
29975
29890
|
};
|
|
29976
29891
|
var cssNoUnusedContainerName = defineCSSRule({
|
|
29977
29892
|
id: "css-no-unused-container-name",
|
|
29978
29893
|
severity: "warn",
|
|
29979
|
-
messages:
|
|
29894
|
+
messages: messages129,
|
|
29980
29895
|
meta: {
|
|
29981
29896
|
description: "Disallow unused named containers.",
|
|
29982
29897
|
fixable: false,
|
|
@@ -29999,7 +29914,7 @@ var cssNoUnusedContainerName = defineCSSRule({
|
|
|
29999
29914
|
d.startColumn,
|
|
30000
29915
|
cssNoUnusedContainerName,
|
|
30001
29916
|
"unusedContainer",
|
|
30002
|
-
resolveMessage(
|
|
29917
|
+
resolveMessage(messages129.unusedContainer, { name })
|
|
30003
29918
|
);
|
|
30004
29919
|
}
|
|
30005
29920
|
}
|
|
@@ -30007,13 +29922,13 @@ var cssNoUnusedContainerName = defineCSSRule({
|
|
|
30007
29922
|
});
|
|
30008
29923
|
|
|
30009
29924
|
// src/css/rules/structure/layer-requirement-for-component-rules.ts
|
|
30010
|
-
var
|
|
29925
|
+
var messages130 = {
|
|
30011
29926
|
missingLayer: "Rule `{{selector}}` is not inside any @layer block while this file uses @layer. Place component rules inside an explicit layer."
|
|
30012
29927
|
};
|
|
30013
29928
|
var layerRequirementForComponentRules = defineCSSRule({
|
|
30014
29929
|
id: "layer-requirement-for-component-rules",
|
|
30015
29930
|
severity: "warn",
|
|
30016
|
-
messages:
|
|
29931
|
+
messages: messages130,
|
|
30017
29932
|
meta: {
|
|
30018
29933
|
description: "Require style rules to be inside @layer when the file defines layers.",
|
|
30019
29934
|
fixable: false,
|
|
@@ -30032,7 +29947,7 @@ var layerRequirementForComponentRules = defineCSSRule({
|
|
|
30032
29947
|
rule.startColumn,
|
|
30033
29948
|
layerRequirementForComponentRules,
|
|
30034
29949
|
"missingLayer",
|
|
30035
|
-
resolveMessage(
|
|
29950
|
+
resolveMessage(messages130.missingLayer, {
|
|
30036
29951
|
selector: rule.selectorText
|
|
30037
29952
|
})
|
|
30038
29953
|
);
|
|
@@ -30072,7 +29987,6 @@ var rules2 = [
|
|
|
30072
29987
|
selectorMaxAttributeAndUniversal,
|
|
30073
29988
|
selectorMaxSpecificity,
|
|
30074
29989
|
cssPolicyTypography,
|
|
30075
|
-
cssPolicyTouchTarget,
|
|
30076
29990
|
cssPolicySpacing,
|
|
30077
29991
|
cssPolicyContrast
|
|
30078
29992
|
];
|
|
@@ -31012,6 +30926,9 @@ function readBaselineOffsetFacts(graph, node) {
|
|
|
31012
30926
|
function readElementRef(graph, node) {
|
|
31013
30927
|
return readElementRefById(graph, node.solidFile, node.elementId);
|
|
31014
30928
|
}
|
|
30929
|
+
function readHostElementRef(graph, node) {
|
|
30930
|
+
return graph.hostElementRefsByNode.get(node) ?? null;
|
|
30931
|
+
}
|
|
31015
30932
|
function readElementRefById(graph, solidFile, elementId) {
|
|
31016
30933
|
const refs = graph.elementRefsBySolidFileAndId.get(solidFile);
|
|
31017
30934
|
if (!refs) return null;
|
|
@@ -32077,7 +31994,7 @@ function publishLayoutPerfStatsForTest(stats) {
|
|
|
32077
31994
|
}
|
|
32078
31995
|
function maybeLogLayoutPerf(stats, log) {
|
|
32079
31996
|
if (process.env["SOLID_LINT_LAYOUT_PROFILE"] !== "1") return;
|
|
32080
|
-
if (!log || !log.
|
|
31997
|
+
if (!log || !log.isLevelEnabled(Level.Debug)) return;
|
|
32081
31998
|
const view = snapshotLayoutPerfStats(stats);
|
|
32082
31999
|
log.debug(
|
|
32083
32000
|
`[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}`
|
|
@@ -32142,17 +32059,17 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32142
32059
|
if (cached !== void 0) return cached;
|
|
32143
32060
|
const binding = resolveTagBinding(normalizedFile, tag);
|
|
32144
32061
|
if (binding === null) {
|
|
32145
|
-
if (logger.
|
|
32062
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): binding=null`);
|
|
32146
32063
|
hostByTagCache.set(cacheKey, null);
|
|
32147
32064
|
return null;
|
|
32148
32065
|
}
|
|
32149
32066
|
if (binding.kind === "component") {
|
|
32150
|
-
if (logger.
|
|
32067
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): component, tagName=${binding.host.descriptor.tagName}, attrs=[${[...binding.host.descriptor.staticAttributes.keys()]}]`);
|
|
32151
32068
|
hostByTagCache.set(cacheKey, binding.host);
|
|
32152
32069
|
return binding.host;
|
|
32153
32070
|
}
|
|
32154
32071
|
const host = binding.base ? binding.base.host : null;
|
|
32155
|
-
if (logger.
|
|
32072
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveHost(${tag}): namespace, base=${host?.descriptor.tagName ?? "null"}`);
|
|
32156
32073
|
hostByTagCache.set(cacheKey, host);
|
|
32157
32074
|
return host;
|
|
32158
32075
|
},
|
|
@@ -32165,26 +32082,26 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32165
32082
|
}
|
|
32166
32083
|
};
|
|
32167
32084
|
function resolveComponentHostEntry(entry) {
|
|
32168
|
-
if (entry.resolution === "resolved")
|
|
32169
|
-
|
|
32085
|
+
if (entry.resolution === "resolved") {
|
|
32086
|
+
return { descriptor: entry.descriptor, hostElementRef: entry.hostElementRef };
|
|
32087
|
+
}
|
|
32088
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveComponentHostEntry: deferred innerTag=${entry.innerTag}, file=${entry.filePath}, attrs=[${[...entry.staticAttributes.keys()]}]`);
|
|
32170
32089
|
const innerBinding = resolveLocalIdentifierBinding(entry.filePath, entry.innerTag);
|
|
32171
|
-
if (logger.
|
|
32090
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] innerBinding=${innerBinding === null ? "null" : innerBinding.kind}`);
|
|
32172
32091
|
const innerHost = extractHostFromBinding(innerBinding);
|
|
32173
|
-
if (logger.
|
|
32174
|
-
let tagName = innerHost !== null ? innerHost.tagName : null;
|
|
32092
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] innerHost=${innerHost === null ? "null" : `tagName=${innerHost.descriptor.tagName}, attrs=[${[...innerHost.descriptor.staticAttributes.keys()]}]`}`);
|
|
32093
|
+
let tagName = innerHost !== null ? innerHost.descriptor.tagName : null;
|
|
32175
32094
|
if (tagName === null) {
|
|
32176
32095
|
tagName = resolveTagNameFromPolymorphicProp(entry.staticAttributes);
|
|
32177
|
-
if (logger.
|
|
32096
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] polymorphic fallback: tagName=${tagName}`);
|
|
32178
32097
|
}
|
|
32179
|
-
const staticAttributes = innerHost !== null ? mergeStaticAttributes(entry.staticAttributes, innerHost.staticAttributes) : entry.staticAttributes;
|
|
32180
|
-
const staticClassTokens = innerHost !== null ? mergeStaticClassTokens(entry.staticClassTokens, innerHost.staticClassTokens) : entry.staticClassTokens;
|
|
32181
|
-
const forwardsChildren = entry.forwardsChildren || innerHost !== null && innerHost.forwardsChildren;
|
|
32182
|
-
if (logger.
|
|
32098
|
+
const staticAttributes = innerHost !== null ? mergeStaticAttributes(entry.staticAttributes, innerHost.descriptor.staticAttributes) : entry.staticAttributes;
|
|
32099
|
+
const staticClassTokens = innerHost !== null ? mergeStaticClassTokens(entry.staticClassTokens, innerHost.descriptor.staticClassTokens) : entry.staticClassTokens;
|
|
32100
|
+
const forwardsChildren = entry.forwardsChildren || innerHost !== null && innerHost.descriptor.forwardsChildren;
|
|
32101
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolved: tagName=${tagName}, attrs=[${[...staticAttributes.keys()]}], classes=[${staticClassTokens}]`);
|
|
32183
32102
|
return {
|
|
32184
|
-
tagName,
|
|
32185
|
-
|
|
32186
|
-
staticClassTokens,
|
|
32187
|
-
forwardsChildren
|
|
32103
|
+
descriptor: { tagName, staticAttributes, staticClassTokens, forwardsChildren },
|
|
32104
|
+
hostElementRef: innerHost?.hostElementRef ?? null
|
|
32188
32105
|
};
|
|
32189
32106
|
}
|
|
32190
32107
|
function extractHostFromBinding(binding) {
|
|
@@ -32225,10 +32142,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32225
32142
|
if (hostEntry) {
|
|
32226
32143
|
const resolved = resolveComponentHostEntry(hostEntry);
|
|
32227
32144
|
if (resolved !== null) {
|
|
32228
|
-
const binding = {
|
|
32229
|
-
kind: "component",
|
|
32230
|
-
host: resolved
|
|
32231
|
-
};
|
|
32145
|
+
const binding = { kind: "component", host: resolved };
|
|
32232
32146
|
localBindingCache.set(key, binding);
|
|
32233
32147
|
resolvingLocal.delete(key);
|
|
32234
32148
|
return binding;
|
|
@@ -32289,7 +32203,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32289
32203
|
const baseExpression = toExpressionArgument(firstArg);
|
|
32290
32204
|
if (baseExpression === null) return null;
|
|
32291
32205
|
const baseBinding = resolveBindingFromExpression(filePath, baseExpression);
|
|
32292
|
-
if (logger.
|
|
32206
|
+
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}` : ""}`);
|
|
32293
32207
|
let baseComponent = null;
|
|
32294
32208
|
const members = /* @__PURE__ */ new Map();
|
|
32295
32209
|
if (baseBinding && baseBinding.kind === "component") {
|
|
@@ -32315,7 +32229,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32315
32229
|
if (!import_typescript125.default.isObjectLiteralExpression(argument)) continue;
|
|
32316
32230
|
appendObjectExpressionMembers(filePath, argument, members);
|
|
32317
32231
|
}
|
|
32318
|
-
if (logger.
|
|
32232
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] Object.assign result: base=${baseComponent === null ? "null" : `tagName=${baseComponent.host.descriptor.tagName}`}, members=[${[...members.keys()]}]`);
|
|
32319
32233
|
if (baseComponent === null && members.size === 0) return null;
|
|
32320
32234
|
return {
|
|
32321
32235
|
kind: "namespace",
|
|
@@ -32357,7 +32271,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32357
32271
|
}
|
|
32358
32272
|
function resolveBindingFromImport(filePath, importBinding) {
|
|
32359
32273
|
const resolvedModule = moduleResolver.resolveSolid(filePath, importBinding.source) ?? resolveAndIndexExternalModule(filePath, importBinding.source);
|
|
32360
|
-
if (logger.
|
|
32274
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] resolveBindingFromImport: source=${importBinding.source}, kind=${importBinding.kind}, resolvedModule=${resolvedModule}`);
|
|
32361
32275
|
if (resolvedModule === null) return null;
|
|
32362
32276
|
const normalized = (0, import_node_path3.resolve)(resolvedModule);
|
|
32363
32277
|
if (importBinding.kind === "namespace") {
|
|
@@ -32366,7 +32280,7 @@ function createLayoutComponentHostResolver(solids, moduleResolver, logger = noop
|
|
|
32366
32280
|
const exportName = importBinding.kind === "default" ? "default" : importBinding.importedName;
|
|
32367
32281
|
if (exportName === null) return null;
|
|
32368
32282
|
const result = resolveExportBinding(normalized, exportName);
|
|
32369
|
-
if (logger.
|
|
32283
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[component-host] export ${exportName}: ${result === null ? "null" : result.kind}`);
|
|
32370
32284
|
return result;
|
|
32371
32285
|
}
|
|
32372
32286
|
function resolveAndIndexExternalModule(importerFile, importSource) {
|
|
@@ -32560,6 +32474,7 @@ function collectComponentHosts(graph) {
|
|
|
32560
32474
|
}
|
|
32561
32475
|
function resolveComponentHostEntryForFunction(graph, fn) {
|
|
32562
32476
|
let entry = null;
|
|
32477
|
+
let hostElementRefAgreed = true;
|
|
32563
32478
|
const bodyEntry = resolveHostEntryFromFunctionBody(graph, fn);
|
|
32564
32479
|
if (bodyEntry !== null) {
|
|
32565
32480
|
entry = bodyEntry;
|
|
@@ -32575,9 +32490,17 @@ function resolveComponentHostEntryForFunction(graph, fn) {
|
|
|
32575
32490
|
entry = returnEntry;
|
|
32576
32491
|
continue;
|
|
32577
32492
|
}
|
|
32578
|
-
if (areComponentHostEntriesEqual(entry, returnEntry))
|
|
32493
|
+
if (areComponentHostEntriesEqual(entry, returnEntry)) {
|
|
32494
|
+
if (hostElementRefAgreed && entry.resolution === "resolved" && returnEntry.resolution === "resolved" && entry.hostElementRef !== returnEntry.hostElementRef) {
|
|
32495
|
+
hostElementRefAgreed = false;
|
|
32496
|
+
}
|
|
32497
|
+
continue;
|
|
32498
|
+
}
|
|
32579
32499
|
return null;
|
|
32580
32500
|
}
|
|
32501
|
+
if (!hostElementRefAgreed && entry !== null && entry.resolution === "resolved") {
|
|
32502
|
+
return { resolution: "resolved", descriptor: entry.descriptor, hostElementRef: null };
|
|
32503
|
+
}
|
|
32581
32504
|
return entry;
|
|
32582
32505
|
}
|
|
32583
32506
|
function resolveHostEntryFromFunctionBody(graph, fn) {
|
|
@@ -32605,7 +32528,8 @@ function resolveHostEntryFromJSXElement(graph, node) {
|
|
|
32605
32528
|
staticAttributes: collectStaticAttributes(element),
|
|
32606
32529
|
staticClassTokens: getStaticClassTokensForElementEntity(graph, element),
|
|
32607
32530
|
forwardsChildren: detectChildrenForwarding(element)
|
|
32608
|
-
}
|
|
32531
|
+
},
|
|
32532
|
+
hostElementRef: { solid: graph, element }
|
|
32609
32533
|
};
|
|
32610
32534
|
}
|
|
32611
32535
|
if (isContextProviderTag(element.tag)) {
|
|
@@ -33315,7 +33239,7 @@ function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
|
|
|
33315
33239
|
ancestor = ancestor.parentElementNode;
|
|
33316
33240
|
}
|
|
33317
33241
|
if (fileRootElements !== null) {
|
|
33318
|
-
if (logger.
|
|
33242
|
+
if (logger.isLevelEnabled(Level.Trace)) {
|
|
33319
33243
|
const compoundDesc = describeCompound(targetCompound);
|
|
33320
33244
|
logger.trace(`[selector-match] fallback: node=${node.key} tag=${node.tagName} checking ${fileRootElements.length} roots for compound=${compoundDesc}`);
|
|
33321
33245
|
}
|
|
@@ -33326,11 +33250,11 @@ function matchesChain(matcher, node, index, perf, fileRootElements, logger) {
|
|
|
33326
33250
|
if (root.solidFile !== node.solidFile) continue;
|
|
33327
33251
|
perf.ancestryChecks++;
|
|
33328
33252
|
const compoundResult = matchesCompound(root, targetCompound);
|
|
33329
|
-
if (logger.
|
|
33253
|
+
if (logger.isLevelEnabled(Level.Trace) && compoundResult === "no-match") {
|
|
33330
33254
|
logger.trace(`[selector-match] fallback MISS: root=${root.key} tag=${root.tagName} attrs=[${[...root.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}]`);
|
|
33331
33255
|
}
|
|
33332
33256
|
if (compoundResult !== "no-match") {
|
|
33333
|
-
if (logger.
|
|
33257
|
+
if (logger.isLevelEnabled(Level.Debug)) {
|
|
33334
33258
|
const compoundDesc = describeCompound(targetCompound);
|
|
33335
33259
|
logger.debug(`[selector-match] fallback HIT: node=${node.key} tag=${node.tagName} matched root=${root.key} tag=${root.tagName} compound=${compoundDesc} isFinal=${isFinal}`);
|
|
33336
33260
|
}
|
|
@@ -36532,7 +36456,7 @@ function appendMatchingEdgesFromSelectorIds(ctx, selectorIds, node, applies, app
|
|
|
36532
36456
|
};
|
|
36533
36457
|
applies.push(edge);
|
|
36534
36458
|
ctx.perf.matchEdgesCreated++;
|
|
36535
|
-
if (ctx.logger.
|
|
36459
|
+
if (ctx.logger.isLevelEnabled(Level.Trace)) {
|
|
36536
36460
|
ctx.logger.trace(
|
|
36537
36461
|
`[cascade] edge node=${node.key} selector=${selector.id} match=${matchResult} conditional=${edge.conditionalMatch} selector-raw=${selector.raw.slice(0, 80)}`
|
|
36538
36462
|
);
|
|
@@ -36975,7 +36899,7 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
36975
36899
|
if (!child) continue;
|
|
36976
36900
|
if (child.kind === "expression") {
|
|
36977
36901
|
if (isStructuralExpression(child.node)) {
|
|
36978
|
-
if (logger.
|
|
36902
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (structural expression child)`);
|
|
36979
36903
|
memo.set(element.id, 2 /* Unknown */);
|
|
36980
36904
|
return 2 /* Unknown */;
|
|
36981
36905
|
}
|
|
@@ -36997,11 +36921,11 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
36997
36921
|
if (!child.isDomElement) {
|
|
36998
36922
|
const childMeta = compositionMetaByElementId.get(child.id);
|
|
36999
36923
|
if (childMeta !== void 0 && isControlTag(childMeta.tagName)) {
|
|
37000
|
-
if (logger.
|
|
36924
|
+
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`);
|
|
37001
36925
|
continue;
|
|
37002
36926
|
}
|
|
37003
36927
|
if (childState !== 1 /* No */) {
|
|
37004
|
-
if (logger.
|
|
36928
|
+
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`);
|
|
37005
36929
|
childHasUnknown = true;
|
|
37006
36930
|
}
|
|
37007
36931
|
continue;
|
|
@@ -37014,12 +36938,12 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
37014
36938
|
if (childState === 3 /* DynamicText */) childHasDynamicText = true;
|
|
37015
36939
|
}
|
|
37016
36940
|
if (childHasUnknown) {
|
|
37017
|
-
if (logger.
|
|
36941
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (child has unknown)`);
|
|
37018
36942
|
memo.set(element.id, 2 /* Unknown */);
|
|
37019
36943
|
return 2 /* Unknown */;
|
|
37020
36944
|
}
|
|
37021
36945
|
if (hasTextOnlyExpression || childHasDynamicText) {
|
|
37022
|
-
if (logger.
|
|
36946
|
+
if (logger.isLevelEnabled(Level.Trace)) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 dynamic-text`);
|
|
37023
36947
|
memo.set(element.id, 3 /* DynamicText */);
|
|
37024
36948
|
return 3 /* DynamicText */;
|
|
37025
36949
|
}
|
|
@@ -37041,15 +36965,16 @@ function collectLayoutElementRecordsForSolid(solid, selectorRequirements, inline
|
|
|
37041
36965
|
const meta = compositionMetaByElementId.get(element.id);
|
|
37042
36966
|
if (!meta || !meta.participates) continue;
|
|
37043
36967
|
const localClassTokens = selectorRequirements.needsClassTokens ? getStaticClassTokensForElementEntity(solid, element) : EMPTY_STRING_LIST3;
|
|
37044
|
-
const classTokens = mergeClassTokens(localClassTokens, meta.
|
|
36968
|
+
const classTokens = mergeClassTokens(localClassTokens, meta.resolvedHost?.descriptor.staticClassTokens);
|
|
37045
36969
|
const classTokenSet = classTokens.length === 0 ? EMPTY_CLASS_TOKEN_SET : createClassTokenSet(classTokens);
|
|
37046
36970
|
const inlineStyleKeys = getStaticStyleKeysForElement(solid, element.id);
|
|
37047
36971
|
const localAttributes = selectorRequirements.needsAttributes ? collectStaticAttributes(element) : EMPTY_ATTRIBUTES2;
|
|
37048
|
-
const attributes = mergeAttributes(localAttributes, meta.
|
|
36972
|
+
const attributes = mergeAttributes(localAttributes, meta.resolvedHost?.descriptor.staticAttributes);
|
|
37049
36973
|
const selectorDispatchKeys = buildSelectorDispatchKeys(attributes, classTokens);
|
|
37050
36974
|
const inlineStyleValues = inlineStyleValuesByElementId.get(element.id) ?? EMPTY_INLINE_STYLE_VALUES;
|
|
37051
36975
|
const textualContent = getTextualContentState(element, textContentMemo, compositionMetaByElementId, logger);
|
|
37052
36976
|
const parentElementId = resolveComposedParentElementId(element, compositionMetaByElementId);
|
|
36977
|
+
const hostElementRef = meta.resolvedHost?.hostElementRef ?? null;
|
|
37053
36978
|
out.push({
|
|
37054
36979
|
element,
|
|
37055
36980
|
key: toLayoutElementKey(solid.file, element.id),
|
|
@@ -37062,7 +36987,8 @@ function collectLayoutElementRecordsForSolid(solid, selectorRequirements, inline
|
|
|
37062
36987
|
selectorDispatchKeys,
|
|
37063
36988
|
inlineStyleValues,
|
|
37064
36989
|
textualContent,
|
|
37065
|
-
parentElementId
|
|
36990
|
+
parentElementId,
|
|
36991
|
+
hostElementRef
|
|
37066
36992
|
});
|
|
37067
36993
|
}
|
|
37068
36994
|
return out;
|
|
@@ -37072,7 +36998,7 @@ function collectCompositionMetaByElementId(solid, componentHostResolver) {
|
|
|
37072
36998
|
for (let i = 0; i < solid.jsxElements.length; i++) {
|
|
37073
36999
|
const element = solid.jsxElements[i];
|
|
37074
37000
|
if (!element) continue;
|
|
37075
|
-
const
|
|
37001
|
+
const resolvedHost = resolveHostForElement(
|
|
37076
37002
|
componentHostResolver,
|
|
37077
37003
|
solid.file,
|
|
37078
37004
|
element
|
|
@@ -37081,30 +37007,30 @@ function collectCompositionMetaByElementId(solid, componentHostResolver) {
|
|
|
37081
37007
|
componentHostResolver,
|
|
37082
37008
|
solid.file,
|
|
37083
37009
|
element,
|
|
37084
|
-
|
|
37010
|
+
resolvedHost
|
|
37085
37011
|
);
|
|
37086
37012
|
const participates = element.tag !== null && !isTransparentPrimitive;
|
|
37087
|
-
const tag = resolveEffectiveTag(element,
|
|
37013
|
+
const tag = resolveEffectiveTag(element, resolvedHost?.descriptor ?? null);
|
|
37088
37014
|
const tagName = tag ? tag.toLowerCase() : null;
|
|
37089
37015
|
out.set(element.id, {
|
|
37090
37016
|
element,
|
|
37091
37017
|
participates,
|
|
37092
37018
|
tag,
|
|
37093
37019
|
tagName,
|
|
37094
|
-
|
|
37020
|
+
resolvedHost
|
|
37095
37021
|
});
|
|
37096
37022
|
}
|
|
37097
37023
|
return out;
|
|
37098
37024
|
}
|
|
37099
|
-
function
|
|
37025
|
+
function resolveHostForElement(componentHostResolver, solidFile, element) {
|
|
37100
37026
|
if (element.tag === null) return null;
|
|
37101
37027
|
if (element.isDomElement) return null;
|
|
37102
37028
|
return componentHostResolver.resolveHost(solidFile, element.tag);
|
|
37103
37029
|
}
|
|
37104
|
-
function resolveTransparentPrimitiveStatus(componentHostResolver, solidFile, element,
|
|
37030
|
+
function resolveTransparentPrimitiveStatus(componentHostResolver, solidFile, element, resolvedHost) {
|
|
37105
37031
|
if (element.tag === null) return false;
|
|
37106
37032
|
if (element.isDomElement) return false;
|
|
37107
|
-
if (
|
|
37033
|
+
if (resolvedHost !== null) return false;
|
|
37108
37034
|
return componentHostResolver.isTransparentPrimitive(solidFile, element.tag);
|
|
37109
37035
|
}
|
|
37110
37036
|
function resolveEffectiveTag(element, hostDescriptor) {
|
|
@@ -37222,6 +37148,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37222
37148
|
const childrenByParentNodeMutable = /* @__PURE__ */ new Map();
|
|
37223
37149
|
const elementBySolidFileAndIdMutable = /* @__PURE__ */ new Map();
|
|
37224
37150
|
const elementRefsBySolidFileAndIdMutable = /* @__PURE__ */ new Map();
|
|
37151
|
+
const hostElementRefsByNodeMutable = /* @__PURE__ */ new Map();
|
|
37225
37152
|
const appliesByElementNodeMutable = /* @__PURE__ */ new Map();
|
|
37226
37153
|
const selectorsById = /* @__PURE__ */ new Map();
|
|
37227
37154
|
const monitoredDeclarationsBySelectorId = /* @__PURE__ */ new Map();
|
|
@@ -37258,7 +37185,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37258
37185
|
const moduleResolver = createLayoutModuleResolver(solids, css);
|
|
37259
37186
|
const componentHostResolver = createLayoutComponentHostResolver(solids, moduleResolver, logger);
|
|
37260
37187
|
const cssScopeBySolidFile = collectCSSScopeBySolidFile(solids, css, moduleResolver);
|
|
37261
|
-
if (logger.
|
|
37188
|
+
if (logger.isLevelEnabled(Level.Trace)) {
|
|
37262
37189
|
for (const [solidFile, scopePaths] of cssScopeBySolidFile) {
|
|
37263
37190
|
if (scopePaths.length > 0) {
|
|
37264
37191
|
let names = "";
|
|
@@ -37353,6 +37280,9 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37353
37280
|
isControl: isControlTag(record.tagName),
|
|
37354
37281
|
isReplaced: isReplacedTag(record.tagName)
|
|
37355
37282
|
};
|
|
37283
|
+
if (record.hostElementRef !== null) {
|
|
37284
|
+
hostElementRefsByNodeMutable.set(node, record.hostElementRef);
|
|
37285
|
+
}
|
|
37356
37286
|
elements.push(node);
|
|
37357
37287
|
elementById.set(record.element.id, node);
|
|
37358
37288
|
nodeByElementId.set(record.element.id, node);
|
|
@@ -37374,7 +37304,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37374
37304
|
}
|
|
37375
37305
|
}
|
|
37376
37306
|
}
|
|
37377
|
-
if (logger.
|
|
37307
|
+
if (logger.isLevelEnabled(Level.Debug)) {
|
|
37378
37308
|
for (const [file, roots] of rootElementsByFile) {
|
|
37379
37309
|
const descs = roots.map((r) => `${r.key}(tag=${r.tagName}, attrs=[${[...r.attributes.entries()].map(([k, v]) => `${k}=${v}`).join(",")}])`);
|
|
37380
37310
|
logger.debug(`[build] rootElementsByFile file=${file} count=${roots.length}: ${descs.join(", ")}`);
|
|
@@ -37417,7 +37347,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37417
37347
|
appliesByNode.set(node, edges);
|
|
37418
37348
|
}
|
|
37419
37349
|
perf.cascadeBuildMs = performance.now() - cascadeStartedAt;
|
|
37420
|
-
if (logger.
|
|
37350
|
+
if (logger.isLevelEnabled(Level.Trace)) {
|
|
37421
37351
|
for (let i = 0; i < elements.length; i++) {
|
|
37422
37352
|
const node = elements[i];
|
|
37423
37353
|
if (!node) continue;
|
|
@@ -37473,6 +37403,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37473
37403
|
childrenByParentNode: childrenByParentNodeMutable,
|
|
37474
37404
|
elementBySolidFileAndId: elementBySolidFileAndIdMutable,
|
|
37475
37405
|
elementRefsBySolidFileAndId: elementRefsBySolidFileAndIdMutable,
|
|
37406
|
+
hostElementRefsByNode: hostElementRefsByNodeMutable,
|
|
37476
37407
|
appliesByNode,
|
|
37477
37408
|
selectorCandidatesByNode,
|
|
37478
37409
|
selectorsById,
|
|
@@ -37873,7 +37804,7 @@ function computeFlowParticipationFact(snapshot) {
|
|
|
37873
37804
|
}
|
|
37874
37805
|
function buildContextIndex(childrenByParentNode, snapshotByElementNode, perf, logger) {
|
|
37875
37806
|
const out = /* @__PURE__ */ new Map();
|
|
37876
|
-
const trace = logger.
|
|
37807
|
+
const trace = logger.isLevelEnabled(Level.Trace);
|
|
37877
37808
|
for (const [parent, children] of childrenByParentNode) {
|
|
37878
37809
|
if (children.length < 2) continue;
|
|
37879
37810
|
const snapshot = snapshotByElementNode.get(parent);
|
|
@@ -38692,7 +38623,7 @@ function runLayoutDetector(context, detector) {
|
|
|
38692
38623
|
result.evidence.posteriorLower,
|
|
38693
38624
|
result.evidence.posteriorUpper
|
|
38694
38625
|
);
|
|
38695
|
-
if (log.
|
|
38626
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
38696
38627
|
log.debug(
|
|
38697
38628
|
`[${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("; ")}]`
|
|
38698
38629
|
);
|
|
@@ -38701,7 +38632,7 @@ function runLayoutDetector(context, detector) {
|
|
|
38701
38632
|
continue;
|
|
38702
38633
|
}
|
|
38703
38634
|
recordPolicyMetrics(context, result.evidenceMass, result.posteriorLower, result.posteriorUpper);
|
|
38704
|
-
if (log.
|
|
38635
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
38705
38636
|
log.debug(
|
|
38706
38637
|
`[${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)}`
|
|
38707
38638
|
);
|
|
@@ -38892,13 +38823,13 @@ function emitLayoutDiagnostic(layout, node, emit, ruleId, messageId, template, s
|
|
|
38892
38823
|
}
|
|
38893
38824
|
|
|
38894
38825
|
// src/cross-file/rules/undefined-css-class.ts
|
|
38895
|
-
var
|
|
38826
|
+
var messages131 = {
|
|
38896
38827
|
undefinedClass: "CSS class '{{className}}' is not defined in project CSS files"
|
|
38897
38828
|
};
|
|
38898
38829
|
var jsxNoUndefinedCssClass = defineCrossRule({
|
|
38899
38830
|
id: "jsx-no-undefined-css-class",
|
|
38900
38831
|
severity: "error",
|
|
38901
|
-
messages:
|
|
38832
|
+
messages: messages131,
|
|
38902
38833
|
meta: {
|
|
38903
38834
|
description: "Detect undefined CSS class names in JSX",
|
|
38904
38835
|
fixable: false,
|
|
@@ -38917,7 +38848,7 @@ var jsxNoUndefinedCssClass = defineCrossRule({
|
|
|
38917
38848
|
ref.solid.sourceFile,
|
|
38918
38849
|
jsxNoUndefinedCssClass.id,
|
|
38919
38850
|
"undefinedClass",
|
|
38920
|
-
resolveMessage(
|
|
38851
|
+
resolveMessage(messages131.undefinedClass, { className: item.className }),
|
|
38921
38852
|
"error"
|
|
38922
38853
|
));
|
|
38923
38854
|
}
|
|
@@ -38925,13 +38856,13 @@ var jsxNoUndefinedCssClass = defineCrossRule({
|
|
|
38925
38856
|
});
|
|
38926
38857
|
|
|
38927
38858
|
// src/cross-file/rules/unreferenced-css-class.ts
|
|
38928
|
-
var
|
|
38859
|
+
var messages132 = {
|
|
38929
38860
|
unreferencedClass: "CSS class '{{className}}' is defined but not referenced by static JSX class attributes"
|
|
38930
38861
|
};
|
|
38931
38862
|
var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
38932
38863
|
id: "css-no-unreferenced-component-class",
|
|
38933
38864
|
severity: "warn",
|
|
38934
|
-
messages:
|
|
38865
|
+
messages: messages132,
|
|
38935
38866
|
meta: {
|
|
38936
38867
|
description: "Detect CSS classes that are never referenced by static JSX class attributes.",
|
|
38937
38868
|
fixable: false,
|
|
@@ -38955,7 +38886,7 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
|
38955
38886
|
},
|
|
38956
38887
|
cssNoUnreferencedComponentClass.id,
|
|
38957
38888
|
"unreferencedClass",
|
|
38958
|
-
resolveMessage(
|
|
38889
|
+
resolveMessage(messages132.unreferencedClass, { className }),
|
|
38959
38890
|
"warn"
|
|
38960
38891
|
)
|
|
38961
38892
|
);
|
|
@@ -38964,13 +38895,13 @@ var cssNoUnreferencedComponentClass = defineCrossRule({
|
|
|
38964
38895
|
});
|
|
38965
38896
|
|
|
38966
38897
|
// src/cross-file/rules/jsx-no-duplicate-class-token-class-classlist.ts
|
|
38967
|
-
var
|
|
38898
|
+
var messages133 = {
|
|
38968
38899
|
duplicateClassToken: "Class token `{{name}}` appears in both class and classList."
|
|
38969
38900
|
};
|
|
38970
38901
|
var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
38971
38902
|
id: "jsx-no-duplicate-class-token-class-classlist",
|
|
38972
38903
|
severity: "warn",
|
|
38973
|
-
messages:
|
|
38904
|
+
messages: messages133,
|
|
38974
38905
|
meta: {
|
|
38975
38906
|
description: "Disallow duplicate class tokens between class and classList on the same JSX element.",
|
|
38976
38907
|
fixable: false,
|
|
@@ -39012,7 +38943,7 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
|
39012
38943
|
solid.sourceFile,
|
|
39013
38944
|
jsxNoDuplicateClassTokenClassClasslist.id,
|
|
39014
38945
|
"duplicateClassToken",
|
|
39015
|
-
resolveMessage(
|
|
38946
|
+
resolveMessage(messages133.duplicateClassToken, { name: token }),
|
|
39016
38947
|
"warn"
|
|
39017
38948
|
));
|
|
39018
38949
|
}
|
|
@@ -39023,13 +38954,13 @@ var jsxNoDuplicateClassTokenClassClasslist = defineCrossRule({
|
|
|
39023
38954
|
|
|
39024
38955
|
// src/cross-file/rules/jsx-classlist-static-keys.ts
|
|
39025
38956
|
var import_typescript128 = __toESM(require("typescript"), 1);
|
|
39026
|
-
var
|
|
38957
|
+
var messages134 = {
|
|
39027
38958
|
nonStaticKey: "classList key must be statically known for reliable class mapping."
|
|
39028
38959
|
};
|
|
39029
38960
|
var jsxClasslistStaticKeys = defineCrossRule({
|
|
39030
38961
|
id: "jsx-classlist-static-keys",
|
|
39031
38962
|
severity: "error",
|
|
39032
|
-
messages:
|
|
38963
|
+
messages: messages134,
|
|
39033
38964
|
meta: {
|
|
39034
38965
|
description: "Require classList keys to be static and non-computed.",
|
|
39035
38966
|
fixable: false,
|
|
@@ -39040,26 +38971,26 @@ var jsxClasslistStaticKeys = defineCrossRule({
|
|
|
39040
38971
|
forEachClassListPropertyAcross(solids, (solid, p) => {
|
|
39041
38972
|
if (import_typescript128.default.isSpreadAssignment(p)) return;
|
|
39042
38973
|
if (!import_typescript128.default.isPropertyAssignment(p)) {
|
|
39043
|
-
emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(
|
|
38974
|
+
emit(createDiagnostic(solid.file, p, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
|
|
39044
38975
|
return;
|
|
39045
38976
|
}
|
|
39046
38977
|
if (import_typescript128.default.isComputedPropertyName(p.name)) return;
|
|
39047
38978
|
if (import_typescript128.default.isIdentifier(p.name)) return;
|
|
39048
38979
|
if (import_typescript128.default.isStringLiteral(p.name)) return;
|
|
39049
|
-
emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(
|
|
38980
|
+
emit(createDiagnostic(solid.file, p.name, solid.sourceFile, jsxClasslistStaticKeys.id, "nonStaticKey", resolveMessage(messages134.nonStaticKey), "error"));
|
|
39050
38981
|
});
|
|
39051
38982
|
}
|
|
39052
38983
|
});
|
|
39053
38984
|
|
|
39054
38985
|
// src/cross-file/rules/jsx-classlist-no-constant-literals.ts
|
|
39055
38986
|
var import_typescript129 = __toESM(require("typescript"), 1);
|
|
39056
|
-
var
|
|
38987
|
+
var messages135 = {
|
|
39057
38988
|
constantEntry: "classList entry `{{name}}: {{value}}` is constant; move it to static class."
|
|
39058
38989
|
};
|
|
39059
38990
|
var jsxClasslistNoConstantLiterals = defineCrossRule({
|
|
39060
38991
|
id: "jsx-classlist-no-constant-literals",
|
|
39061
38992
|
severity: "warn",
|
|
39062
|
-
messages:
|
|
38993
|
+
messages: messages135,
|
|
39063
38994
|
meta: {
|
|
39064
38995
|
description: "Disallow classList entries with constant true/false values.",
|
|
39065
38996
|
fixable: false,
|
|
@@ -39079,7 +39010,7 @@ var jsxClasslistNoConstantLiterals = defineCrossRule({
|
|
|
39079
39010
|
solid.sourceFile,
|
|
39080
39011
|
jsxClasslistNoConstantLiterals.id,
|
|
39081
39012
|
"constantEntry",
|
|
39082
|
-
resolveMessage(
|
|
39013
|
+
resolveMessage(messages135.constantEntry, { name: n, value: val.kind === import_typescript129.default.SyntaxKind.TrueKeyword ? "true" : "false" }),
|
|
39083
39014
|
"warn"
|
|
39084
39015
|
));
|
|
39085
39016
|
});
|
|
@@ -39114,13 +39045,13 @@ function isDefinitelyNonBooleanType(solid, node) {
|
|
|
39114
39045
|
}
|
|
39115
39046
|
|
|
39116
39047
|
// src/cross-file/rules/jsx-classlist-boolean-values.ts
|
|
39117
|
-
var
|
|
39048
|
+
var messages136 = {
|
|
39118
39049
|
nonBooleanValue: "classList value for `{{name}}` must be boolean."
|
|
39119
39050
|
};
|
|
39120
39051
|
var jsxClasslistBooleanValues = defineCrossRule({
|
|
39121
39052
|
id: "jsx-classlist-boolean-values",
|
|
39122
39053
|
severity: "error",
|
|
39123
|
-
messages:
|
|
39054
|
+
messages: messages136,
|
|
39124
39055
|
meta: {
|
|
39125
39056
|
description: "Require classList values to be boolean-like expressions.",
|
|
39126
39057
|
fixable: false,
|
|
@@ -39134,25 +39065,25 @@ var jsxClasslistBooleanValues = defineCrossRule({
|
|
|
39134
39065
|
if (!n) return;
|
|
39135
39066
|
if (isBooleanish(p.initializer)) return;
|
|
39136
39067
|
if (isDefinitelyNonBoolean(p.initializer)) {
|
|
39137
|
-
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(
|
|
39068
|
+
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
|
|
39138
39069
|
return;
|
|
39139
39070
|
}
|
|
39140
39071
|
if (isBooleanType(solid, p.initializer)) return;
|
|
39141
39072
|
if (!isDefinitelyNonBooleanType(solid, p.initializer)) return;
|
|
39142
|
-
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(
|
|
39073
|
+
emit(createDiagnostic(solid.file, p.initializer, solid.sourceFile, jsxClasslistBooleanValues.id, "nonBooleanValue", resolveMessage(messages136.nonBooleanValue, { name: n }), "error"));
|
|
39143
39074
|
});
|
|
39144
39075
|
}
|
|
39145
39076
|
});
|
|
39146
39077
|
|
|
39147
39078
|
// src/cross-file/rules/jsx-classlist-no-accessor-reference.ts
|
|
39148
39079
|
var import_typescript131 = __toESM(require("typescript"), 1);
|
|
39149
|
-
var
|
|
39080
|
+
var messages137 = {
|
|
39150
39081
|
accessorReference: "Signal accessor `{{name}}` must be called in classList value (use {{name}}())."
|
|
39151
39082
|
};
|
|
39152
39083
|
var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
39153
39084
|
id: "jsx-classlist-no-accessor-reference",
|
|
39154
39085
|
severity: "error",
|
|
39155
|
-
messages:
|
|
39086
|
+
messages: messages137,
|
|
39156
39087
|
meta: {
|
|
39157
39088
|
description: "Disallow passing accessor references directly as classList values.",
|
|
39158
39089
|
fixable: false,
|
|
@@ -39184,7 +39115,7 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
|
39184
39115
|
solid.sourceFile,
|
|
39185
39116
|
jsxClasslistNoAccessorReference.id,
|
|
39186
39117
|
"accessorReference",
|
|
39187
|
-
resolveMessage(
|
|
39118
|
+
resolveMessage(messages137.accessorReference, { name: v.text }),
|
|
39188
39119
|
"error"
|
|
39189
39120
|
));
|
|
39190
39121
|
});
|
|
@@ -39193,13 +39124,13 @@ var jsxClasslistNoAccessorReference = defineCrossRule({
|
|
|
39193
39124
|
|
|
39194
39125
|
// src/cross-file/rules/jsx-style-kebab-case-keys.ts
|
|
39195
39126
|
var import_typescript132 = __toESM(require("typescript"), 1);
|
|
39196
|
-
var
|
|
39127
|
+
var messages138 = {
|
|
39197
39128
|
kebabStyleKey: "Style key `{{name}}` should be `{{kebab}}` in Solid style objects."
|
|
39198
39129
|
};
|
|
39199
39130
|
var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
39200
39131
|
id: "jsx-style-kebab-case-keys",
|
|
39201
39132
|
severity: "error",
|
|
39202
|
-
messages:
|
|
39133
|
+
messages: messages138,
|
|
39203
39134
|
meta: {
|
|
39204
39135
|
description: "Require kebab-case keys in JSX style object literals.",
|
|
39205
39136
|
fixable: false,
|
|
@@ -39220,7 +39151,7 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
|
39220
39151
|
solid.sourceFile,
|
|
39221
39152
|
jsxStyleKebabCaseKeys.id,
|
|
39222
39153
|
"kebabStyleKey",
|
|
39223
|
-
resolveMessage(
|
|
39154
|
+
resolveMessage(messages138.kebabStyleKey, { name: n, kebab }),
|
|
39224
39155
|
"error"
|
|
39225
39156
|
));
|
|
39226
39157
|
});
|
|
@@ -39229,13 +39160,13 @@ var jsxStyleKebabCaseKeys = defineCrossRule({
|
|
|
39229
39160
|
|
|
39230
39161
|
// src/cross-file/rules/jsx-style-no-function-values.ts
|
|
39231
39162
|
var import_typescript133 = __toESM(require("typescript"), 1);
|
|
39232
|
-
var
|
|
39163
|
+
var messages139 = {
|
|
39233
39164
|
functionStyleValue: "Style value for `{{name}}` is a function; pass computed value instead."
|
|
39234
39165
|
};
|
|
39235
39166
|
var jsxStyleNoFunctionValues = defineCrossRule({
|
|
39236
39167
|
id: "jsx-style-no-function-values",
|
|
39237
39168
|
severity: "error",
|
|
39238
|
-
messages:
|
|
39169
|
+
messages: messages139,
|
|
39239
39170
|
meta: {
|
|
39240
39171
|
description: "Disallow function values in JSX style objects.",
|
|
39241
39172
|
fixable: false,
|
|
@@ -39249,11 +39180,11 @@ var jsxStyleNoFunctionValues = defineCrossRule({
|
|
|
39249
39180
|
if (!n) return;
|
|
39250
39181
|
const v = p.initializer;
|
|
39251
39182
|
if (import_typescript133.default.isArrowFunction(v) || import_typescript133.default.isFunctionExpression(v)) {
|
|
39252
|
-
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(
|
|
39183
|
+
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
|
|
39253
39184
|
return;
|
|
39254
39185
|
}
|
|
39255
39186
|
if (import_typescript133.default.isIdentifier(v) && solid.typeResolver.isCallableType(v)) {
|
|
39256
|
-
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(
|
|
39187
|
+
emit(createDiagnostic(solid.file, v, solid.sourceFile, jsxStyleNoFunctionValues.id, "functionStyleValue", resolveMessage(messages139.functionStyleValue, { name: n }), "error"));
|
|
39257
39188
|
}
|
|
39258
39189
|
});
|
|
39259
39190
|
}
|
|
@@ -39261,13 +39192,13 @@ var jsxStyleNoFunctionValues = defineCrossRule({
|
|
|
39261
39192
|
|
|
39262
39193
|
// src/cross-file/rules/jsx-style-no-unused-custom-prop.ts
|
|
39263
39194
|
var import_typescript134 = __toESM(require("typescript"), 1);
|
|
39264
|
-
var
|
|
39195
|
+
var messages140 = {
|
|
39265
39196
|
unusedInlineVar: "Inline custom property `{{name}}` is never read via var({{name}})."
|
|
39266
39197
|
};
|
|
39267
39198
|
var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
39268
39199
|
id: "jsx-style-no-unused-custom-prop",
|
|
39269
39200
|
severity: "warn",
|
|
39270
|
-
messages:
|
|
39201
|
+
messages: messages140,
|
|
39271
39202
|
meta: {
|
|
39272
39203
|
description: "Detect inline style custom properties that are never consumed by CSS var() references.",
|
|
39273
39204
|
fixable: false,
|
|
@@ -39308,7 +39239,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
|
39308
39239
|
solid.sourceFile,
|
|
39309
39240
|
jsxStyleNoUnusedCustomProp.id,
|
|
39310
39241
|
"unusedInlineVar",
|
|
39311
|
-
resolveMessage(
|
|
39242
|
+
resolveMessage(messages140.unusedInlineVar, { name: n }),
|
|
39312
39243
|
"warn"
|
|
39313
39244
|
));
|
|
39314
39245
|
}
|
|
@@ -39318,7 +39249,7 @@ var jsxStyleNoUnusedCustomProp = defineCrossRule({
|
|
|
39318
39249
|
|
|
39319
39250
|
// src/cross-file/rules/jsx-style-policy.ts
|
|
39320
39251
|
var import_typescript135 = __toESM(require("typescript"), 1);
|
|
39321
|
-
var
|
|
39252
|
+
var messages141 = {
|
|
39322
39253
|
fontTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for policy `{{policy}}`.",
|
|
39323
39254
|
lineHeightTooSmall: "Inline style `line-height: {{value}}` is below the minimum `{{min}}` for policy `{{policy}}`.",
|
|
39324
39255
|
heightTooSmall: "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`.",
|
|
@@ -39329,28 +39260,54 @@ var INLINE_TOUCH_TARGET_KEYS = /* @__PURE__ */ new Set([
|
|
|
39329
39260
|
"height",
|
|
39330
39261
|
"min-height",
|
|
39331
39262
|
"width",
|
|
39332
|
-
"min-width"
|
|
39333
|
-
"padding-left",
|
|
39334
|
-
"padding-right",
|
|
39335
|
-
"padding-inline",
|
|
39336
|
-
"padding-inline-start",
|
|
39337
|
-
"padding-inline-end"
|
|
39263
|
+
"min-width"
|
|
39338
39264
|
]);
|
|
39265
|
+
var INTERACTIVE_HTML_TAGS = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
|
|
39266
|
+
var INTERACTIVE_ARIA_ROLES = /* @__PURE__ */ new Set([
|
|
39267
|
+
"button",
|
|
39268
|
+
"link",
|
|
39269
|
+
"checkbox",
|
|
39270
|
+
"radio",
|
|
39271
|
+
"combobox",
|
|
39272
|
+
"listbox",
|
|
39273
|
+
"menuitem",
|
|
39274
|
+
"menuitemcheckbox",
|
|
39275
|
+
"menuitemradio",
|
|
39276
|
+
"option",
|
|
39277
|
+
"switch",
|
|
39278
|
+
"tab"
|
|
39279
|
+
]);
|
|
39280
|
+
function isInteractiveElement(solid, element, hostElementRef) {
|
|
39281
|
+
if (element.tagName !== null && INTERACTIVE_HTML_TAGS.has(element.tagName)) return true;
|
|
39282
|
+
const roleAttr = getJSXAttributeEntity(solid, element, "role");
|
|
39283
|
+
if (roleAttr !== null && roleAttr.valueNode !== null) {
|
|
39284
|
+
const role = getStaticStringFromJSXValue(roleAttr.valueNode);
|
|
39285
|
+
if (role !== null && INTERACTIVE_ARIA_ROLES.has(role)) return true;
|
|
39286
|
+
}
|
|
39287
|
+
if (hostElementRef !== null && hostElementRef.element.tagName !== null) {
|
|
39288
|
+
if (INTERACTIVE_HTML_TAGS.has(hostElementRef.element.tagName)) return true;
|
|
39289
|
+
}
|
|
39290
|
+
return false;
|
|
39291
|
+
}
|
|
39292
|
+
function readNodeHostElementRef(layout, solid, element) {
|
|
39293
|
+
const node = layout.elementBySolidFileAndId.get(solid.file)?.get(element.id) ?? null;
|
|
39294
|
+
return node !== null ? readHostElementRef(layout, node) : null;
|
|
39295
|
+
}
|
|
39339
39296
|
var jsxStylePolicy = defineCrossRule({
|
|
39340
39297
|
id: "jsx-style-policy",
|
|
39341
39298
|
severity: "warn",
|
|
39342
|
-
messages:
|
|
39299
|
+
messages: messages141,
|
|
39343
39300
|
meta: {
|
|
39344
39301
|
description: "Enforce accessibility policy thresholds on inline JSX style objects.",
|
|
39345
39302
|
fixable: false,
|
|
39346
39303
|
category: "css-jsx"
|
|
39347
39304
|
},
|
|
39348
39305
|
check(context, emit) {
|
|
39349
|
-
const { solids } = context;
|
|
39306
|
+
const { solids, layout } = context;
|
|
39350
39307
|
const policy = getActivePolicy();
|
|
39351
39308
|
if (policy === null) return;
|
|
39352
39309
|
const name = getActivePolicyName() ?? "";
|
|
39353
|
-
forEachStylePropertyAcross(solids, (solid, p) => {
|
|
39310
|
+
forEachStylePropertyAcross(solids, (solid, p, element) => {
|
|
39354
39311
|
if (!import_typescript135.default.isPropertyAssignment(p)) return;
|
|
39355
39312
|
const key = objectKeyName(p.name);
|
|
39356
39313
|
if (!key) return;
|
|
@@ -39366,7 +39323,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39366
39323
|
solid.sourceFile,
|
|
39367
39324
|
jsxStylePolicy.id,
|
|
39368
39325
|
"fontTooSmall",
|
|
39369
|
-
resolveMessage(
|
|
39326
|
+
resolveMessage(messages141.fontTooSmall, {
|
|
39370
39327
|
prop: key,
|
|
39371
39328
|
value: strVal,
|
|
39372
39329
|
resolved: formatRounded(px),
|
|
@@ -39388,7 +39345,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39388
39345
|
solid.sourceFile,
|
|
39389
39346
|
jsxStylePolicy.id,
|
|
39390
39347
|
"lineHeightTooSmall",
|
|
39391
|
-
resolveMessage(
|
|
39348
|
+
resolveMessage(messages141.lineHeightTooSmall, {
|
|
39392
39349
|
value: String(lh),
|
|
39393
39350
|
min: String(policy.minLineHeight),
|
|
39394
39351
|
policy: name
|
|
@@ -39398,6 +39355,8 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39398
39355
|
return;
|
|
39399
39356
|
}
|
|
39400
39357
|
if (INLINE_TOUCH_TARGET_KEYS.has(normalizedKey)) {
|
|
39358
|
+
const hostRef = readNodeHostElementRef(layout, solid, element);
|
|
39359
|
+
if (!isInteractiveElement(solid, element, hostRef)) return;
|
|
39401
39360
|
const strVal = getStaticStringValue(p.initializer);
|
|
39402
39361
|
if (!strVal) return;
|
|
39403
39362
|
const px = parsePxValue(strVal);
|
|
@@ -39410,7 +39369,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39410
39369
|
solid.sourceFile,
|
|
39411
39370
|
jsxStylePolicy.id,
|
|
39412
39371
|
"heightTooSmall",
|
|
39413
|
-
resolveMessage(
|
|
39372
|
+
resolveMessage(messages141.heightTooSmall, {
|
|
39414
39373
|
prop: key,
|
|
39415
39374
|
value: strVal,
|
|
39416
39375
|
resolved: formatRounded(px),
|
|
@@ -39432,7 +39391,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39432
39391
|
solid.sourceFile,
|
|
39433
39392
|
jsxStylePolicy.id,
|
|
39434
39393
|
"letterSpacingTooSmall",
|
|
39435
|
-
resolveMessage(
|
|
39394
|
+
resolveMessage(messages141.letterSpacingTooSmall, {
|
|
39436
39395
|
value: strVal,
|
|
39437
39396
|
resolved: String(em),
|
|
39438
39397
|
min: String(policy.minLetterSpacing),
|
|
@@ -39453,7 +39412,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39453
39412
|
solid.sourceFile,
|
|
39454
39413
|
jsxStylePolicy.id,
|
|
39455
39414
|
"wordSpacingTooSmall",
|
|
39456
|
-
resolveMessage(
|
|
39415
|
+
resolveMessage(messages141.wordSpacingTooSmall, {
|
|
39457
39416
|
value: strVal,
|
|
39458
39417
|
resolved: String(em),
|
|
39459
39418
|
min: String(policy.minWordSpacing),
|
|
@@ -39467,7 +39426,7 @@ var jsxStylePolicy = defineCrossRule({
|
|
|
39467
39426
|
});
|
|
39468
39427
|
|
|
39469
39428
|
// src/cross-file/rules/css-layout-sibling-alignment-outlier.ts
|
|
39470
|
-
var
|
|
39429
|
+
var messages142 = {
|
|
39471
39430
|
misalignedSibling: "Vertically misaligned '{{subject}}' in '{{parent}}'.{{fix}}{{offsetClause}}"
|
|
39472
39431
|
};
|
|
39473
39432
|
var MIN_CONFIDENCE_THRESHOLD = 0.48;
|
|
@@ -39476,7 +39435,7 @@ var siblingAlignmentDetector = {
|
|
|
39476
39435
|
id: "sibling-alignment-outlier",
|
|
39477
39436
|
collect: collectAlignmentCases,
|
|
39478
39437
|
evaluate(input, context) {
|
|
39479
|
-
if (context.logger.
|
|
39438
|
+
if (context.logger.isLevelEnabled(Level.Trace)) {
|
|
39480
39439
|
const ctx = input.context;
|
|
39481
39440
|
context.logger.trace(
|
|
39482
39441
|
`[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}`
|
|
@@ -39515,7 +39474,7 @@ var siblingAlignmentDetector = {
|
|
|
39515
39474
|
var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
39516
39475
|
id: "css-layout-sibling-alignment-outlier",
|
|
39517
39476
|
severity: "warn",
|
|
39518
|
-
messages:
|
|
39477
|
+
messages: messages142,
|
|
39519
39478
|
meta: {
|
|
39520
39479
|
description: "Detect vertical alignment outliers between sibling elements in shared layout containers.",
|
|
39521
39480
|
fixable: false,
|
|
@@ -39525,7 +39484,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39525
39484
|
const log = context.logger;
|
|
39526
39485
|
const detections = runLayoutDetector(context, siblingAlignmentDetector);
|
|
39527
39486
|
const uniqueDetections = dedupeDetectionsBySubject(detections);
|
|
39528
|
-
if (log.
|
|
39487
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39529
39488
|
log.debug(
|
|
39530
39489
|
`[sibling-alignment] raw=${detections.length} deduped=${uniqueDetections.length}`
|
|
39531
39490
|
);
|
|
@@ -39539,7 +39498,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39539
39498
|
const subjectId = detection.caseData.subject.elementId;
|
|
39540
39499
|
const logPrefix = `[sibling-alignment] <${subjectTag}> in <${parentTag}> (${subjectFile}#${subjectId})`;
|
|
39541
39500
|
if (detection.evidence.confidence < MIN_CONFIDENCE_THRESHOLD) {
|
|
39542
|
-
if (log.
|
|
39501
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39543
39502
|
log.debug(
|
|
39544
39503
|
`${logPrefix} SKIP: confidence=${detection.evidence.confidence.toFixed(2)} < threshold=${MIN_CONFIDENCE_THRESHOLD}`
|
|
39545
39504
|
);
|
|
@@ -39548,7 +39507,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39548
39507
|
}
|
|
39549
39508
|
const estimatedOffset = detection.evidence.estimatedOffsetPx;
|
|
39550
39509
|
if (estimatedOffset !== null && Math.abs(estimatedOffset) < MIN_OFFSET_PX_THRESHOLD && !hasNonOffsetPrimaryEvidence(detection.evidence.topFactors)) {
|
|
39551
|
-
if (log.
|
|
39510
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39552
39511
|
log.debug(
|
|
39553
39512
|
`${logPrefix} SKIP: offset=${estimatedOffset.toFixed(2)}px < ${MIN_OFFSET_PX_THRESHOLD}px (no non-offset primary evidence, topFactors=[${detection.evidence.topFactors.join(",")}])`
|
|
39554
39513
|
);
|
|
@@ -39560,7 +39519,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39560
39519
|
detection.caseData.cohort.parentElementKey,
|
|
39561
39520
|
detection.caseData.subject.solidFile
|
|
39562
39521
|
)) {
|
|
39563
|
-
if (log.
|
|
39522
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39564
39523
|
log.debug(`${logPrefix} SKIP: out-of-flow ancestor`);
|
|
39565
39524
|
}
|
|
39566
39525
|
continue;
|
|
@@ -39571,7 +39530,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39571
39530
|
detection.caseData.subject.elementId
|
|
39572
39531
|
);
|
|
39573
39532
|
if (!subjectRef) {
|
|
39574
|
-
if (log.
|
|
39533
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39575
39534
|
log.debug(`${logPrefix} SKIP: no node ref`);
|
|
39576
39535
|
}
|
|
39577
39536
|
continue;
|
|
@@ -39587,7 +39546,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39587
39546
|
const primaryFix = detection.evidence.primaryFix;
|
|
39588
39547
|
const firstChar = primaryFix.length > 0 ? primaryFix[0] : void 0;
|
|
39589
39548
|
const fix = firstChar !== void 0 ? ` ${firstChar.toUpperCase()}${primaryFix.slice(1)}.` : "";
|
|
39590
|
-
if (log.
|
|
39549
|
+
if (log.isLevelEnabled(Level.Debug)) {
|
|
39591
39550
|
log.debug(
|
|
39592
39551
|
`${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}]`
|
|
39593
39552
|
);
|
|
@@ -39599,7 +39558,7 @@ var cssLayoutSiblingAlignmentOutlier = defineCrossRule({
|
|
|
39599
39558
|
subjectRef.solid.sourceFile,
|
|
39600
39559
|
cssLayoutSiblingAlignmentOutlier.id,
|
|
39601
39560
|
"misalignedSibling",
|
|
39602
|
-
resolveMessage(
|
|
39561
|
+
resolveMessage(messages142.misalignedSibling, {
|
|
39603
39562
|
subject,
|
|
39604
39563
|
parent,
|
|
39605
39564
|
fix,
|
|
@@ -39683,13 +39642,13 @@ function hasNonOffsetPrimaryEvidence(topFactors) {
|
|
|
39683
39642
|
}
|
|
39684
39643
|
|
|
39685
39644
|
// src/cross-file/rules/css-layout-transition-layout-property.ts
|
|
39686
|
-
var
|
|
39645
|
+
var messages143 = {
|
|
39687
39646
|
transitionLayoutProperty: "Transition '{{property}}' in '{{declaration}}' animates layout-affecting geometry. Prefer transform/opacity to avoid CLS."
|
|
39688
39647
|
};
|
|
39689
39648
|
var cssLayoutTransitionLayoutProperty = defineCrossRule({
|
|
39690
39649
|
id: "css-layout-transition-layout-property",
|
|
39691
39650
|
severity: "warn",
|
|
39692
|
-
messages:
|
|
39651
|
+
messages: messages143,
|
|
39693
39652
|
meta: {
|
|
39694
39653
|
description: "Disallow transitions that animate layout-affecting geometry properties.",
|
|
39695
39654
|
fixable: false,
|
|
@@ -39713,7 +39672,7 @@ var cssLayoutTransitionLayoutProperty = defineCrossRule({
|
|
|
39713
39672
|
},
|
|
39714
39673
|
cssLayoutTransitionLayoutProperty.id,
|
|
39715
39674
|
"transitionLayoutProperty",
|
|
39716
|
-
resolveMessage(
|
|
39675
|
+
resolveMessage(messages143.transitionLayoutProperty, {
|
|
39717
39676
|
property: target,
|
|
39718
39677
|
declaration: declaration.property
|
|
39719
39678
|
}),
|
|
@@ -39728,13 +39687,13 @@ function findLayoutTransitionTarget(raw) {
|
|
|
39728
39687
|
}
|
|
39729
39688
|
|
|
39730
39689
|
// src/cross-file/rules/css-layout-animation-layout-property.ts
|
|
39731
|
-
var
|
|
39690
|
+
var messages144 = {
|
|
39732
39691
|
animationLayoutProperty: "Animation '{{animation}}' mutates layout-affecting '{{property}}', which can trigger CLS. Prefer transform/opacity or reserve geometry."
|
|
39733
39692
|
};
|
|
39734
39693
|
var cssLayoutAnimationLayoutProperty = defineCrossRule({
|
|
39735
39694
|
id: "css-layout-animation-layout-property",
|
|
39736
39695
|
severity: "warn",
|
|
39737
|
-
messages:
|
|
39696
|
+
messages: messages144,
|
|
39738
39697
|
meta: {
|
|
39739
39698
|
description: "Disallow keyframe animations that mutate layout-affecting properties and can trigger CLS.",
|
|
39740
39699
|
fixable: false,
|
|
@@ -39762,7 +39721,7 @@ var cssLayoutAnimationLayoutProperty = defineCrossRule({
|
|
|
39762
39721
|
},
|
|
39763
39722
|
cssLayoutAnimationLayoutProperty.id,
|
|
39764
39723
|
"animationLayoutProperty",
|
|
39765
|
-
resolveMessage(
|
|
39724
|
+
resolveMessage(messages144.animationLayoutProperty, {
|
|
39766
39725
|
animation: match.name,
|
|
39767
39726
|
property: match.property
|
|
39768
39727
|
}),
|
|
@@ -39832,13 +39791,13 @@ function firstRiskyAnimationName(names, riskyKeyframes) {
|
|
|
39832
39791
|
}
|
|
39833
39792
|
|
|
39834
39793
|
// src/cross-file/rules/css-layout-stateful-box-model-shift.ts
|
|
39835
|
-
var
|
|
39794
|
+
var messages145 = {
|
|
39836
39795
|
statefulBoxModelShift: "State selector '{{selector}}' changes layout-affecting '{{property}}'. Keep geometry stable across states to avoid CLS."
|
|
39837
39796
|
};
|
|
39838
39797
|
var cssLayoutStatefulBoxModelShift = defineCrossRule({
|
|
39839
39798
|
id: "css-layout-stateful-box-model-shift",
|
|
39840
39799
|
severity: "warn",
|
|
39841
|
-
messages:
|
|
39800
|
+
messages: messages145,
|
|
39842
39801
|
meta: {
|
|
39843
39802
|
description: "Disallow stateful selector changes that alter element geometry and trigger layout shifts.",
|
|
39844
39803
|
fixable: false,
|
|
@@ -39879,7 +39838,7 @@ var cssLayoutStatefulBoxModelShift = defineCrossRule({
|
|
|
39879
39838
|
},
|
|
39880
39839
|
cssLayoutStatefulBoxModelShift.id,
|
|
39881
39840
|
"statefulBoxModelShift",
|
|
39882
|
-
resolveMessage(
|
|
39841
|
+
resolveMessage(messages145.statefulBoxModelShift, {
|
|
39883
39842
|
selector: match.raw,
|
|
39884
39843
|
property: declaration.property
|
|
39885
39844
|
}),
|
|
@@ -39973,14 +39932,14 @@ function lookupBaseByProperty(baseValueIndex, selectorKeys) {
|
|
|
39973
39932
|
|
|
39974
39933
|
// src/cross-file/rules/css-layout-unsized-replaced-element.ts
|
|
39975
39934
|
var import_typescript136 = __toESM(require("typescript"), 1);
|
|
39976
|
-
var
|
|
39935
|
+
var messages146 = {
|
|
39977
39936
|
unsizedReplacedElement: "Replaced element '{{tag}}' has no stable reserved size (width/height or aspect-ratio with a dimension), which can cause CLS."
|
|
39978
39937
|
};
|
|
39979
39938
|
var REPLACED_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "iframe", "canvas", "svg"]);
|
|
39980
39939
|
var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
39981
39940
|
id: "css-layout-unsized-replaced-element",
|
|
39982
39941
|
severity: "warn",
|
|
39983
|
-
messages:
|
|
39942
|
+
messages: messages146,
|
|
39984
39943
|
meta: {
|
|
39985
39944
|
description: "Require stable reserved geometry for replaced media elements to prevent layout shifts.",
|
|
39986
39945
|
fixable: false,
|
|
@@ -39996,7 +39955,8 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
|
39996
39955
|
const ref = readNodeRef(context.layout, node);
|
|
39997
39956
|
if (!ref) continue;
|
|
39998
39957
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
39999
|
-
|
|
39958
|
+
const hostRef = readHostElementRef(context.layout, node);
|
|
39959
|
+
if (hasReservedSize(ref.solid, node.attributes, ref.element, reservedSpace, hostRef)) continue;
|
|
40000
39960
|
emit(
|
|
40001
39961
|
createDiagnostic(
|
|
40002
39962
|
ref.solid.file,
|
|
@@ -40004,22 +39964,24 @@ var cssLayoutUnsizedReplacedElement = defineCrossRule({
|
|
|
40004
39964
|
ref.solid.sourceFile,
|
|
40005
39965
|
cssLayoutUnsizedReplacedElement.id,
|
|
40006
39966
|
"unsizedReplacedElement",
|
|
40007
|
-
resolveMessage(
|
|
39967
|
+
resolveMessage(messages146.unsizedReplacedElement, { tag }),
|
|
40008
39968
|
"warn"
|
|
40009
39969
|
)
|
|
40010
39970
|
);
|
|
40011
39971
|
}
|
|
40012
39972
|
}
|
|
40013
39973
|
});
|
|
40014
|
-
function hasReservedSize(solid, attributes, element, reservedSpaceFact) {
|
|
39974
|
+
function hasReservedSize(solid, attributes, element, reservedSpaceFact, hostElementRef) {
|
|
40015
39975
|
if (reservedSpaceFact.hasReservedSpace) return true;
|
|
40016
39976
|
const attrWidth = parsePositiveLength(attributes.get("width"));
|
|
40017
39977
|
const attrHeight = parsePositiveLength(attributes.get("height"));
|
|
40018
39978
|
const jsxAttrWidth = readPositiveJsxAttribute(solid, element, "width");
|
|
40019
39979
|
const jsxAttrHeight = readPositiveJsxAttribute(solid, element, "height");
|
|
40020
|
-
|
|
40021
|
-
const
|
|
40022
|
-
|
|
39980
|
+
const hostJsxWidth = hostElementRef !== null ? readPositiveJsxAttribute(hostElementRef.solid, hostElementRef.element, "width") : false;
|
|
39981
|
+
const hostJsxHeight = hostElementRef !== null ? readPositiveJsxAttribute(hostElementRef.solid, hostElementRef.element, "height") : false;
|
|
39982
|
+
if (attrWidth && attrHeight || jsxAttrWidth && jsxAttrHeight || hostJsxWidth && hostJsxHeight) return true;
|
|
39983
|
+
const hasAnyWidth = attrWidth || jsxAttrWidth || hostJsxWidth || reservedSpaceFact.hasUsableInlineDimension;
|
|
39984
|
+
const hasAnyHeight = attrHeight || jsxAttrHeight || hostJsxHeight || reservedSpaceFact.hasUsableBlockDimension || reservedSpaceFact.hasContainIntrinsicSize;
|
|
40023
39985
|
if (reservedSpaceFact.hasUsableAspectRatio && (hasAnyWidth || hasAnyHeight)) return true;
|
|
40024
39986
|
if (reservedSpaceFact.hasContainIntrinsicSize && (hasAnyWidth || hasAnyHeight)) return true;
|
|
40025
39987
|
return false;
|
|
@@ -40055,7 +40017,7 @@ function readPositiveJsxAttribute(solid, element, name) {
|
|
|
40055
40017
|
}
|
|
40056
40018
|
|
|
40057
40019
|
// src/cross-file/rules/css-layout-dynamic-slot-no-reserved-space.ts
|
|
40058
|
-
var
|
|
40020
|
+
var messages147 = {
|
|
40059
40021
|
dynamicSlotNoReservedSpace: "Dynamic content container '{{tag}}' does not reserve block space (min-height/height/aspect-ratio/contain-intrinsic-size), which can cause CLS."
|
|
40060
40022
|
};
|
|
40061
40023
|
var INLINE_DISPLAYS = /* @__PURE__ */ new Set(["inline", "contents"]);
|
|
@@ -40077,7 +40039,7 @@ function hasOutOfFlowAncestor(layout, node) {
|
|
|
40077
40039
|
var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
|
|
40078
40040
|
id: "css-layout-dynamic-slot-no-reserved-space",
|
|
40079
40041
|
severity: "warn",
|
|
40080
|
-
messages:
|
|
40042
|
+
messages: messages147,
|
|
40081
40043
|
meta: {
|
|
40082
40044
|
description: "Require reserved block space for dynamic content containers to avoid layout shifts.",
|
|
40083
40045
|
fixable: false,
|
|
@@ -40100,19 +40062,19 @@ var cssLayoutDynamicSlotNoReservedSpace = defineCrossRule({
|
|
|
40100
40062
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40101
40063
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40102
40064
|
if (hasBlockAxisPadding(snapshot)) continue;
|
|
40103
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace",
|
|
40065
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutDynamicSlotNoReservedSpace.id, "dynamicSlotNoReservedSpace", messages147.dynamicSlotNoReservedSpace, cssLayoutDynamicSlotNoReservedSpace.severity)) continue;
|
|
40104
40066
|
}
|
|
40105
40067
|
}
|
|
40106
40068
|
});
|
|
40107
40069
|
|
|
40108
40070
|
// src/cross-file/rules/css-layout-scrollbar-gutter-instability.ts
|
|
40109
|
-
var
|
|
40071
|
+
var messages148 = {
|
|
40110
40072
|
missingScrollbarGutter: "Scrollable container '{{tag}}' uses overflow auto/scroll without `scrollbar-gutter: stable`, which can trigger CLS when scrollbars appear."
|
|
40111
40073
|
};
|
|
40112
40074
|
var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
40113
40075
|
id: "css-layout-scrollbar-gutter-instability",
|
|
40114
40076
|
severity: "warn",
|
|
40115
|
-
messages:
|
|
40077
|
+
messages: messages148,
|
|
40116
40078
|
meta: {
|
|
40117
40079
|
description: "Require stable scrollbar gutters for scrollable containers to reduce layout shifts.",
|
|
40118
40080
|
fixable: false,
|
|
@@ -40131,19 +40093,19 @@ var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
|
40131
40093
|
if (scrollbarWidth === "none") continue;
|
|
40132
40094
|
const gutter = readKnownNormalized(snapshot, "scrollbar-gutter");
|
|
40133
40095
|
if (gutter !== null && gutter.startsWith("stable")) continue;
|
|
40134
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter",
|
|
40096
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutScrollbarGutterInstability.id, "missingScrollbarGutter", messages148.missingScrollbarGutter, cssLayoutScrollbarGutterInstability.severity)) continue;
|
|
40135
40097
|
}
|
|
40136
40098
|
}
|
|
40137
40099
|
});
|
|
40138
40100
|
|
|
40139
40101
|
// src/cross-file/rules/css-layout-overflow-anchor-instability.ts
|
|
40140
|
-
var
|
|
40102
|
+
var messages149 = {
|
|
40141
40103
|
unstableOverflowAnchor: "Element '{{tag}}' sets `overflow-anchor: none` on a {{context}} container; disabling scroll anchoring can amplify visible layout shifts."
|
|
40142
40104
|
};
|
|
40143
40105
|
var cssLayoutOverflowAnchorInstability = defineCrossRule({
|
|
40144
40106
|
id: "css-layout-overflow-anchor-instability",
|
|
40145
40107
|
severity: "warn",
|
|
40146
|
-
messages:
|
|
40108
|
+
messages: messages149,
|
|
40147
40109
|
meta: {
|
|
40148
40110
|
description: "Disallow overflow-anchor none on dynamic or scrollable containers prone to visible layout shifts.",
|
|
40149
40111
|
fixable: false,
|
|
@@ -40161,20 +40123,20 @@ var cssLayoutOverflowAnchorInstability = defineCrossRule({
|
|
|
40161
40123
|
const isDynamicContainer = isDynamicContainerLike(node);
|
|
40162
40124
|
if (!isScrollable && !isDynamicContainer) continue;
|
|
40163
40125
|
const containerContext = isScrollable ? "scrollable" : "dynamic";
|
|
40164
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor",
|
|
40126
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowAnchorInstability.id, "unstableOverflowAnchor", messages149.unstableOverflowAnchor, cssLayoutOverflowAnchorInstability.severity, { context: containerContext })) continue;
|
|
40165
40127
|
}
|
|
40166
40128
|
}
|
|
40167
40129
|
});
|
|
40168
40130
|
|
|
40169
40131
|
// src/cross-file/rules/css-layout-font-swap-instability.ts
|
|
40170
|
-
var
|
|
40132
|
+
var messages150 = {
|
|
40171
40133
|
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."
|
|
40172
40134
|
};
|
|
40173
40135
|
var SWAP_DISPLAYS = /* @__PURE__ */ new Set(["swap", "fallback"]);
|
|
40174
40136
|
var cssLayoutFontSwapInstability = defineCrossRule({
|
|
40175
40137
|
id: "css-layout-font-swap-instability",
|
|
40176
40138
|
severity: "warn",
|
|
40177
|
-
messages:
|
|
40139
|
+
messages: messages150,
|
|
40178
40140
|
meta: {
|
|
40179
40141
|
description: "Require metric overrides for swapping webfonts to reduce layout shifts during font load.",
|
|
40180
40142
|
fixable: false,
|
|
@@ -40221,7 +40183,7 @@ var cssLayoutFontSwapInstability = defineCrossRule({
|
|
|
40221
40183
|
},
|
|
40222
40184
|
cssLayoutFontSwapInstability.id,
|
|
40223
40185
|
"unstableFontSwap",
|
|
40224
|
-
resolveMessage(
|
|
40186
|
+
resolveMessage(messages150.unstableFontSwap, {
|
|
40225
40187
|
family,
|
|
40226
40188
|
display: report.display
|
|
40227
40189
|
}),
|
|
@@ -40234,14 +40196,14 @@ var cssLayoutFontSwapInstability = defineCrossRule({
|
|
|
40234
40196
|
});
|
|
40235
40197
|
|
|
40236
40198
|
// src/cross-file/rules/css-layout-conditional-display-collapse.ts
|
|
40237
|
-
var
|
|
40199
|
+
var messages151 = {
|
|
40238
40200
|
conditionalDisplayCollapse: "Conditional display sets '{{display}}' on '{{tag}}' without stable reserved space, which can collapse/expand layout and cause CLS."
|
|
40239
40201
|
};
|
|
40240
40202
|
var COLLAPSING_DISPLAYS = /* @__PURE__ */ new Set(["none", "contents"]);
|
|
40241
40203
|
var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
40242
40204
|
id: "css-layout-conditional-display-collapse",
|
|
40243
40205
|
severity: "warn",
|
|
40244
|
-
messages:
|
|
40206
|
+
messages: messages151,
|
|
40245
40207
|
meta: {
|
|
40246
40208
|
description: "Disallow conditional display collapse in flow without reserved geometry.",
|
|
40247
40209
|
fixable: false,
|
|
@@ -40262,13 +40224,13 @@ var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
|
40262
40224
|
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
40263
40225
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40264
40226
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40265
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse",
|
|
40227
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages151.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
|
|
40266
40228
|
}
|
|
40267
40229
|
}
|
|
40268
40230
|
});
|
|
40269
40231
|
|
|
40270
40232
|
// src/cross-file/rules/css-layout-conditional-white-space-wrap-shift.ts
|
|
40271
|
-
var
|
|
40233
|
+
var messages152 = {
|
|
40272
40234
|
conditionalWhiteSpaceShift: "Conditional white-space '{{whiteSpace}}' on '{{tag}}' can reflow text and shift siblings; keep wrapping behavior stable or reserve geometry."
|
|
40273
40235
|
};
|
|
40274
40236
|
var WRAP_SHIFT_VALUES = /* @__PURE__ */ new Set(["nowrap", "pre"]);
|
|
@@ -40277,7 +40239,7 @@ var BLOCK_SIZE_PROPERTIES = ["height", "min-height"];
|
|
|
40277
40239
|
var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
40278
40240
|
id: "css-layout-conditional-white-space-wrap-shift",
|
|
40279
40241
|
severity: "warn",
|
|
40280
|
-
messages:
|
|
40242
|
+
messages: messages152,
|
|
40281
40243
|
meta: {
|
|
40282
40244
|
description: "Disallow conditional white-space wrapping mode toggles that can trigger CLS.",
|
|
40283
40245
|
fixable: false,
|
|
@@ -40300,7 +40262,7 @@ var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
|
40300
40262
|
if (!flow.inFlow) continue;
|
|
40301
40263
|
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
40302
40264
|
if (hasStableTextShell(snapshot)) continue;
|
|
40303
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift",
|
|
40265
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages152.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
|
|
40304
40266
|
}
|
|
40305
40267
|
}
|
|
40306
40268
|
});
|
|
@@ -40322,13 +40284,13 @@ function hasWrapShiftDelta(delta) {
|
|
|
40322
40284
|
}
|
|
40323
40285
|
|
|
40324
40286
|
// src/cross-file/rules/css-layout-overflow-mode-toggle-instability.ts
|
|
40325
|
-
var
|
|
40287
|
+
var messages153 = {
|
|
40326
40288
|
overflowModeToggle: "Conditional overflow mode changes scrolling ('{{overflow}}') on '{{tag}}' without `scrollbar-gutter: stable`, which can trigger CLS."
|
|
40327
40289
|
};
|
|
40328
40290
|
var cssLayoutOverflowModeToggleInstability = defineCrossRule({
|
|
40329
40291
|
id: "css-layout-overflow-mode-toggle-instability",
|
|
40330
40292
|
severity: "warn",
|
|
40331
|
-
messages:
|
|
40293
|
+
messages: messages153,
|
|
40332
40294
|
meta: {
|
|
40333
40295
|
description: "Disallow conditional overflow mode switches that can introduce scrollbar-induced layout shifts.",
|
|
40334
40296
|
fixable: false,
|
|
@@ -40353,7 +40315,7 @@ var cssLayoutOverflowModeToggleInstability = defineCrossRule({
|
|
|
40353
40315
|
const gutter = readKnownNormalizedWithGuard(snapshot, "scrollbar-gutter");
|
|
40354
40316
|
if (gutter !== null && gutter.startsWith("stable")) continue;
|
|
40355
40317
|
const overflowValue = scrollFact.overflowY ?? scrollFact.overflow ?? "auto";
|
|
40356
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle",
|
|
40318
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutOverflowModeToggleInstability.id, "overflowModeToggle", messages153.overflowModeToggle, cssLayoutOverflowModeToggleInstability.severity, { overflow: overflowValue })) continue;
|
|
40357
40319
|
}
|
|
40358
40320
|
}
|
|
40359
40321
|
});
|
|
@@ -40373,7 +40335,7 @@ function hasAnyScrollValue(delta) {
|
|
|
40373
40335
|
}
|
|
40374
40336
|
|
|
40375
40337
|
// src/cross-file/rules/css-layout-box-sizing-toggle-with-chrome.ts
|
|
40376
|
-
var
|
|
40338
|
+
var messages154 = {
|
|
40377
40339
|
boxSizingToggleWithChrome: "Conditional `box-sizing` toggle on '{{tag}}' combines with non-zero padding/border, which can shift layout and trigger CLS."
|
|
40378
40340
|
};
|
|
40379
40341
|
var BOX_SIZING_VALUES = /* @__PURE__ */ new Set(["content-box", "border-box"]);
|
|
@@ -40390,7 +40352,7 @@ var CHROME_PROPERTIES = [
|
|
|
40390
40352
|
var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
|
|
40391
40353
|
id: "css-layout-box-sizing-toggle-with-chrome",
|
|
40392
40354
|
severity: "warn",
|
|
40393
|
-
messages:
|
|
40355
|
+
messages: messages154,
|
|
40394
40356
|
meta: {
|
|
40395
40357
|
description: "Disallow conditional box-sizing mode toggles when box chrome contributes to geometry shifts.",
|
|
40396
40358
|
fixable: false,
|
|
@@ -40408,7 +40370,7 @@ var cssLayoutBoxSizingToggleWithChrome = defineCrossRule({
|
|
|
40408
40370
|
if (!boxSizingDelta.hasConditional) continue;
|
|
40409
40371
|
if (!boxSizingDelta.hasDelta) continue;
|
|
40410
40372
|
if (!hasNonZeroChrome(snapshot)) continue;
|
|
40411
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome",
|
|
40373
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutBoxSizingToggleWithChrome.id, "boxSizingToggleWithChrome", messages154.boxSizingToggleWithChrome, cssLayoutBoxSizingToggleWithChrome.severity)) continue;
|
|
40412
40374
|
}
|
|
40413
40375
|
}
|
|
40414
40376
|
});
|
|
@@ -40417,13 +40379,13 @@ function hasNonZeroChrome(snapshot) {
|
|
|
40417
40379
|
}
|
|
40418
40380
|
|
|
40419
40381
|
// src/cross-file/rules/css-layout-content-visibility-no-intrinsic-size.ts
|
|
40420
|
-
var
|
|
40382
|
+
var messages155 = {
|
|
40421
40383
|
missingIntrinsicSize: "`content-visibility: auto` on '{{tag}}' lacks intrinsic size reservation (`contain-intrinsic-size`/min-height/height/aspect-ratio), which can cause CLS."
|
|
40422
40384
|
};
|
|
40423
40385
|
var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
40424
40386
|
id: "css-layout-content-visibility-no-intrinsic-size",
|
|
40425
40387
|
severity: "warn",
|
|
40426
|
-
messages:
|
|
40388
|
+
messages: messages155,
|
|
40427
40389
|
meta: {
|
|
40428
40390
|
description: "Require intrinsic size reservation when using content-visibility auto to avoid late layout shifts.",
|
|
40429
40391
|
fixable: false,
|
|
@@ -40438,19 +40400,19 @@ var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
|
40438
40400
|
if (!isDeferredContainerLike(node, snapshot.node.textualContent)) continue;
|
|
40439
40401
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40440
40402
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40441
|
-
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize",
|
|
40403
|
+
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages155.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
|
|
40442
40404
|
}
|
|
40443
40405
|
}
|
|
40444
40406
|
});
|
|
40445
40407
|
|
|
40446
40408
|
// src/cross-file/rules/css-layout-conditional-offset-shift.ts
|
|
40447
|
-
var
|
|
40409
|
+
var messages156 = {
|
|
40448
40410
|
conditionalOffsetShift: "Conditional style applies non-zero '{{property}}' offset ({{value}}), which can cause layout shifts when conditions toggle."
|
|
40449
40411
|
};
|
|
40450
40412
|
var cssLayoutConditionalOffsetShift = defineCrossRule({
|
|
40451
40413
|
id: "css-layout-conditional-offset-shift",
|
|
40452
40414
|
severity: "warn",
|
|
40453
|
-
messages:
|
|
40415
|
+
messages: messages156,
|
|
40454
40416
|
meta: {
|
|
40455
40417
|
description: "Disallow conditional non-zero block-axis offsets that can trigger layout shifts.",
|
|
40456
40418
|
fixable: false,
|
|
@@ -40476,7 +40438,7 @@ var cssLayoutConditionalOffsetShift = defineCrossRule({
|
|
|
40476
40438
|
ref.solid.sourceFile,
|
|
40477
40439
|
cssLayoutConditionalOffsetShift.id,
|
|
40478
40440
|
"conditionalOffsetShift",
|
|
40479
|
-
resolveMessage(
|
|
40441
|
+
resolveMessage(messages156.conditionalOffsetShift, {
|
|
40480
40442
|
property: match.property,
|
|
40481
40443
|
value: `${formatFixed(match.value)}px`
|
|
40482
40444
|
}),
|
|
@@ -40537,7 +40499,7 @@ function hasStableBaseline(baselineBySignal, property, expectedPx) {
|
|
|
40537
40499
|
|
|
40538
40500
|
// src/cross-file/rules/jsx-layout-unstable-style-toggle.ts
|
|
40539
40501
|
var import_typescript137 = __toESM(require("typescript"), 1);
|
|
40540
|
-
var
|
|
40502
|
+
var messages157 = {
|
|
40541
40503
|
unstableLayoutStyleToggle: "Dynamic style value for '{{property}}' can toggle layout geometry at runtime and cause CLS."
|
|
40542
40504
|
};
|
|
40543
40505
|
var PX_NUMBER_PROPERTIES = /* @__PURE__ */ new Set([
|
|
@@ -40560,7 +40522,7 @@ var POSITIONED_OFFSET_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
40560
40522
|
var jsxLayoutUnstableStyleToggle = defineCrossRule({
|
|
40561
40523
|
id: "jsx-layout-unstable-style-toggle",
|
|
40562
40524
|
severity: "warn",
|
|
40563
|
-
messages:
|
|
40525
|
+
messages: messages157,
|
|
40564
40526
|
meta: {
|
|
40565
40527
|
description: "Flag dynamic inline style values on layout-sensitive properties that can trigger CLS.",
|
|
40566
40528
|
fixable: false,
|
|
@@ -40582,7 +40544,7 @@ var jsxLayoutUnstableStyleToggle = defineCrossRule({
|
|
|
40582
40544
|
solid.sourceFile,
|
|
40583
40545
|
jsxLayoutUnstableStyleToggle.id,
|
|
40584
40546
|
"unstableLayoutStyleToggle",
|
|
40585
|
-
resolveMessage(
|
|
40547
|
+
resolveMessage(messages157.unstableLayoutStyleToggle, { property: normalized }),
|
|
40586
40548
|
"warn"
|
|
40587
40549
|
)
|
|
40588
40550
|
);
|
|
@@ -40699,14 +40661,14 @@ function unwrapTypeWrapper(node) {
|
|
|
40699
40661
|
|
|
40700
40662
|
// src/cross-file/rules/jsx-layout-classlist-geometry-toggle.ts
|
|
40701
40663
|
var import_typescript138 = __toESM(require("typescript"), 1);
|
|
40702
|
-
var
|
|
40664
|
+
var messages158 = {
|
|
40703
40665
|
classListGeometryToggle: "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS."
|
|
40704
40666
|
};
|
|
40705
40667
|
var OUT_OF_FLOW_POSITIONS2 = /* @__PURE__ */ new Set(["fixed", "absolute"]);
|
|
40706
40668
|
var jsxLayoutClasslistGeometryToggle = defineCrossRule({
|
|
40707
40669
|
id: "jsx-layout-classlist-geometry-toggle",
|
|
40708
40670
|
severity: "warn",
|
|
40709
|
-
messages:
|
|
40671
|
+
messages: messages158,
|
|
40710
40672
|
meta: {
|
|
40711
40673
|
description: "Flag classList-driven class toggles that map to layout-affecting CSS geometry changes.",
|
|
40712
40674
|
fixable: false,
|
|
@@ -40732,7 +40694,7 @@ var jsxLayoutClasslistGeometryToggle = defineCrossRule({
|
|
|
40732
40694
|
solid.sourceFile,
|
|
40733
40695
|
jsxLayoutClasslistGeometryToggle.id,
|
|
40734
40696
|
"classListGeometryToggle",
|
|
40735
|
-
resolveMessage(
|
|
40697
|
+
resolveMessage(messages158.classListGeometryToggle, {
|
|
40736
40698
|
className,
|
|
40737
40699
|
property
|
|
40738
40700
|
}),
|
|
@@ -40781,14 +40743,14 @@ function isDynamicallyToggleable(node) {
|
|
|
40781
40743
|
}
|
|
40782
40744
|
|
|
40783
40745
|
// src/cross-file/rules/jsx-layout-picture-source-ratio-consistency.ts
|
|
40784
|
-
var
|
|
40746
|
+
var messages159 = {
|
|
40785
40747
|
inconsistentPictureRatio: "`<picture>` source ratio {{sourceRatio}} differs from fallback img ratio {{imgRatio}}, which can cause reserved-space mismatch and CLS."
|
|
40786
40748
|
};
|
|
40787
40749
|
var RATIO_DELTA_THRESHOLD = 0.02;
|
|
40788
40750
|
var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
|
|
40789
40751
|
id: "jsx-layout-picture-source-ratio-consistency",
|
|
40790
40752
|
severity: "warn",
|
|
40791
|
-
messages:
|
|
40753
|
+
messages: messages159,
|
|
40792
40754
|
meta: {
|
|
40793
40755
|
description: "Require consistent intrinsic aspect ratios across <picture> sources and fallback image.",
|
|
40794
40756
|
fixable: false,
|
|
@@ -40811,7 +40773,7 @@ var jsxLayoutPictureSourceRatioConsistency = defineCrossRule({
|
|
|
40811
40773
|
solid.sourceFile,
|
|
40812
40774
|
jsxLayoutPictureSourceRatioConsistency.id,
|
|
40813
40775
|
"inconsistentPictureRatio",
|
|
40814
|
-
resolveMessage(
|
|
40776
|
+
resolveMessage(messages159.inconsistentPictureRatio, {
|
|
40815
40777
|
sourceRatio: mismatch.sourceRatio,
|
|
40816
40778
|
imgRatio: mismatch.imgRatio
|
|
40817
40779
|
}),
|
|
@@ -40881,13 +40843,13 @@ function formatRatio(value2) {
|
|
|
40881
40843
|
}
|
|
40882
40844
|
|
|
40883
40845
|
// src/cross-file/rules/jsx-layout-fill-image-parent-must-be-sized.ts
|
|
40884
|
-
var
|
|
40846
|
+
var messages160 = {
|
|
40885
40847
|
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."
|
|
40886
40848
|
};
|
|
40887
40849
|
var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
40888
40850
|
id: "jsx-layout-fill-image-parent-must-be-sized",
|
|
40889
40851
|
severity: "warn",
|
|
40890
|
-
messages:
|
|
40852
|
+
messages: messages160,
|
|
40891
40853
|
meta: {
|
|
40892
40854
|
description: "Require stable parent size and positioning for fill-image component usage.",
|
|
40893
40855
|
fixable: false,
|
|
@@ -40917,7 +40879,7 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
|
40917
40879
|
solid.sourceFile,
|
|
40918
40880
|
jsxLayoutFillImageParentMustBeSized.id,
|
|
40919
40881
|
"unsizedFillParent",
|
|
40920
|
-
resolveMessage(
|
|
40882
|
+
resolveMessage(messages160.unsizedFillParent, {
|
|
40921
40883
|
component: element.tag ?? "Image"
|
|
40922
40884
|
}),
|
|
40923
40885
|
"warn"
|
|
@@ -40928,6 +40890,210 @@ var jsxLayoutFillImageParentMustBeSized = defineCrossRule({
|
|
|
40928
40890
|
}
|
|
40929
40891
|
});
|
|
40930
40892
|
|
|
40893
|
+
// src/cross-file/rules/jsx-layout-policy-touch-target.ts
|
|
40894
|
+
var messages161 = {
|
|
40895
|
+
heightTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
40896
|
+
widthTooSmall: "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
40897
|
+
paddingTooSmall: "Horizontal padding `{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
40898
|
+
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.",
|
|
40899
|
+
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."
|
|
40900
|
+
};
|
|
40901
|
+
var INTERACTIVE_HTML_TAGS2 = /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label", "summary"]);
|
|
40902
|
+
var INTERACTIVE_ARIA_ROLES2 = /* @__PURE__ */ new Set([
|
|
40903
|
+
"button",
|
|
40904
|
+
"link",
|
|
40905
|
+
"checkbox",
|
|
40906
|
+
"radio",
|
|
40907
|
+
"combobox",
|
|
40908
|
+
"listbox",
|
|
40909
|
+
"menuitem",
|
|
40910
|
+
"menuitemcheckbox",
|
|
40911
|
+
"menuitemradio",
|
|
40912
|
+
"option",
|
|
40913
|
+
"switch",
|
|
40914
|
+
"tab"
|
|
40915
|
+
]);
|
|
40916
|
+
function classifyInteractive(node, solid, element, layout) {
|
|
40917
|
+
const tag = node.tagName;
|
|
40918
|
+
if (tag !== null && INTERACTIVE_HTML_TAGS2.has(tag)) {
|
|
40919
|
+
if (tag === "input" || tag === "select" || tag === "textarea") return "input";
|
|
40920
|
+
return "button";
|
|
40921
|
+
}
|
|
40922
|
+
const roleAttr = getJSXAttributeEntity(solid, element, "role");
|
|
40923
|
+
if (roleAttr !== null && roleAttr.valueNode !== null) {
|
|
40924
|
+
const role = getStaticStringFromJSXValue(roleAttr.valueNode);
|
|
40925
|
+
if (role !== null && INTERACTIVE_ARIA_ROLES2.has(role)) return "button";
|
|
40926
|
+
}
|
|
40927
|
+
const hostRef = layout.hostElementRefsByNode.get(node) ?? null;
|
|
40928
|
+
if (hostRef !== null && hostRef.element.tagName !== null) {
|
|
40929
|
+
const hostTag = hostRef.element.tagName;
|
|
40930
|
+
if (INTERACTIVE_HTML_TAGS2.has(hostTag)) {
|
|
40931
|
+
if (hostTag === "input" || hostTag === "select" || hostTag === "textarea") return "input";
|
|
40932
|
+
return "button";
|
|
40933
|
+
}
|
|
40934
|
+
}
|
|
40935
|
+
return null;
|
|
40936
|
+
}
|
|
40937
|
+
function isVisuallyHidden(snapshot) {
|
|
40938
|
+
const position = readKnownNormalized(snapshot, "position");
|
|
40939
|
+
if (position !== "absolute" && position !== "fixed") return false;
|
|
40940
|
+
const node = snapshot.node;
|
|
40941
|
+
const opacityAttr = node.inlineStyleValues.get("opacity");
|
|
40942
|
+
if (opacityAttr === "0") return true;
|
|
40943
|
+
if (node.classTokenSet.has("opacity-0")) return true;
|
|
40944
|
+
return false;
|
|
40945
|
+
}
|
|
40946
|
+
var jsxLayoutPolicyTouchTarget = defineCrossRule({
|
|
40947
|
+
id: "jsx-layout-policy-touch-target",
|
|
40948
|
+
severity: "warn",
|
|
40949
|
+
messages: messages161,
|
|
40950
|
+
meta: {
|
|
40951
|
+
description: "Enforce minimum interactive element sizes per accessibility policy via resolved layout signals.",
|
|
40952
|
+
fixable: false,
|
|
40953
|
+
category: "css-a11y"
|
|
40954
|
+
},
|
|
40955
|
+
check(context, emit) {
|
|
40956
|
+
const policy = getActivePolicy();
|
|
40957
|
+
if (policy === null) return;
|
|
40958
|
+
const policyName = getActivePolicyName() ?? "";
|
|
40959
|
+
const { layout } = context;
|
|
40960
|
+
const elements = layout.elements;
|
|
40961
|
+
for (let i = 0; i < elements.length; i++) {
|
|
40962
|
+
const node = elements[i];
|
|
40963
|
+
if (!node) continue;
|
|
40964
|
+
const ref = readElementRef(layout, node);
|
|
40965
|
+
if (!ref) continue;
|
|
40966
|
+
const kind = classifyInteractive(node, ref.solid, ref.element, layout);
|
|
40967
|
+
if (kind === null) continue;
|
|
40968
|
+
const snapshot = collectSignalSnapshot(context, node);
|
|
40969
|
+
if (isVisuallyHidden(snapshot)) continue;
|
|
40970
|
+
const tag = node.tagName ?? node.tag ?? "element";
|
|
40971
|
+
checkDimension(
|
|
40972
|
+
snapshot,
|
|
40973
|
+
"height",
|
|
40974
|
+
kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
|
|
40975
|
+
layout,
|
|
40976
|
+
node,
|
|
40977
|
+
emit,
|
|
40978
|
+
"heightTooSmall",
|
|
40979
|
+
messages161.heightTooSmall,
|
|
40980
|
+
tag,
|
|
40981
|
+
policyName
|
|
40982
|
+
);
|
|
40983
|
+
checkDimension(
|
|
40984
|
+
snapshot,
|
|
40985
|
+
"min-height",
|
|
40986
|
+
kind === "button" ? policy.minButtonHeight : policy.minInputHeight,
|
|
40987
|
+
layout,
|
|
40988
|
+
node,
|
|
40989
|
+
emit,
|
|
40990
|
+
"heightTooSmall",
|
|
40991
|
+
messages161.heightTooSmall,
|
|
40992
|
+
tag,
|
|
40993
|
+
policyName
|
|
40994
|
+
);
|
|
40995
|
+
checkDimension(
|
|
40996
|
+
snapshot,
|
|
40997
|
+
"width",
|
|
40998
|
+
kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
|
|
40999
|
+
layout,
|
|
41000
|
+
node,
|
|
41001
|
+
emit,
|
|
41002
|
+
"widthTooSmall",
|
|
41003
|
+
messages161.widthTooSmall,
|
|
41004
|
+
tag,
|
|
41005
|
+
policyName
|
|
41006
|
+
);
|
|
41007
|
+
checkDimension(
|
|
41008
|
+
snapshot,
|
|
41009
|
+
"min-width",
|
|
41010
|
+
kind === "button" ? policy.minButtonWidth : policy.minTouchTarget,
|
|
41011
|
+
layout,
|
|
41012
|
+
node,
|
|
41013
|
+
emit,
|
|
41014
|
+
"widthTooSmall",
|
|
41015
|
+
messages161.widthTooSmall,
|
|
41016
|
+
tag,
|
|
41017
|
+
policyName
|
|
41018
|
+
);
|
|
41019
|
+
if (kind === "button") {
|
|
41020
|
+
checkDimension(
|
|
41021
|
+
snapshot,
|
|
41022
|
+
"padding-left",
|
|
41023
|
+
policy.minButtonHorizontalPadding,
|
|
41024
|
+
layout,
|
|
41025
|
+
node,
|
|
41026
|
+
emit,
|
|
41027
|
+
"paddingTooSmall",
|
|
41028
|
+
messages161.paddingTooSmall,
|
|
41029
|
+
tag,
|
|
41030
|
+
policyName
|
|
41031
|
+
);
|
|
41032
|
+
checkDimension(
|
|
41033
|
+
snapshot,
|
|
41034
|
+
"padding-right",
|
|
41035
|
+
policy.minButtonHorizontalPadding,
|
|
41036
|
+
layout,
|
|
41037
|
+
node,
|
|
41038
|
+
emit,
|
|
41039
|
+
"paddingTooSmall",
|
|
41040
|
+
messages161.paddingTooSmall,
|
|
41041
|
+
tag,
|
|
41042
|
+
policyName
|
|
41043
|
+
);
|
|
41044
|
+
}
|
|
41045
|
+
const reservedSpace = readReservedSpaceFact(layout, node);
|
|
41046
|
+
const minBlock = kind === "button" ? policy.minButtonHeight : policy.minInputHeight;
|
|
41047
|
+
const minInline = kind === "button" ? policy.minButtonWidth : policy.minTouchTarget;
|
|
41048
|
+
if (!reservedSpace.hasUsableBlockDimension) {
|
|
41049
|
+
emitLayoutDiagnostic(
|
|
41050
|
+
layout,
|
|
41051
|
+
node,
|
|
41052
|
+
emit,
|
|
41053
|
+
jsxLayoutPolicyTouchTarget.id,
|
|
41054
|
+
"noReservedBlockSize",
|
|
41055
|
+
messages161.noReservedBlockSize,
|
|
41056
|
+
"warn",
|
|
41057
|
+
{ tag, min: String(minBlock), policy: policyName }
|
|
41058
|
+
);
|
|
41059
|
+
}
|
|
41060
|
+
if (!reservedSpace.hasUsableInlineDimension) {
|
|
41061
|
+
emitLayoutDiagnostic(
|
|
41062
|
+
layout,
|
|
41063
|
+
node,
|
|
41064
|
+
emit,
|
|
41065
|
+
jsxLayoutPolicyTouchTarget.id,
|
|
41066
|
+
"noReservedInlineSize",
|
|
41067
|
+
messages161.noReservedInlineSize,
|
|
41068
|
+
"warn",
|
|
41069
|
+
{ tag, min: String(minInline), policy: policyName }
|
|
41070
|
+
);
|
|
41071
|
+
}
|
|
41072
|
+
}
|
|
41073
|
+
}
|
|
41074
|
+
});
|
|
41075
|
+
function checkDimension(snapshot, signal, min, layout, node, emit, messageId, template, tag, policyName) {
|
|
41076
|
+
const px = readKnownPx(snapshot, signal);
|
|
41077
|
+
if (px === null) return;
|
|
41078
|
+
if (px >= min) return;
|
|
41079
|
+
emitLayoutDiagnostic(
|
|
41080
|
+
layout,
|
|
41081
|
+
node,
|
|
41082
|
+
emit,
|
|
41083
|
+
jsxLayoutPolicyTouchTarget.id,
|
|
41084
|
+
messageId,
|
|
41085
|
+
template,
|
|
41086
|
+
"warn",
|
|
41087
|
+
{
|
|
41088
|
+
signal,
|
|
41089
|
+
value: formatRounded(px),
|
|
41090
|
+
min: String(min),
|
|
41091
|
+
tag,
|
|
41092
|
+
policy: policyName
|
|
41093
|
+
}
|
|
41094
|
+
);
|
|
41095
|
+
}
|
|
41096
|
+
|
|
40931
41097
|
// src/cross-file/rules/index.ts
|
|
40932
41098
|
var rules3 = [
|
|
40933
41099
|
jsxNoUndefinedCssClass,
|
|
@@ -40959,7 +41125,8 @@ var rules3 = [
|
|
|
40959
41125
|
cssLayoutOverflowModeToggleInstability,
|
|
40960
41126
|
cssLayoutBoxSizingToggleWithChrome,
|
|
40961
41127
|
cssLayoutContentVisibilityNoIntrinsicSize,
|
|
40962
|
-
cssLayoutConditionalOffsetShift
|
|
41128
|
+
cssLayoutConditionalOffsetShift,
|
|
41129
|
+
jsxLayoutPolicyTouchTarget
|
|
40963
41130
|
];
|
|
40964
41131
|
|
|
40965
41132
|
// src/cross-file/plugin.ts
|