.agents/skills/lint-new/references/style-collector-guide.md
Load this reference when your rule needs to analyze CSS-in-JS style declarations — specifically the dynamic values passed via interpolation.
Use createStyleCollector when your rule needs to:
Do NOT use it when you need to:
createQuasiScanner from src/ast/scanner/index.ts insteadImportDeclaration visitor)createImportTracker)File: src/ast/extractor/index.ts
createStyleCollector(context)
├── createThemeTracker() ← tracks useTheme() / callback theme bindings
├── createStyledExtractor() ← handles styled.div`...` and styled(X)`...`
├── createCssPropExtractor() ← handles css={} and css`...` props
└── createStylePropExtractor() ← handles style={{}} prop
Returns: { collector, visitors, themeTracker }
Each StyleDeclaration in collector.getAll():
interface StyleDeclaration {
property: {
name: string; // Normalized CSS property (e.g., 'background-color')
node: TSESTree.Node; // AST node of the property name
};
values: Array<{
rawNode: TSESTree.Node;
tokenInfo?: {
tokenPath: string; // e.g., 'content.primary', 'border.secondary'
node: TSESTree.Node; // AST node of the token access
};
}>;
}
The collector uses deferred validation — it collects during traversal and you validate in Program:exit:
create(context) {
if (!shouldAnalyze(context)) return {};
const {collector, visitors} = createStyleCollector(context);
return {
...visitors, // Spread the collector's visitors (handles all extraction)
'Program:exit'() {
for (const decl of collector.getAll()) {
// Your validation logic here
}
collector.clear(); // REQUIRED: cleanup for next file
},
};
}
Why deferred? Because a single styled block may have properties and values spread across multiple AST nodes (template quasis + expressions). The collector aggregates them all, then you validate the complete picture.
import {shouldAnalyze} from '../ast/extractor/index';
if (!shouldAnalyze(context)) return {};
This regex-based pre-scan checks for Emotion imports/usage patterns. Returns false for files that clearly don't use styled-components. Always use it as the first line in create() for any rule that uses the style collector or analyzes Emotion patterns.
The #1 mistake is using createStyleCollector when your rule needs to analyze static CSS text. Example:
const Box = styled.div`
color: #ff0000; ← This is static text in a quasi — collector won't see it
background: ${p => p.theme.tokens.background.primary}; ← This IS captured
`;
If your rule detects raw hex colors, nested selectors, or other patterns in the text itself, use createQuasiScanner from src/ast/scanner/index.ts instead. See the "Template Text Analysis" archetype in rule-archetypes.md.