@drskillissue/ganko 0.2.7 → 0.2.8
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-5OEDGKHL.js → chunk-NFDA6LAI.js} +17 -15
- package/dist/chunk-NFDA6LAI.js.map +1 -0
- package/dist/{chunk-WY5MMHK2.js → chunk-SSLKXOHI.js} +1464 -1918
- package/dist/chunk-SSLKXOHI.js.map +1 -0
- package/dist/eslint-plugin.cjs +1445 -1912
- package/dist/eslint-plugin.cjs.map +1 -1
- package/dist/eslint-plugin.js +1 -1
- package/dist/index.cjs +1479 -1931
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -69
- package/dist/index.d.ts +76 -69
- package/dist/index.js +2 -2
- package/dist/rules-manifest.cjs +16 -14
- package/dist/rules-manifest.cjs.map +1 -1
- package/dist/rules-manifest.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5OEDGKHL.js.map +0 -1
- package/dist/chunk-WY5MMHK2.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1622,7 +1622,7 @@ interface TailwindValidator {
|
|
|
1622
1622
|
declare function resolveTailwindValidator(files: readonly {
|
|
1623
1623
|
path: string;
|
|
1624
1624
|
content: string;
|
|
1625
|
-
}[]): Promise<TailwindValidator | null>;
|
|
1625
|
+
}[], logger?: Logger): Promise<TailwindValidator | null>;
|
|
1626
1626
|
|
|
1627
1627
|
/**
|
|
1628
1628
|
* CSSInput - Input type for building CSSGraph from CSS/SCSS source files.
|
|
@@ -2031,8 +2031,40 @@ interface SelectorAttributeConstraint {
|
|
|
2031
2031
|
value: string | null;
|
|
2032
2032
|
caseInsensitive: boolean;
|
|
2033
2033
|
}
|
|
2034
|
+
interface NthPattern {
|
|
2035
|
+
readonly step: number;
|
|
2036
|
+
readonly offset: number;
|
|
2037
|
+
}
|
|
2038
|
+
declare const enum PseudoConstraintKind {
|
|
2039
|
+
Simple = 0,
|
|
2040
|
+
FirstChild = 1,
|
|
2041
|
+
LastChild = 2,
|
|
2042
|
+
OnlyChild = 3,
|
|
2043
|
+
NthChild = 4,
|
|
2044
|
+
NthLastChild = 5,
|
|
2045
|
+
NthOfType = 6,
|
|
2046
|
+
NthLastOfType = 7,
|
|
2047
|
+
MatchesAny = 8,
|
|
2048
|
+
NoneOf = 9
|
|
2049
|
+
}
|
|
2050
|
+
interface ParsedPseudoConstraint {
|
|
2051
|
+
readonly name: string;
|
|
2052
|
+
readonly raw: string;
|
|
2053
|
+
readonly kind: PseudoConstraintKind;
|
|
2054
|
+
readonly nthPattern: NthPattern | null;
|
|
2055
|
+
readonly nestedCompounds: readonly SelectorCompound[][] | null;
|
|
2056
|
+
}
|
|
2057
|
+
interface SelectorCompound {
|
|
2058
|
+
readonly parts: readonly SelectorPart[];
|
|
2059
|
+
readonly tagName: string | null;
|
|
2060
|
+
readonly idValue: string | null;
|
|
2061
|
+
readonly classes: readonly string[];
|
|
2062
|
+
readonly attributes: readonly SelectorAttributeConstraint[];
|
|
2063
|
+
readonly pseudoClasses: readonly ParsedPseudoConstraint[];
|
|
2064
|
+
}
|
|
2034
2065
|
interface SelectorAnchor {
|
|
2035
2066
|
subjectTag: string | null;
|
|
2067
|
+
idValue: string | null;
|
|
2036
2068
|
classes: readonly string[];
|
|
2037
2069
|
attributes: readonly SelectorAttributeConstraint[];
|
|
2038
2070
|
includesDescendantCombinator: boolean;
|
|
@@ -2062,6 +2094,8 @@ interface SelectorEntity {
|
|
|
2062
2094
|
specificity: Specificity;
|
|
2063
2095
|
specificityScore: number;
|
|
2064
2096
|
complexity: SelectorComplexity;
|
|
2097
|
+
compounds: readonly SelectorCompound[];
|
|
2098
|
+
combinators: readonly CombinatorType[];
|
|
2065
2099
|
parts: SelectorPart[];
|
|
2066
2100
|
anchor: SelectorAnchor;
|
|
2067
2101
|
overrides: SelectorEntity[];
|
|
@@ -2293,7 +2327,8 @@ declare class CSSGraph {
|
|
|
2293
2327
|
readonly parseErrors: CSSParseError[];
|
|
2294
2328
|
readonly failedFilePaths: string[];
|
|
2295
2329
|
readonly tokenCategories: TokenCategory[];
|
|
2296
|
-
|
|
2330
|
+
private _filesWithLayers;
|
|
2331
|
+
get filesWithLayers(): ReadonlySet<string>;
|
|
2297
2332
|
readonly selectorsByPseudoClass: Map<string, SelectorEntity[]>;
|
|
2298
2333
|
readonly knownKeyframeNames: Set<string>;
|
|
2299
2334
|
readonly unresolvedAnimationRefs: UnresolvedAnimationRef[];
|
|
@@ -2305,17 +2340,14 @@ declare class CSSGraph {
|
|
|
2305
2340
|
readonly multiDeclarationProperties: Map<string, readonly DeclarationEntity[]>;
|
|
2306
2341
|
/** Declarations whose parent rule is inside a @keyframes block. */
|
|
2307
2342
|
readonly keyframeDeclarations: DeclarationEntity[];
|
|
2308
|
-
/** Rules with zero declarations and zero nested rules. */
|
|
2309
|
-
|
|
2343
|
+
/** Rules with zero declarations, zero nested rules, and zero nested at-rules. */
|
|
2344
|
+
private _emptyRules;
|
|
2345
|
+
get emptyRules(): readonly RuleEntity[];
|
|
2310
2346
|
/** @keyframes at-rules with no effective keyframe declarations. */
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
readonly urlDeclarations: DeclarationEntity[];
|
|
2316
|
-
readonly vendorPrefixedDeclarations: DeclarationEntity[];
|
|
2317
|
-
readonly hardcodedColorDeclarations: DeclarationEntity[];
|
|
2318
|
-
readonly overqualifiedSelectors: SelectorEntity[];
|
|
2347
|
+
private _emptyKeyframes;
|
|
2348
|
+
get emptyKeyframes(): readonly AtRuleEntity[];
|
|
2349
|
+
private _overqualifiedSelectors;
|
|
2350
|
+
get overqualifiedSelectors(): readonly SelectorEntity[];
|
|
2319
2351
|
readonly idSelectors: SelectorEntity[];
|
|
2320
2352
|
readonly attributeSelectors: SelectorEntity[];
|
|
2321
2353
|
readonly universalSelectors: SelectorEntity[];
|
|
@@ -2331,7 +2363,8 @@ declare class CSSGraph {
|
|
|
2331
2363
|
readonly usedFontFamilies: Set<string>;
|
|
2332
2364
|
/** Tailwind validator for utility class lookup (null if not a Tailwind project). */
|
|
2333
2365
|
readonly tailwind: TailwindValidator | null;
|
|
2334
|
-
|
|
2366
|
+
private _deepNestedRules;
|
|
2367
|
+
get deepNestedRules(): readonly RuleEntity[];
|
|
2335
2368
|
constructor(input: CSSInput);
|
|
2336
2369
|
intern(s: string): string;
|
|
2337
2370
|
nextFileId(): number;
|
|
@@ -2377,37 +2410,16 @@ declare class CSSGraph {
|
|
|
2377
2410
|
* Called after all phases complete.
|
|
2378
2411
|
*/
|
|
2379
2412
|
buildDerivedIndexes(): void;
|
|
2380
|
-
private buildRuleDeclarationIndexes;
|
|
2381
2413
|
private buildContainingMediaStacks;
|
|
2382
|
-
private
|
|
2414
|
+
private buildKeyframeIndexes;
|
|
2383
2415
|
private buildContainerNameIndexes;
|
|
2384
|
-
private buildElementKinds;
|
|
2385
|
-
private buildFilesWithLayers;
|
|
2386
|
-
private buildSelectorPseudoClassIndex;
|
|
2387
2416
|
/**
|
|
2388
2417
|
* Sort each declarationsByProperty list by sourceOrder and populate
|
|
2389
2418
|
* multiDeclarationProperties with only those having 2+ entries.
|
|
2390
2419
|
*/
|
|
2391
2420
|
private buildMultiDeclarationProperties;
|
|
2392
|
-
/**
|
|
2393
|
-
* Collect declarations whose parent rule is inside a @keyframes block.
|
|
2394
|
-
*/
|
|
2395
|
-
private buildKeyframeDeclarations;
|
|
2396
|
-
private buildKeyframeLayoutMutationsByName;
|
|
2397
|
-
/**
|
|
2398
|
-
* Collect rules with no declarations and no nested rules.
|
|
2399
|
-
*/
|
|
2400
|
-
private buildEmptyRules;
|
|
2401
|
-
/**
|
|
2402
|
-
* Collect @keyframes with no effective keyframe declarations.
|
|
2403
|
-
*/
|
|
2404
|
-
private buildEmptyKeyframes;
|
|
2405
|
-
private buildDeclarationDerivedIndexes;
|
|
2406
|
-
private buildSelectorDerivedIndexes;
|
|
2407
2421
|
private buildLayoutPropertiesByClassToken;
|
|
2408
|
-
private
|
|
2409
|
-
private buildFontFaceDescriptorsByFamily;
|
|
2410
|
-
private buildRuleDerivedIndexes;
|
|
2422
|
+
private buildFontIndexes;
|
|
2411
2423
|
buildUnusedIndexes(): void;
|
|
2412
2424
|
}
|
|
2413
2425
|
|
|
@@ -2533,18 +2545,26 @@ declare const enum LayoutSignalUnit {
|
|
|
2533
2545
|
Keyword = 2,
|
|
2534
2546
|
Unknown = 3
|
|
2535
2547
|
}
|
|
2548
|
+
declare const enum SignalValueKind {
|
|
2549
|
+
Known = 0,
|
|
2550
|
+
Unknown = 1
|
|
2551
|
+
}
|
|
2552
|
+
declare const enum SignalQuality {
|
|
2553
|
+
Exact = 0,
|
|
2554
|
+
Estimated = 1
|
|
2555
|
+
}
|
|
2536
2556
|
interface LayoutKnownSignalValue {
|
|
2537
|
-
readonly kind:
|
|
2557
|
+
readonly kind: SignalValueKind.Known;
|
|
2538
2558
|
readonly name: LayoutSignalName;
|
|
2539
2559
|
readonly normalized: string;
|
|
2540
2560
|
readonly source: LayoutSignalSource;
|
|
2541
2561
|
readonly guard: LayoutRuleGuard;
|
|
2542
2562
|
readonly unit: LayoutSignalUnit;
|
|
2543
2563
|
readonly px: number | null;
|
|
2544
|
-
readonly quality:
|
|
2564
|
+
readonly quality: SignalQuality;
|
|
2545
2565
|
}
|
|
2546
2566
|
interface LayoutUnknownSignalValue {
|
|
2547
|
-
readonly kind:
|
|
2567
|
+
readonly kind: SignalValueKind.Unknown;
|
|
2548
2568
|
readonly name: LayoutSignalName;
|
|
2549
2569
|
readonly source: LayoutSignalSource | null;
|
|
2550
2570
|
readonly guard: LayoutRuleGuard;
|
|
@@ -2782,10 +2802,10 @@ type LayoutReservedSpaceReason = "height" | "block-size" | "min-height" | "min-b
|
|
|
2782
2802
|
interface LayoutReservedSpaceFact {
|
|
2783
2803
|
readonly hasReservedSpace: boolean;
|
|
2784
2804
|
readonly reasons: readonly LayoutReservedSpaceReason[];
|
|
2785
|
-
readonly hasUsableInlineDimension: boolean;
|
|
2786
|
-
readonly hasUsableBlockDimension: boolean;
|
|
2787
2805
|
readonly hasContainIntrinsicSize: boolean;
|
|
2788
2806
|
readonly hasUsableAspectRatio: boolean;
|
|
2807
|
+
readonly hasDeclaredInlineDimension: boolean;
|
|
2808
|
+
readonly hasDeclaredBlockDimension: boolean;
|
|
2789
2809
|
}
|
|
2790
2810
|
declare const enum LayoutScrollAxis {
|
|
2791
2811
|
None = 0,
|
|
@@ -2843,46 +2863,35 @@ interface LayoutNormalizedRuleDeclaration {
|
|
|
2843
2863
|
readonly startColumn: number;
|
|
2844
2864
|
readonly propertyLength: number;
|
|
2845
2865
|
}
|
|
2846
|
-
interface
|
|
2866
|
+
interface LayoutElementRecord {
|
|
2867
|
+
readonly ref: LayoutElementRef | null;
|
|
2868
|
+
readonly edges: readonly LayoutMatchEdge[];
|
|
2869
|
+
readonly cascade: ReadonlyMap<string, LayoutCascadedDeclaration>;
|
|
2870
|
+
readonly snapshot: LayoutSignalSnapshot;
|
|
2871
|
+
readonly hotSignals: LayoutSnapshotHotSignals;
|
|
2872
|
+
readonly reservedSpace: LayoutReservedSpaceFact;
|
|
2873
|
+
readonly scrollContainer: LayoutScrollContainerFact;
|
|
2874
|
+
readonly flowParticipation: LayoutFlowParticipationFact;
|
|
2875
|
+
readonly containingBlock: LayoutContainingBlockFact;
|
|
2876
|
+
readonly conditionalDelta: ReadonlyMap<LayoutSignalName, LayoutConditionalSignalDeltaFact> | null;
|
|
2877
|
+
readonly baselineOffsets: ReadonlyMap<LayoutSignalName, readonly number[]> | null;
|
|
2878
|
+
}
|
|
2879
|
+
interface LayoutGraph {
|
|
2847
2880
|
readonly elements: readonly LayoutElementNode[];
|
|
2848
2881
|
readonly childrenByParentNode: ReadonlyMap<LayoutElementNode, readonly LayoutElementNode[]>;
|
|
2849
2882
|
readonly elementBySolidFileAndId: ReadonlyMap<string, ReadonlyMap<number, LayoutElementNode>>;
|
|
2850
2883
|
readonly elementRefsBySolidFileAndId: ReadonlyMap<string, ReadonlyMap<number, LayoutElementRef>>;
|
|
2851
2884
|
readonly elementsByTagName: ReadonlyMap<string, readonly LayoutElementNode[]>;
|
|
2852
2885
|
readonly measurementNodeByRootKey: ReadonlyMap<string, LayoutElementNode>;
|
|
2853
|
-
/**
|
|
2854
|
-
* Maps component call-site nodes to their resolved host DOM element reference.
|
|
2855
|
-
* Only populated for nodes that represent a component resolved to a concrete DOM
|
|
2856
|
-
* element. Native DOM element nodes and unresolvable components are absent.
|
|
2857
|
-
* Used by rules that need to inspect the host element's JSX attributes (e.g.
|
|
2858
|
-
* dynamic `width`/`height` expressions not capturable as static strings).
|
|
2859
|
-
*/
|
|
2860
2886
|
readonly hostElementRefsByNode: ReadonlyMap<LayoutElementNode, LayoutElementRef>;
|
|
2861
|
-
}
|
|
2862
|
-
interface LayoutGraphCascade {
|
|
2863
2887
|
readonly styleRules: readonly LayoutStyleRuleNode[];
|
|
2864
2888
|
readonly applies: readonly LayoutMatchEdge[];
|
|
2865
2889
|
readonly cssScopeBySolidFile: ReadonlyMap<string, readonly string[]>;
|
|
2866
|
-
readonly appliesByNode: ReadonlyMap<LayoutElementNode, readonly LayoutMatchEdge[]>;
|
|
2867
2890
|
readonly selectorCandidatesByNode: ReadonlyMap<LayoutElementNode, readonly number[]>;
|
|
2868
2891
|
readonly selectorsById: ReadonlyMap<number, SelectorEntity>;
|
|
2869
|
-
readonly
|
|
2870
|
-
readonly snapshotByElementNode: WeakMap<LayoutElementNode, LayoutSignalSnapshot>;
|
|
2871
|
-
readonly snapshotHotSignalsByNode: ReadonlyMap<LayoutElementNode, LayoutSnapshotHotSignals>;
|
|
2872
|
-
}
|
|
2873
|
-
interface LayoutGraphFacts {
|
|
2874
|
-
readonly reservedSpaceFactsByNode: ReadonlyMap<LayoutElementNode, LayoutReservedSpaceFact>;
|
|
2875
|
-
readonly scrollContainerFactsByNode: ReadonlyMap<LayoutElementNode, LayoutScrollContainerFact>;
|
|
2876
|
-
readonly flowParticipationFactsByNode: ReadonlyMap<LayoutElementNode, LayoutFlowParticipationFact>;
|
|
2877
|
-
readonly containingBlockFactsByNode: ReadonlyMap<LayoutElementNode, LayoutContainingBlockFact>;
|
|
2878
|
-
readonly conditionalSignalDeltaFactsByNode: ReadonlyMap<LayoutElementNode, ReadonlyMap<LayoutSignalName, LayoutConditionalSignalDeltaFact>>;
|
|
2879
|
-
readonly baselineOffsetFactsByNode: ReadonlyMap<LayoutElementNode, ReadonlyMap<LayoutSignalName, readonly number[]>>;
|
|
2880
|
-
}
|
|
2881
|
-
interface LayoutGraphCohorts {
|
|
2892
|
+
readonly records: ReadonlyMap<LayoutElementNode, LayoutElementRecord>;
|
|
2882
2893
|
readonly cohortStatsByParentNode: ReadonlyMap<LayoutElementNode, LayoutCohortStats>;
|
|
2883
2894
|
readonly contextByParentNode: ReadonlyMap<LayoutElementNode, AlignmentContext>;
|
|
2884
|
-
}
|
|
2885
|
-
interface LayoutGraphIndexes {
|
|
2886
2895
|
readonly elementsWithConditionalDeltaBySignal: ReadonlyMap<LayoutSignalName, readonly LayoutElementNode[]>;
|
|
2887
2896
|
readonly elementsWithConditionalOverflowDelta: readonly LayoutElementNode[];
|
|
2888
2897
|
readonly elementsWithConditionalOffsetDelta: readonly LayoutElementNode[];
|
|
@@ -2892,8 +2901,6 @@ interface LayoutGraphIndexes {
|
|
|
2892
2901
|
readonly statefulSelectorEntriesByRuleId: ReadonlyMap<number, readonly LayoutStatefulSelectorEntry[]>;
|
|
2893
2902
|
readonly statefulNormalizedDeclarationsByRuleId: ReadonlyMap<number, readonly LayoutNormalizedRuleDeclaration[]>;
|
|
2894
2903
|
readonly statefulBaseValueIndex: ReadonlyMap<string, ReadonlyMap<string, ReadonlySet<string>>>;
|
|
2895
|
-
}
|
|
2896
|
-
interface LayoutGraph extends LayoutGraphTopology, LayoutGraphCascade, LayoutGraphFacts, LayoutGraphCohorts, LayoutGraphIndexes {
|
|
2897
2904
|
readonly perf: LayoutPerfStatsMutable;
|
|
2898
2905
|
}
|
|
2899
2906
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1622,7 +1622,7 @@ interface TailwindValidator {
|
|
|
1622
1622
|
declare function resolveTailwindValidator(files: readonly {
|
|
1623
1623
|
path: string;
|
|
1624
1624
|
content: string;
|
|
1625
|
-
}[]): Promise<TailwindValidator | null>;
|
|
1625
|
+
}[], logger?: Logger): Promise<TailwindValidator | null>;
|
|
1626
1626
|
|
|
1627
1627
|
/**
|
|
1628
1628
|
* CSSInput - Input type for building CSSGraph from CSS/SCSS source files.
|
|
@@ -2031,8 +2031,40 @@ interface SelectorAttributeConstraint {
|
|
|
2031
2031
|
value: string | null;
|
|
2032
2032
|
caseInsensitive: boolean;
|
|
2033
2033
|
}
|
|
2034
|
+
interface NthPattern {
|
|
2035
|
+
readonly step: number;
|
|
2036
|
+
readonly offset: number;
|
|
2037
|
+
}
|
|
2038
|
+
declare const enum PseudoConstraintKind {
|
|
2039
|
+
Simple = 0,
|
|
2040
|
+
FirstChild = 1,
|
|
2041
|
+
LastChild = 2,
|
|
2042
|
+
OnlyChild = 3,
|
|
2043
|
+
NthChild = 4,
|
|
2044
|
+
NthLastChild = 5,
|
|
2045
|
+
NthOfType = 6,
|
|
2046
|
+
NthLastOfType = 7,
|
|
2047
|
+
MatchesAny = 8,
|
|
2048
|
+
NoneOf = 9
|
|
2049
|
+
}
|
|
2050
|
+
interface ParsedPseudoConstraint {
|
|
2051
|
+
readonly name: string;
|
|
2052
|
+
readonly raw: string;
|
|
2053
|
+
readonly kind: PseudoConstraintKind;
|
|
2054
|
+
readonly nthPattern: NthPattern | null;
|
|
2055
|
+
readonly nestedCompounds: readonly SelectorCompound[][] | null;
|
|
2056
|
+
}
|
|
2057
|
+
interface SelectorCompound {
|
|
2058
|
+
readonly parts: readonly SelectorPart[];
|
|
2059
|
+
readonly tagName: string | null;
|
|
2060
|
+
readonly idValue: string | null;
|
|
2061
|
+
readonly classes: readonly string[];
|
|
2062
|
+
readonly attributes: readonly SelectorAttributeConstraint[];
|
|
2063
|
+
readonly pseudoClasses: readonly ParsedPseudoConstraint[];
|
|
2064
|
+
}
|
|
2034
2065
|
interface SelectorAnchor {
|
|
2035
2066
|
subjectTag: string | null;
|
|
2067
|
+
idValue: string | null;
|
|
2036
2068
|
classes: readonly string[];
|
|
2037
2069
|
attributes: readonly SelectorAttributeConstraint[];
|
|
2038
2070
|
includesDescendantCombinator: boolean;
|
|
@@ -2062,6 +2094,8 @@ interface SelectorEntity {
|
|
|
2062
2094
|
specificity: Specificity;
|
|
2063
2095
|
specificityScore: number;
|
|
2064
2096
|
complexity: SelectorComplexity;
|
|
2097
|
+
compounds: readonly SelectorCompound[];
|
|
2098
|
+
combinators: readonly CombinatorType[];
|
|
2065
2099
|
parts: SelectorPart[];
|
|
2066
2100
|
anchor: SelectorAnchor;
|
|
2067
2101
|
overrides: SelectorEntity[];
|
|
@@ -2293,7 +2327,8 @@ declare class CSSGraph {
|
|
|
2293
2327
|
readonly parseErrors: CSSParseError[];
|
|
2294
2328
|
readonly failedFilePaths: string[];
|
|
2295
2329
|
readonly tokenCategories: TokenCategory[];
|
|
2296
|
-
|
|
2330
|
+
private _filesWithLayers;
|
|
2331
|
+
get filesWithLayers(): ReadonlySet<string>;
|
|
2297
2332
|
readonly selectorsByPseudoClass: Map<string, SelectorEntity[]>;
|
|
2298
2333
|
readonly knownKeyframeNames: Set<string>;
|
|
2299
2334
|
readonly unresolvedAnimationRefs: UnresolvedAnimationRef[];
|
|
@@ -2305,17 +2340,14 @@ declare class CSSGraph {
|
|
|
2305
2340
|
readonly multiDeclarationProperties: Map<string, readonly DeclarationEntity[]>;
|
|
2306
2341
|
/** Declarations whose parent rule is inside a @keyframes block. */
|
|
2307
2342
|
readonly keyframeDeclarations: DeclarationEntity[];
|
|
2308
|
-
/** Rules with zero declarations and zero nested rules. */
|
|
2309
|
-
|
|
2343
|
+
/** Rules with zero declarations, zero nested rules, and zero nested at-rules. */
|
|
2344
|
+
private _emptyRules;
|
|
2345
|
+
get emptyRules(): readonly RuleEntity[];
|
|
2310
2346
|
/** @keyframes at-rules with no effective keyframe declarations. */
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
readonly urlDeclarations: DeclarationEntity[];
|
|
2316
|
-
readonly vendorPrefixedDeclarations: DeclarationEntity[];
|
|
2317
|
-
readonly hardcodedColorDeclarations: DeclarationEntity[];
|
|
2318
|
-
readonly overqualifiedSelectors: SelectorEntity[];
|
|
2347
|
+
private _emptyKeyframes;
|
|
2348
|
+
get emptyKeyframes(): readonly AtRuleEntity[];
|
|
2349
|
+
private _overqualifiedSelectors;
|
|
2350
|
+
get overqualifiedSelectors(): readonly SelectorEntity[];
|
|
2319
2351
|
readonly idSelectors: SelectorEntity[];
|
|
2320
2352
|
readonly attributeSelectors: SelectorEntity[];
|
|
2321
2353
|
readonly universalSelectors: SelectorEntity[];
|
|
@@ -2331,7 +2363,8 @@ declare class CSSGraph {
|
|
|
2331
2363
|
readonly usedFontFamilies: Set<string>;
|
|
2332
2364
|
/** Tailwind validator for utility class lookup (null if not a Tailwind project). */
|
|
2333
2365
|
readonly tailwind: TailwindValidator | null;
|
|
2334
|
-
|
|
2366
|
+
private _deepNestedRules;
|
|
2367
|
+
get deepNestedRules(): readonly RuleEntity[];
|
|
2335
2368
|
constructor(input: CSSInput);
|
|
2336
2369
|
intern(s: string): string;
|
|
2337
2370
|
nextFileId(): number;
|
|
@@ -2377,37 +2410,16 @@ declare class CSSGraph {
|
|
|
2377
2410
|
* Called after all phases complete.
|
|
2378
2411
|
*/
|
|
2379
2412
|
buildDerivedIndexes(): void;
|
|
2380
|
-
private buildRuleDeclarationIndexes;
|
|
2381
2413
|
private buildContainingMediaStacks;
|
|
2382
|
-
private
|
|
2414
|
+
private buildKeyframeIndexes;
|
|
2383
2415
|
private buildContainerNameIndexes;
|
|
2384
|
-
private buildElementKinds;
|
|
2385
|
-
private buildFilesWithLayers;
|
|
2386
|
-
private buildSelectorPseudoClassIndex;
|
|
2387
2416
|
/**
|
|
2388
2417
|
* Sort each declarationsByProperty list by sourceOrder and populate
|
|
2389
2418
|
* multiDeclarationProperties with only those having 2+ entries.
|
|
2390
2419
|
*/
|
|
2391
2420
|
private buildMultiDeclarationProperties;
|
|
2392
|
-
/**
|
|
2393
|
-
* Collect declarations whose parent rule is inside a @keyframes block.
|
|
2394
|
-
*/
|
|
2395
|
-
private buildKeyframeDeclarations;
|
|
2396
|
-
private buildKeyframeLayoutMutationsByName;
|
|
2397
|
-
/**
|
|
2398
|
-
* Collect rules with no declarations and no nested rules.
|
|
2399
|
-
*/
|
|
2400
|
-
private buildEmptyRules;
|
|
2401
|
-
/**
|
|
2402
|
-
* Collect @keyframes with no effective keyframe declarations.
|
|
2403
|
-
*/
|
|
2404
|
-
private buildEmptyKeyframes;
|
|
2405
|
-
private buildDeclarationDerivedIndexes;
|
|
2406
|
-
private buildSelectorDerivedIndexes;
|
|
2407
2421
|
private buildLayoutPropertiesByClassToken;
|
|
2408
|
-
private
|
|
2409
|
-
private buildFontFaceDescriptorsByFamily;
|
|
2410
|
-
private buildRuleDerivedIndexes;
|
|
2422
|
+
private buildFontIndexes;
|
|
2411
2423
|
buildUnusedIndexes(): void;
|
|
2412
2424
|
}
|
|
2413
2425
|
|
|
@@ -2533,18 +2545,26 @@ declare const enum LayoutSignalUnit {
|
|
|
2533
2545
|
Keyword = 2,
|
|
2534
2546
|
Unknown = 3
|
|
2535
2547
|
}
|
|
2548
|
+
declare const enum SignalValueKind {
|
|
2549
|
+
Known = 0,
|
|
2550
|
+
Unknown = 1
|
|
2551
|
+
}
|
|
2552
|
+
declare const enum SignalQuality {
|
|
2553
|
+
Exact = 0,
|
|
2554
|
+
Estimated = 1
|
|
2555
|
+
}
|
|
2536
2556
|
interface LayoutKnownSignalValue {
|
|
2537
|
-
readonly kind:
|
|
2557
|
+
readonly kind: SignalValueKind.Known;
|
|
2538
2558
|
readonly name: LayoutSignalName;
|
|
2539
2559
|
readonly normalized: string;
|
|
2540
2560
|
readonly source: LayoutSignalSource;
|
|
2541
2561
|
readonly guard: LayoutRuleGuard;
|
|
2542
2562
|
readonly unit: LayoutSignalUnit;
|
|
2543
2563
|
readonly px: number | null;
|
|
2544
|
-
readonly quality:
|
|
2564
|
+
readonly quality: SignalQuality;
|
|
2545
2565
|
}
|
|
2546
2566
|
interface LayoutUnknownSignalValue {
|
|
2547
|
-
readonly kind:
|
|
2567
|
+
readonly kind: SignalValueKind.Unknown;
|
|
2548
2568
|
readonly name: LayoutSignalName;
|
|
2549
2569
|
readonly source: LayoutSignalSource | null;
|
|
2550
2570
|
readonly guard: LayoutRuleGuard;
|
|
@@ -2782,10 +2802,10 @@ type LayoutReservedSpaceReason = "height" | "block-size" | "min-height" | "min-b
|
|
|
2782
2802
|
interface LayoutReservedSpaceFact {
|
|
2783
2803
|
readonly hasReservedSpace: boolean;
|
|
2784
2804
|
readonly reasons: readonly LayoutReservedSpaceReason[];
|
|
2785
|
-
readonly hasUsableInlineDimension: boolean;
|
|
2786
|
-
readonly hasUsableBlockDimension: boolean;
|
|
2787
2805
|
readonly hasContainIntrinsicSize: boolean;
|
|
2788
2806
|
readonly hasUsableAspectRatio: boolean;
|
|
2807
|
+
readonly hasDeclaredInlineDimension: boolean;
|
|
2808
|
+
readonly hasDeclaredBlockDimension: boolean;
|
|
2789
2809
|
}
|
|
2790
2810
|
declare const enum LayoutScrollAxis {
|
|
2791
2811
|
None = 0,
|
|
@@ -2843,46 +2863,35 @@ interface LayoutNormalizedRuleDeclaration {
|
|
|
2843
2863
|
readonly startColumn: number;
|
|
2844
2864
|
readonly propertyLength: number;
|
|
2845
2865
|
}
|
|
2846
|
-
interface
|
|
2866
|
+
interface LayoutElementRecord {
|
|
2867
|
+
readonly ref: LayoutElementRef | null;
|
|
2868
|
+
readonly edges: readonly LayoutMatchEdge[];
|
|
2869
|
+
readonly cascade: ReadonlyMap<string, LayoutCascadedDeclaration>;
|
|
2870
|
+
readonly snapshot: LayoutSignalSnapshot;
|
|
2871
|
+
readonly hotSignals: LayoutSnapshotHotSignals;
|
|
2872
|
+
readonly reservedSpace: LayoutReservedSpaceFact;
|
|
2873
|
+
readonly scrollContainer: LayoutScrollContainerFact;
|
|
2874
|
+
readonly flowParticipation: LayoutFlowParticipationFact;
|
|
2875
|
+
readonly containingBlock: LayoutContainingBlockFact;
|
|
2876
|
+
readonly conditionalDelta: ReadonlyMap<LayoutSignalName, LayoutConditionalSignalDeltaFact> | null;
|
|
2877
|
+
readonly baselineOffsets: ReadonlyMap<LayoutSignalName, readonly number[]> | null;
|
|
2878
|
+
}
|
|
2879
|
+
interface LayoutGraph {
|
|
2847
2880
|
readonly elements: readonly LayoutElementNode[];
|
|
2848
2881
|
readonly childrenByParentNode: ReadonlyMap<LayoutElementNode, readonly LayoutElementNode[]>;
|
|
2849
2882
|
readonly elementBySolidFileAndId: ReadonlyMap<string, ReadonlyMap<number, LayoutElementNode>>;
|
|
2850
2883
|
readonly elementRefsBySolidFileAndId: ReadonlyMap<string, ReadonlyMap<number, LayoutElementRef>>;
|
|
2851
2884
|
readonly elementsByTagName: ReadonlyMap<string, readonly LayoutElementNode[]>;
|
|
2852
2885
|
readonly measurementNodeByRootKey: ReadonlyMap<string, LayoutElementNode>;
|
|
2853
|
-
/**
|
|
2854
|
-
* Maps component call-site nodes to their resolved host DOM element reference.
|
|
2855
|
-
* Only populated for nodes that represent a component resolved to a concrete DOM
|
|
2856
|
-
* element. Native DOM element nodes and unresolvable components are absent.
|
|
2857
|
-
* Used by rules that need to inspect the host element's JSX attributes (e.g.
|
|
2858
|
-
* dynamic `width`/`height` expressions not capturable as static strings).
|
|
2859
|
-
*/
|
|
2860
2886
|
readonly hostElementRefsByNode: ReadonlyMap<LayoutElementNode, LayoutElementRef>;
|
|
2861
|
-
}
|
|
2862
|
-
interface LayoutGraphCascade {
|
|
2863
2887
|
readonly styleRules: readonly LayoutStyleRuleNode[];
|
|
2864
2888
|
readonly applies: readonly LayoutMatchEdge[];
|
|
2865
2889
|
readonly cssScopeBySolidFile: ReadonlyMap<string, readonly string[]>;
|
|
2866
|
-
readonly appliesByNode: ReadonlyMap<LayoutElementNode, readonly LayoutMatchEdge[]>;
|
|
2867
2890
|
readonly selectorCandidatesByNode: ReadonlyMap<LayoutElementNode, readonly number[]>;
|
|
2868
2891
|
readonly selectorsById: ReadonlyMap<number, SelectorEntity>;
|
|
2869
|
-
readonly
|
|
2870
|
-
readonly snapshotByElementNode: WeakMap<LayoutElementNode, LayoutSignalSnapshot>;
|
|
2871
|
-
readonly snapshotHotSignalsByNode: ReadonlyMap<LayoutElementNode, LayoutSnapshotHotSignals>;
|
|
2872
|
-
}
|
|
2873
|
-
interface LayoutGraphFacts {
|
|
2874
|
-
readonly reservedSpaceFactsByNode: ReadonlyMap<LayoutElementNode, LayoutReservedSpaceFact>;
|
|
2875
|
-
readonly scrollContainerFactsByNode: ReadonlyMap<LayoutElementNode, LayoutScrollContainerFact>;
|
|
2876
|
-
readonly flowParticipationFactsByNode: ReadonlyMap<LayoutElementNode, LayoutFlowParticipationFact>;
|
|
2877
|
-
readonly containingBlockFactsByNode: ReadonlyMap<LayoutElementNode, LayoutContainingBlockFact>;
|
|
2878
|
-
readonly conditionalSignalDeltaFactsByNode: ReadonlyMap<LayoutElementNode, ReadonlyMap<LayoutSignalName, LayoutConditionalSignalDeltaFact>>;
|
|
2879
|
-
readonly baselineOffsetFactsByNode: ReadonlyMap<LayoutElementNode, ReadonlyMap<LayoutSignalName, readonly number[]>>;
|
|
2880
|
-
}
|
|
2881
|
-
interface LayoutGraphCohorts {
|
|
2892
|
+
readonly records: ReadonlyMap<LayoutElementNode, LayoutElementRecord>;
|
|
2882
2893
|
readonly cohortStatsByParentNode: ReadonlyMap<LayoutElementNode, LayoutCohortStats>;
|
|
2883
2894
|
readonly contextByParentNode: ReadonlyMap<LayoutElementNode, AlignmentContext>;
|
|
2884
|
-
}
|
|
2885
|
-
interface LayoutGraphIndexes {
|
|
2886
2895
|
readonly elementsWithConditionalDeltaBySignal: ReadonlyMap<LayoutSignalName, readonly LayoutElementNode[]>;
|
|
2887
2896
|
readonly elementsWithConditionalOverflowDelta: readonly LayoutElementNode[];
|
|
2888
2897
|
readonly elementsWithConditionalOffsetDelta: readonly LayoutElementNode[];
|
|
@@ -2892,8 +2901,6 @@ interface LayoutGraphIndexes {
|
|
|
2892
2901
|
readonly statefulSelectorEntriesByRuleId: ReadonlyMap<number, readonly LayoutStatefulSelectorEntry[]>;
|
|
2893
2902
|
readonly statefulNormalizedDeclarationsByRuleId: ReadonlyMap<number, readonly LayoutNormalizedRuleDeclaration[]>;
|
|
2894
2903
|
readonly statefulBaseValueIndex: ReadonlyMap<string, ReadonlyMap<string, ReadonlySet<string>>>;
|
|
2895
|
-
}
|
|
2896
|
-
interface LayoutGraph extends LayoutGraphTopology, LayoutGraphCascade, LayoutGraphFacts, LayoutGraphCohorts, LayoutGraphIndexes {
|
|
2897
2904
|
readonly perf: LayoutPerfStatsMutable;
|
|
2898
2905
|
}
|
|
2899
2906
|
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
RULES,
|
|
3
3
|
RULES_BY_CATEGORY,
|
|
4
4
|
getRule
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NFDA6LAI.js";
|
|
6
6
|
import {
|
|
7
7
|
CSSPlugin,
|
|
8
8
|
Level,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
runSolidRules,
|
|
21
21
|
scanDependencyCustomProperties,
|
|
22
22
|
setActivePolicy
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-SSLKXOHI.js";
|
|
24
24
|
import "./chunk-EGRHWZRV.js";
|
|
25
25
|
|
|
26
26
|
// src/runner.ts
|
package/dist/rules-manifest.cjs
CHANGED
|
@@ -260,19 +260,6 @@ var RULES = [
|
|
|
260
260
|
"paragraphSpacingTooSmall": "Paragraph spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` ({{minMultiplier}}\xD7 font-size) for policy `{{policy}}`."
|
|
261
261
|
}
|
|
262
262
|
},
|
|
263
|
-
{
|
|
264
|
-
"id": "css-policy-touch-target",
|
|
265
|
-
"severity": "warn",
|
|
266
|
-
"description": "Enforce minimum interactive element sizes per accessibility policy.",
|
|
267
|
-
"fixable": false,
|
|
268
|
-
"category": "css-a11y",
|
|
269
|
-
"plugin": "css",
|
|
270
|
-
"messages": {
|
|
271
|
-
"heightTooSmall": "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
272
|
-
"widthTooSmall": "`{{property}}` of `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`.",
|
|
273
|
-
"paddingTooSmall": "Horizontal padding `{{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for `{{element}}` elements in policy `{{policy}}`."
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
263
|
{
|
|
277
264
|
"id": "css-policy-typography",
|
|
278
265
|
"severity": "warn",
|
|
@@ -296,6 +283,21 @@ var RULES = [
|
|
|
296
283
|
"missingReducedMotion": "Animated selector `{{selector}}` lacks prefers-reduced-motion override."
|
|
297
284
|
}
|
|
298
285
|
},
|
|
286
|
+
{
|
|
287
|
+
"id": "jsx-layout-policy-touch-target",
|
|
288
|
+
"severity": "warn",
|
|
289
|
+
"description": "Enforce minimum interactive element sizes per accessibility policy via resolved layout signals.",
|
|
290
|
+
"fixable": false,
|
|
291
|
+
"category": "css-a11y",
|
|
292
|
+
"plugin": "cross-file",
|
|
293
|
+
"messages": {
|
|
294
|
+
"heightTooSmall": "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
295
|
+
"widthTooSmall": "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
296
|
+
"paddingTooSmall": "Horizontal padding `{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.",
|
|
297
|
+
"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.",
|
|
298
|
+
"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."
|
|
299
|
+
}
|
|
300
|
+
},
|
|
299
301
|
{
|
|
300
302
|
"id": "css-no-discrete-transition",
|
|
301
303
|
"severity": "error",
|
|
@@ -1954,7 +1956,7 @@ var RULES = [
|
|
|
1954
1956
|
];
|
|
1955
1957
|
var RULES_BY_CATEGORY = {
|
|
1956
1958
|
"correctness": [{ "id": "avoid-conditional-spreads", "severity": "error", "description": "Disallow conditional spread operators that create empty objects. Patterns like `...(condition ? {...} : {})` are fragile and create unnecessary object creations.", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "avoidConditionalSpread": "Avoid conditional spread with empty object fallback. Instead of `...(cond ? {...} : {})`, build the object first with conditional property assignment, then spread once.", "avoidLogicalAndSpread": "Avoid logical AND spread pattern. Instead of `...(cond && {...})`, use explicit conditional property assignment for clarity." } }, { "id": "avoid-non-null-assertions", "severity": "error", "description": "Disallow non-null assertion operator (`!`). Use optional chaining, nullish coalescing, or proper type narrowing instead.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "avoidNonNull": 'Avoid non-null assertion on "{{name}}". Non-null assertions bypass type safety. Use optional chaining (`?.`), nullish coalescing (`??`), or proper type narrowing instead.' } }, { "id": "avoid-object-assign", "severity": "error", "description": "Disallow Object.assign(). Prefer object spread syntax or structuredClone() for copying objects.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "avoidMerge": "Avoid Object.assign() for merging. Use object spread syntax { ...obj } instead.", "avoidMutation": "Avoid Object.assign() for mutation. Consider immutable patterns like { ...existing, ...props }." } }, { "id": "avoid-object-spread", "severity": "error", "description": "Disallow object spread operators that break Solid's fine-grained reactivity.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "avoidObjectCopy": "Avoid object spread for copying. Use direct property access.", "avoidObjectMerge": "Avoid object spread for merging. Use mergeProps() from 'solid-js'.", "avoidObjectUpdate": "Avoid object spread for updates. Use produce() or direct assignment.", "avoidJsxSpread": "Avoid JSX prop spreading. Use splitProps() to separate props.", "avoidRestDestructure": "Avoid rest destructuring. Use splitProps() from 'solid-js'.", "avoidPropsSpread": "Spreading props breaks reactivity. Use splitProps() to separate known props.", "avoidStoreSpread": "Spreading store creates a static snapshot. Access properties directly.", "avoidSignalSpread": "Spreading signal result captures current value. Wrap in createMemo().", "avoidClassListSpread": "Spreading in classList breaks reactivity. Wrap in createMemo().", "avoidStyleSpread": "Spreading in style breaks reactivity. Wrap in createMemo().", "unnecessarySplitProps": "Unnecessary splitProps with empty array. Remove it and use {{source}} directly." } }, { "id": "avoid-type-casting", "severity": "error", "description": "Disallow type casting methods that bypass TypeScript's type safety. Includes unnecessary casts, double assertions, casting to any, type predicates, and unsafe generic assertions.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "unnecessaryCast": `Unnecessary type assertion: "{{name}}" is already of type "{{exprType}}", which is assignable to "{{type}}". Remove the cast - it adds noise and suggests you don't understand the types.`, "doubleAssertion": 'Double assertion detected: "{{name}}" is cast through unknown/any to "{{type}}". This bypasses type safety. You are creating sloppy architecture.', "castToAny": 'Casting "{{name}}" to `any` disables all type checking. Use `unknown` with proper type guards, or fix the underlying type issue.', "castToUnknown": "Casting to `unknown` requires runtime type checks before use. You are creating sloppy architecture.", "simpleAssertion": 'Type assertion on "{{name}}" to "{{type}}" bypasses type checking. Why are you doing this? Do you EVEN need this? This is sloppy architecture.', "assertionInLoop": 'Type assertion on "{{name}}" inside a loop. Repeated casts to "{{type}}" without validation can mask type errors. Consider validating the type once before the loop.', "importAssertion": 'Type assertion on dynamic import to "{{type}}". Import types should be validated at runtime or use proper module type declarations.', "typePredicate": 'Type predicate function asserts "{{param}}" is "{{type}}". Why are you doing this? Do you EVEN need this? This is sloppy architecture.', "unsafeGeneric": 'Casting to generic type parameter "{{typeParam}}" without runtime validation. The function returns an unverified type. This is sloppy architecture.' } }, { "id": "avoid-unsafe-type-annotations", "severity": "error", "description": "Disallow `any` and `unknown` in value-level type annotation positions (parameters, returns, variables, properties)", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "anyParameter": "Parameter '{{name}}' is typed `any`{{inFunction}}. This disables type checking for all callers. Use a specific type, a generic, or `unknown` with proper type narrowing.", "anyReturn": "Function '{{name}}' returns `any`. This disables type checking for all callers. Use a specific return type.", "anyVariable": "Variable '{{name}}' is typed `any`. This disables all type checking on this variable. Use a specific type or `unknown` with type narrowing.", "anyProperty": "Property '{{name}}' is typed `any`. This disables type checking for all accesses. Use a specific type.", "unknownParameter": "Parameter '{{name}}' is typed `unknown`{{inFunction}}. Callers can pass anything and the function body requires type narrowing on every use. Use a specific type or a generic constraint.", "unknownReturn": "Function '{{name}}' returns `unknown`. Callers must narrow the return value before use. Use a specific return type or a generic.", "unknownVariable": "Variable '{{name}}' is typed `unknown`. Every use requires type narrowing. Use a specific type or parse the value at the boundary.", "unknownProperty": "Property '{{name}}' is typed `unknown`. Every access requires type narrowing. Use a specific type." } }, { "id": "event-handlers", "severity": "error", "description": "Enforce naming DOM element event handlers consistently and prevent Solid's analysis from misunderstanding whether a prop should be an event handler.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "detectedAttr": 'The "{{name}}" prop looks like an event handler but has a static value ({{staticValue}}), so Solid will treat it as an attribute instead of attaching an event listener. Use attr:{{name}} to make this explicit, or provide a function value.', "naming": 'The "{{name}}" prop is ambiguous. Solid cannot determine if this is an event handler or an attribute. Use {{handlerName}} for an event handler, or {{attrName}} for an attribute.', "capitalization": 'The "{{name}}" prop should be {{fixedName}} for Solid to recognize it as an event handler. Event handlers use camelCase with an uppercase letter after "on".', "nonstandard": 'The "{{name}}" prop uses a nonstandard event name. Use {{fixedName}} instead, which is the standard DOM event name that Solid recognizes.', "makeHandler": "Change {{name}} to {{handlerName}} (event handler).", "makeAttr": "Change {{name}} to {{attrName}} (attribute).", "spreadHandler": 'The "{{name}}" prop is being spread into JSX, which prevents Solid from attaching it as an event listener. Add it directly as a JSX attribute instead: {{name}}={...}.' } }, { "id": "missing-jsdoc-comments", "severity": "error", "description": "Require JSDoc comments on functions with appropriate tags for parameters, return values, and throws.", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "missingJsdoc": "Function '{{name}}' is missing a JSDoc comment.", "missingParam": "JSDoc for '{{name}}' is missing @param tag for '{{param}}'.", "missingReturn": "JSDoc for '{{name}}' is missing @returns tag.", "missingThrows": "JSDoc for '{{name}}' is missing @throws tag.", "missingExample": "JSDoc for '{{name}}' is missing @example tag.", "missingClassJsdoc": "Class '{{name}}' is missing a JSDoc comment.", "missingPropertyJsdoc": "Property '{{name}}' is missing a JSDoc comment." } }, { "id": "no-ai-slop-comments", "severity": "error", "description": "Disallow comments containing specified forbidden words or phrases. Useful for enforcing comment style guidelines and detecting AI-generated boilerplate.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "forbiddenWord": "Comment contains forbidden word '{{word}}'." } }, { "id": "no-array-handlers", "severity": "error", "description": "Disallow array handlers in JSX event properties.", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "noArrayHandlers": 'Passing an array to "{{handlerName}}" is type-unsafe. The array syntax `[handler, data]` passes data as the first argument, making the event object the second argument. Use a closure instead: `{{handlerName}}={() => handler(data)}`.' } }, { "id": "no-banner-comments", "severity": "error", "description": "Disallow banner-style comments with repeated separator characters.", "fixable": true, "category": "correctness", "plugin": "solid", "messages": { "banner": "Avoid banner-style comments with repeated separator characters. Use simple comments instead." } }, { "id": "no-destructure", "severity": "error", "description": "Disallow destructuring props in Solid components. Props must be accessed via property access (props.x) to preserve reactivity.", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "noDestructure": "Destructuring component props breaks Solid's reactivity. Props are reactive getters, so `{ a }` captures the value at component creation time and won't update. Use `props.a` to access props reactively.", "noDestructureWithDefaults": "Destructuring component props breaks Solid's reactivity. For default values, use `mergeProps({ a: defaultValue }, props)` instead of `{ a = defaultValue }`.", "noDestructureWithRest": "Destructuring component props breaks Solid's reactivity. For rest patterns, use `splitProps(props, ['a', 'b'])` instead of `{ a, b, ...rest }`.", "noDestructureWithBoth": "Destructuring component props breaks Solid's reactivity. For default values with rest, use `splitProps(mergeProps({ a: defaultValue }, props), ['a'])` to combine both patterns." } }, { "id": "no-inline-imports", "severity": "error", "description": "Disallow inline type imports. Import types at the top of the file for clarity and maintainability.", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "inlineImport": "Avoid inline imports. Import `{{specifier}}` at the top of the file instead." } }, { "id": "string-concat-in-loop", "severity": "error", "description": "Disallow string concatenation with += inside loops. Use array.push() and .join() instead.", "fixable": false, "category": "correctness", "plugin": "solid", "messages": { "stringConcatInLoop": "Avoid string concatenation with += inside loops. Use an array with .push() and .join() instead." } }],
|
|
1957
|
-
"css-a11y": [{ "id": "css-no-outline-none-without-focus-visible", "severity": "error", "description": "Disallow removing outline without explicit focus-visible replacement.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "missingFocusVisible": "Focus outline removed without matching `:focus-visible` replacement." } }, { "id": "css-policy-contrast", "severity": "warn", "description": "Enforce minimum contrast ratio between foreground and background colors per accessibility policy.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "insufficientContrast": "Contrast ratio `{{ratio}}:1` between `{{fg}}` and `{{bg}}` is below the minimum `{{min}}:1` for `{{textSize}}` text in policy `{{policy}}`." } }, { "id": "css-policy-spacing", "severity": "warn", "description": "Enforce minimum letter-spacing, word-spacing, and paragraph spacing per accessibility policy.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "letterSpacingTooSmall": "Letter spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.", "wordSpacingTooSmall": "Word spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.", "paragraphSpacingTooSmall": "Paragraph spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` ({{minMultiplier}}\xD7 font-size) for policy `{{policy}}`." } }, { "id": "css-policy-
|
|
1959
|
+
"css-a11y": [{ "id": "css-no-outline-none-without-focus-visible", "severity": "error", "description": "Disallow removing outline without explicit focus-visible replacement.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "missingFocusVisible": "Focus outline removed without matching `:focus-visible` replacement." } }, { "id": "css-policy-contrast", "severity": "warn", "description": "Enforce minimum contrast ratio between foreground and background colors per accessibility policy.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "insufficientContrast": "Contrast ratio `{{ratio}}:1` between `{{fg}}` and `{{bg}}` is below the minimum `{{min}}:1` for `{{textSize}}` text in policy `{{policy}}`." } }, { "id": "css-policy-spacing", "severity": "warn", "description": "Enforce minimum letter-spacing, word-spacing, and paragraph spacing per accessibility policy.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "letterSpacingTooSmall": "Letter spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.", "wordSpacingTooSmall": "Word spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.", "paragraphSpacingTooSmall": "Paragraph spacing `{{value}}` ({{resolved}}em) is below the minimum `{{min}}em` ({{minMultiplier}}\xD7 font-size) for policy `{{policy}}`." } }, { "id": "css-policy-typography", "severity": "warn", "description": "Enforce minimum font sizes and line heights per accessibility policy.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "fontTooSmall": "Font size `{{value}}` ({{resolved}}px) is below the `{{context}}` minimum of `{{min}}px` for policy `{{policy}}`.", "lineHeightTooSmall": "Line height `{{value}}` is below the `{{context}}` minimum of `{{min}}` for policy `{{policy}}`." } }, { "id": "css-require-reduced-motion-override", "severity": "warn", "description": "Require reduced-motion override for animated selectors.", "fixable": false, "category": "css-a11y", "plugin": "css", "messages": { "missingReducedMotion": "Animated selector `{{selector}}` lacks prefers-reduced-motion override." } }, { "id": "jsx-layout-policy-touch-target", "severity": "warn", "description": "Enforce minimum interactive element sizes per accessibility policy via resolved layout signals.", "fixable": false, "category": "css-a11y", "plugin": "cross-file", "messages": { "heightTooSmall": "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.", "widthTooSmall": "`{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.", "paddingTooSmall": "Horizontal padding `{{signal}}` of `{{value}}px` is below the minimum `{{min}}px` for interactive element `<{{tag}}>` in policy `{{policy}}`.", "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.", "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." } }],
|
|
1958
1960
|
"css-animation": [{ "id": "css-no-discrete-transition", "severity": "error", "description": "Disallow transitions on discrete CSS properties.", "fixable": false, "category": "css-animation", "plugin": "css", "messages": { "discreteTransition": "Property `{{property}}` is discrete and should not be transitioned." } }, { "id": "css-no-empty-keyframes", "severity": "error", "description": "Disallow empty @keyframes rules.", "fixable": false, "category": "css-animation", "plugin": "css", "messages": { "emptyKeyframes": "@keyframes `{{name}}` has no effective keyframes." } }, { "id": "no-layout-property-animation", "severity": "warn", "description": "Disallow animating layout-affecting properties.", "fixable": false, "category": "css-animation", "plugin": "css", "messages": { "avoidLayoutAnimation": "Avoid animating layout property `{{property}}`. Prefer transform or opacity to reduce layout thrashing." } }, { "id": "no-transition-all", "severity": "warn", "description": "Disallow transition: all and transition-property: all.", "fixable": false, "category": "css-animation", "plugin": "css", "messages": { "avoidTransitionAll": "Avoid `transition: all`. Transition specific properties to reduce unnecessary style and paint work." } }, { "id": "no-unknown-animation-name", "severity": "error", "description": "Disallow animation names that do not match declared keyframes.", "fixable": false, "category": "css-animation", "plugin": "css", "messages": { "unknownAnimationName": "Animation name `{{name}}` in `{{property}}` does not match any declared @keyframes." } }, { "id": "no-unused-keyframes", "severity": "warn", "description": "Disallow unused @keyframes declarations.", "fixable": false, "category": "css-animation", "plugin": "css", "messages": { "unusedKeyframes": "@keyframes `{{name}}` is never referenced by animation declarations." } }],
|
|
1959
1961
|
"css-cascade": [{ "id": "declaration-no-overridden-within-rule", "severity": "warn", "description": "Disallow duplicate declarations of the same property within a single rule block.", "fixable": false, "category": "css-cascade", "plugin": "css", "messages": { "overriddenWithinRule": "Declaration `{{property}}` is overridden later in the same rule. Keep one final declaration per property." } }, { "id": "media-query-overlap-conflict", "severity": "warn", "description": "Disallow conflicting declarations in partially overlapping media queries.", "fixable": false, "category": "css-cascade", "plugin": "css", "messages": { "mediaOverlapConflict": "Overlapping media queries set different `{{property}}` values for `{{selector}}` in the same overlap range." } }, { "id": "no-descending-specificity-conflict", "severity": "warn", "description": "Disallow lower-specificity selectors after higher-specificity selectors for the same property.", "fixable": false, "category": "css-cascade", "plugin": "css", "messages": { "descendingSpecificity": "Lower-specificity selector `{{laterSelector}}` appears after `{{earlierSelector}}` for `{{property}}`, creating brittle cascade behavior." } }, { "id": "no-layer-order-inversion", "severity": "warn", "description": "Disallow source-order assumptions that are inverted by layer precedence.", "fixable": false, "category": "css-cascade", "plugin": "css", "messages": { "layerOrderInversion": "Declaration for `{{property}}` in selector `{{selector}}` appears later but is overridden by an earlier declaration due to @layer precedence." } }, { "id": "no-redundant-override-pairs", "severity": "warn", "description": "Disallow declarations that are deterministically overridden in the same selector context.", "fixable": false, "category": "css-cascade", "plugin": "css", "messages": { "redundantOverride": "Declaration `{{property}}` is always overridden later by the same selector in the same cascade context." } }],
|
|
1960
1962
|
"css-jsx": [{ "id": "css-no-unreferenced-component-class", "severity": "warn", "description": "Detect CSS classes that are never referenced by static JSX class attributes.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "unreferencedClass": "CSS class '{{className}}' is defined but not referenced by static JSX class attributes" } }, { "id": "jsx-classlist-boolean-values", "severity": "error", "description": "Require classList values to be boolean-like expressions.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "nonBooleanValue": "classList value for `{{name}}` must be boolean." } }, { "id": "jsx-classlist-no-accessor-reference", "severity": "error", "description": "Disallow passing accessor references directly as classList values.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "accessorReference": "Signal accessor `{{name}}` must be called in classList value (use {{name}}())." } }, { "id": "jsx-classlist-no-constant-literals", "severity": "warn", "description": "Disallow classList entries with constant true/false values.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "constantEntry": "classList entry `{{name}}: {{value}}` is constant; move it to static class." } }, { "id": "jsx-classlist-static-keys", "severity": "error", "description": "Require classList keys to be static and non-computed.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "nonStaticKey": "classList key must be statically known for reliable class mapping." } }, { "id": "jsx-layout-classlist-geometry-toggle", "severity": "warn", "description": "Flag classList-driven class toggles that map to layout-affecting CSS geometry changes.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "classListGeometryToggle": "classList toggles '{{className}}', and matching CSS changes layout-affecting '{{property}}', which can cause CLS." } }, { "id": "jsx-layout-fill-image-parent-must-be-sized", "severity": "warn", "description": "Require stable parent size and positioning for fill-image component usage.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "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." } }, { "id": "jsx-layout-picture-source-ratio-consistency", "severity": "warn", "description": "Require consistent intrinsic aspect ratios across <picture> sources and fallback image.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "inconsistentPictureRatio": "`<picture>` source ratio {{sourceRatio}} differs from fallback img ratio {{imgRatio}}, which can cause reserved-space mismatch and CLS." } }, { "id": "jsx-layout-unstable-style-toggle", "severity": "warn", "description": "Flag dynamic inline style values on layout-sensitive properties that can trigger CLS.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "unstableLayoutStyleToggle": "Dynamic style value for '{{property}}' can toggle layout geometry at runtime and cause CLS." } }, { "id": "jsx-no-duplicate-class-token-class-classlist", "severity": "warn", "description": "Disallow duplicate class tokens between class and classList on the same JSX element.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "duplicateClassToken": "Class token `{{name}}` appears in both class and classList." } }, { "id": "jsx-no-undefined-css-class", "severity": "error", "description": "Detect undefined CSS class names in JSX", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "undefinedClass": "CSS class '{{className}}' is not defined in project CSS files" } }, { "id": "jsx-style-kebab-case-keys", "severity": "error", "description": "Require kebab-case keys in JSX style object literals.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "kebabStyleKey": "Style key `{{name}}` should be `{{kebab}}` in Solid style objects." } }, { "id": "jsx-style-no-function-values", "severity": "error", "description": "Disallow function values in JSX style objects.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "functionStyleValue": "Style value for `{{name}}` is a function; pass computed value instead." } }, { "id": "jsx-style-no-unused-custom-prop", "severity": "warn", "description": "Detect inline style custom properties that are never consumed by CSS var() references.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "unusedInlineVar": "Inline custom property `{{name}}` is never read via var({{name}})." } }, { "id": "jsx-style-policy", "severity": "warn", "description": "Enforce accessibility policy thresholds on inline JSX style objects.", "fixable": false, "category": "css-jsx", "plugin": "cross-file", "messages": { "fontTooSmall": "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for policy `{{policy}}`.", "lineHeightTooSmall": "Inline style `line-height: {{value}}` is below the minimum `{{min}}` for policy `{{policy}}`.", "heightTooSmall": "Inline style `{{prop}}: {{value}}` ({{resolved}}px) is below the minimum `{{min}}px` for interactive elements in policy `{{policy}}`.", "letterSpacingTooSmall": "Inline style `letter-spacing: {{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`.", "wordSpacingTooSmall": "Inline style `word-spacing: {{value}}` ({{resolved}}em) is below the minimum `{{min}}em` for policy `{{policy}}`." } }],
|