feat(cli): Add exfig lint command for Figma file validation#80
Merged
Conversation
Validates Figma file structure against PKL config before export. 7 rules checking naming conventions, frame/page structure, variable bindings, dark mode setup, and component types. Rules: - frame-page-match: frame/page names exist in Figma file - naming-convention: component names match nameValidateRegexp - component-not-frame: configured frames have published components - deleted-variables: no deletedButReferenced variables - alias-chain-integrity: alias chains resolve without broken refs - dark-mode-variables: fills bound to Variables when variablesDarkMode - dark-mode-suffix: light components have matching _dark pairs Supports --rules filter, --format json for CI, --severity filter, and exit code 1 on errors.
Add lint command section, troubleshooting entries for config type reference, Paint.visible, and variablesColors location.
Update exfig.usage.kdl with lint subcommand and flags. Add Linting section to Usage.md with rules table. Add Linting in CI section to CICDIntegration.md.
alias-chain-integrity: recognize cross-file variable IDs (long hex hash prefix) as external library references — not broken chains. dark-mode-suffix: only check components within configured export frames, not all components in the entire Figma file.
21 tests covering FramePageMatchRule, NamingConventionRule, DeletedVariablesRule, AliasChainIntegrityRule, ComponentNotFrameRule, DarkModeSuffixRule, and LintEngine with mock Figma API responses. refactor(lint): improve output, progress, and rules - Add per-rule spinner progress: "Checking X... (2/7)" - Replace verbose text output with compact table format - Add duplicate-component-names rule (catches silent overwrites) - Remove alias-chain-integrity from defaults (cross-file refs normal) - Keep dark-mode-suffix as warning (not all icons need dark pairs) - Errors sorted first, then warnings perf(lint): cache API responses and show rule names in spinner - Add LintDataCache actor to deduplicate Components/Variables API calls (5 rules shared the same ComponentsEndpoint, now 1 request per fileId) - Add withSpinnerMessage to TerminalUI for dynamic message updates - Spinner now shows: "Checking Dark mode fills... (6/7)" fix(lint): downgrade deleted-variables to warning (ExFig handles them) fix(lint): skip root frame fills in dark-mode-variables check Root component frames often have background #FFFFFF fills that aren't meant to be variable-bound. Only check fills on child vector nodes, not the component's root frame. fix(lint): filter dark-mode-variables by page name from config fix(lint): skip RTL variant components in dark-mode-variables check fix(lint): filter duplicate-component-names by configured frame/page fix(lint): skip RTL variants in duplicate-component-names check docs: add lint rule patterns and cp gotcha to CLAUDE.md docs: add lint to ExFig.md, GettingStarted.md, and regenerate llms feat(mcp): add exfig_lint tool for Figma structure validation Returns JSON diagnostics with errors/warnings. Supports rule filtering and severity threshold. Uses LintDataCache for dedup. test(lint): add tests for duplicate-component-names rule and RTL skip fix(lint): suppress spinner in --format json mode for clean stdout
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive lint command to validate Figma file structures against PKL configurations. It includes a new LintEngine with seven built-in rules covering naming conventions, frame/page structure, variable bindings, and dark mode setup. The command is integrated into the CLI, MCP server, and documentation. Feedback focuses on performance optimizations, such as caching compiled regular expressions and avoiding redundant dictionary constructions during component iteration.
|
|
||
| let pageNames = Set(components.compactMap(\.containingFrame.pageName)) | ||
| let frameNames = Set(components.compactMap(\.containingFrame.name)) | ||
| var framesByPage: [String: Set<String>] = [:] |
Comment on lines
+36
to
+38
| let regex: NSRegularExpression | ||
| do { | ||
| regex = try NSRegularExpression(pattern: pattern) |
…afety
- Register AliasChainIntegrityRule in default engine (was dead code)
- Replace silent `catch { continue }` with error diagnostics in 6 rules
- Raise engine catch severity from .info to .error, propagate CancellationError
- Add figmaPageName filtering to NamingConventionRule and DarkModeSuffixRule
- Add RTL variant skip to DarkModeSuffixRule
- Use ExpressibleByArgument for --format/--severity (reject invalid values)
- Add Comparable to LintSeverity, remove duplicated severityRank()
- Add diagnostic() factory on LintRule to reduce boilerplate
- Fix Usage.md severities and add missing duplicate-component-names rule
- Add flutter.images to NamingConventionRule
- Add sampling info diagnostic in DarkModeVariablesRule
- Route JSON output through TerminalUI instead of print()
- Validate MCP lint params before expensive PKL eval
- Add engine composition, error handling, and severity filtering tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
exfig lintCLI command that validates Figma file structure against PKL config before exportLintDataCacheactor to deduplicate Figma API calls across rules--format json(auto-quiet)--rulesfilter,--severitythreshold, exit code 1 on errors (CI-ready)exfig_lintfor AI assistant integrationAdditional notes
RTL=On/RTL=Off) are excluded from duplicate and variable checksfigmaFrameName+figmaPageNamefrom PKL config entriesexfig-actionupdated withcommand: lintsupport,lint_rules/lint_severityinputs, Slack notifications