feat: design-first CLI (design:sync/lint, previews:refresh, make:component)#102
Open
anilcancakir wants to merge 3 commits into
Open
feat: design-first CLI (design:sync/lint, previews:refresh, make:component)#102anilcancakir wants to merge 3 commits into
anilcancakir wants to merge 3 commits into
Conversation
Add two magic CLI commands. previews:refresh scans a configurable dir for *.preview.dart files, validates one public *Preview class each, fails fast on slug collisions, sorts deterministically, and atomically writes a _previews.g.dart that returns List<PreviewEntry> from a previewEntries() function (never a top-level const, per sdk#33920) importing PreviewEntry from magic_devtools. make:component scaffolds the canonical 4-file atomic component folder from stubs (variant axes or WindSlotRecipe via --slots) then chains previews:refresh. Mirrors the artisan codegen substrate; no build_runner, no CliBundleCache.purge.
design:sync parses a DESIGN.md (YAML front-matter, single-file dark:
overlay per color role, {group.token} ref resolution) and emits a wind
theme source: a Map<String,String> aliases map keyed by the 17 Step 7
property-prefixed semantic roles (bg-surface, text-fg, border-color-border,
...) with arbitrary-hex light + dark values, plus a brand primary
MaterialColor with a generated 50-900 ramp. Output is drop-in compatible
with MagicStarterTokens.defaultAliases; atomic write, idempotent.
design:lint ports 6 rules (broken-ref, missing-primary, unknown-key with
the dark: overlay whitelisted, section-order, orphaned-tokens, WCAG 4.5:1
contrast via a greenfield sRGB-luminance helper).
Name make:component / previews:refresh / design:sync / design:lint in the README CLI row and the magic-framework SKILL.md CLI section + reference index, so the design-first workflow is discoverable.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR adds a “design-first” workflow to Magic’s artisan plugin by introducing new CLI commands for DESIGN.md-driven Wind theming, preview catalog codegen, and atomic component scaffolding, along with tests and documentation updates across the repo.
Changes:
- Add
design:sync/design:lintcommands backed by a sharedDesignMdParser+ WCAG contrast helper. - Add
previews:refreshcommand plus_previews.g.dartgeneration utilities. - Add
make:componentgenerator (4-file atomic component folder) and new stubs, chainingpreviews:refresh.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test/cli/helpers/design_md_parser_test.dart | Adds unit coverage for DESIGN.md parsing, reference resolution, and WCAG contrast helper. |
| test/cli/commands/previews_refresh_command_test.dart | Tests preview discovery + deterministic index generation + atomic write behavior. |
| test/cli/commands/make_component_command_test.dart | Tests component scaffolding outputs, variants/slots options, and chained previews refresh. |
| test/cli/commands/design_sync_command_test.dart | Verifies generated Wind theme output (aliases + MaterialColor) and atomic/idempotent behavior. |
| test/cli/commands/design_lint_command_test.dart | Tests lint rules: broken refs, contrast warnings, schema typo detection, section ordering. |
| skills/magic-framework/SKILL.md | Updates skill version and documents the new design-first CLI commands. |
| skills/magic-framework/references/cli-commands.md | Extends CLI reference with make:component / previews:refresh / design:* docs. |
| README.md | Updates the Magic CLI feature blurb to include design-first commands. |
| lib/src/cli/magic_artisan_provider.dart | Registers the new commands in the artisan provider. |
| lib/src/cli/helpers/previews_index_writer.dart | Implements preview scanning, deterministic rendering, and atomic index writing. |
| lib/src/cli/helpers/magic_stub_loader.dart | Adds loadFrom() to support explicit stub dir override (testing seam). |
| lib/src/cli/helpers/design_md_parser.dart | Introduces DESIGN.md front matter parsing, reference resolution, section extraction, and contrast helper. |
| lib/src/cli/commands/previews_refresh_command.dart | Adds the previews:refresh command wiring the index writer into artisan. |
| lib/src/cli/commands/make_component_command.dart | Adds make:component generator with stub-based 4-file output + command chaining. |
| lib/src/cli/commands/design_sync_command.dart | Adds design:sync to emit Wind theme aliases + brand MaterialColor from DESIGN.md. |
| lib/src/cli/commands/design_lint_command.dart | Adds design:lint with findings model, rules, and reporting/exit behavior. |
| doc/packages/magic-cli.md | Documents the new commands and the DESIGN.md format in the CLI package docs. |
| CHANGELOG.md | Adds Unreleased entries describing the new commands and workflow. |
| assets/stubs/preview.stub | Adds preview stub used by make:component. |
| assets/stubs/component.stub | Adds component widget stub (single recipe). |
| assets/stubs/component.slots.stub | Adds component widget stub (slot-based recipe). |
| assets/stubs/component.slot_recipe.stub | Adds slot-based recipe stub. |
| assets/stubs/component.recipe.stub | Adds single-recipe stub. |
| assets/stubs/component_index.stub | Adds folder-local barrel stub (exports component + recipe only). |
Comment on lines
+365
to
+373
| switch (finding.severity) { | ||
| case _Severity.error: | ||
| errors++; | ||
| ctx.output.error('$prefix${finding.message}'); | ||
| case _Severity.warning: | ||
| ctx.output.warning('$prefix${finding.message}'); | ||
| case _Severity.info: | ||
| ctx.output.info('$prefix${finding.message}'); | ||
| } |
Comment on lines
+27
to
+28
| /// `design:lint`: validates a `DESIGN.md` against six rules ported from the | ||
| /// design.md reference linter, adapted to the wind-flavored superset. |
| ); | ||
| } | ||
|
|
||
| final yaml = loadYaml(frontMatter); |
Comment on lines
+211
to
+229
| var inFrontMatter = false; | ||
| var seenFirstDelimiter = false; | ||
|
|
||
| for (final line in lines) { | ||
| final trimmed = line.trim(); | ||
| if (trimmed == '---' && !seenFirstDelimiter && headings.isEmpty) { | ||
| inFrontMatter = !inFrontMatter; | ||
| seenFirstDelimiter = false; | ||
| continue; | ||
| } | ||
| if (trimmed == '---' && inFrontMatter) { | ||
| inFrontMatter = false; | ||
| continue; | ||
| } | ||
| if (inFrontMatter) continue; | ||
|
|
||
| final match = RegExp(r'^##\s+(.+)$').firstMatch(line); | ||
| if (match != null) headings.add(match.group(1)!.trim()); | ||
| } |
Comment on lines
+182
to
+185
| final outputPath = p.join(previewsDir.path, '_previews.g.dart'); | ||
| final tmpPath = '$outputPath.tmp'; | ||
| File(tmpPath).writeAsStringSync(renderPreviewsIndex(discovered)); | ||
| File(tmpPath).renameSync(outputPath); |
Comment on lines
+118
to
+120
| final tmpPath = '$outputPath.tmp'; | ||
| File(tmpPath).writeAsStringSync(source); | ||
| File(tmpPath).renameSync(outputPath); |
|
|
||
| ### `dart run magic:artisan design:lint` | ||
|
|
||
| Validates a `DESIGN.md` against six rules: broken-ref (error), missing-primary, unknown-key (the `dark:` overlay is never flagged), section-order, missing-sections, orphaned-tokens, and contrast-ratio (WCAG AA 4.5:1 on component bg/text pairs). Exits nonzero only on an error-severity finding. |
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.
Adds 4 CLI commands:
design:sync/design:lint(DESIGN.md -> wind theme: 17 semantic aliases + brand MaterialColor, WCAG contrast lint),previews:refresh(atomic codegen of a previewEntries() function) andmake:component(4-file atomic component scaffold + chain). No build_runner. analyze 0, 1234 tests, coverage >80%, pub publish --dry-run clean.Cross-repo: this design-first component system spans 5 repos. Land in dependency order: wind (WindRecipe + 5 primitives) first, then magic (design:sync/lint, previews:refresh, make:component) and magic_devtools (preview catalog) which consume wind, then magic_starter (component library + view rewrite), then magic_example (consumer app). Branches are all
feat/design-first-component-system. Verified locally end-to-end (analyze 0, full suites green, real-browser e2e of the /preview catalog, release-strip confirmed).