@bovinphang/frontend-craft 2.6.0 → 2.8.0
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +72 -1
- package/CHANGELOG.zh-CN.md +71 -1
- package/README.md +10 -6
- package/README.openclaw.md +100 -42
- package/README.openclaw.zh-CN.md +100 -42
- package/README.zh-CN.md +10 -6
- package/agents/fec-architect.md +70 -70
- package/agents/fec-code-reviewer.md +82 -82
- package/agents/fec-debugger.md +20 -20
- package/agents/fec-design-token-mapper.md +36 -36
- package/agents/fec-doc-updater.md +13 -13
- package/agents/fec-e2e-runner.md +45 -45
- package/agents/fec-figma-implementer.md +59 -59
- package/agents/fec-performance-optimizer.md +128 -128
- package/agents/fec-refactor-cleaner.md +14 -14
- package/agents/fec-security-reviewer.md +66 -67
- package/agents/fec-test-planner.md +27 -27
- package/agents/fec-typescript-reviewer.md +88 -88
- package/agents/fec-ui-checker.md +74 -74
- package/commands/fec-debug.md +19 -19
- package/commands/fec-doc-sync.md +11 -11
- package/commands/fec-init.md +37 -38
- package/commands/fec-plan.md +58 -58
- package/commands/fec-refactor-clean.md +11 -11
- package/commands/fec-review.md +41 -41
- package/commands/fec-scaffold.md +41 -41
- package/commands/fec-tdd.md +13 -13
- package/dist/bin/frontend-craft.js +29 -27
- package/docs/example-prompts.md +84 -69
- package/docs/ja-JP/README.md +56 -52
- package/docs/ko-KR/README.md +45 -41
- package/docs/project-structure.md +19 -7
- package/docs/superpowers/plans/2026-05-29-fec-debug.md +491 -0
- package/docs/superpowers/specs/2026-05-29-fec-debug-design.md +340 -0
- package/docs/zh-CN/example-prompts.md +84 -69
- package/docs/zh-CN/project-structure.md +14 -5
- package/docs/zh-TW/README.md +33 -29
- package/localized/zh-CN/agents/fec-architect.md +125 -0
- package/localized/zh-CN/agents/fec-code-reviewer.md +152 -0
- package/localized/zh-CN/agents/fec-debugger.md +44 -0
- package/localized/zh-CN/agents/fec-design-token-mapper.md +75 -0
- package/localized/zh-CN/agents/fec-doc-updater.md +30 -0
- package/localized/zh-CN/agents/fec-e2e-runner.md +107 -0
- package/localized/zh-CN/agents/fec-figma-implementer.md +104 -0
- package/localized/zh-CN/agents/fec-performance-optimizer.md +293 -0
- package/localized/zh-CN/agents/fec-refactor-cleaner.md +32 -0
- package/localized/zh-CN/agents/fec-security-reviewer.md +116 -0
- package/localized/zh-CN/agents/fec-test-planner.md +50 -0
- package/localized/zh-CN/agents/fec-typescript-reviewer.md +142 -0
- package/localized/zh-CN/agents/fec-ui-checker.md +120 -0
- package/localized/zh-CN/commands/fec-debug.md +30 -0
- package/localized/zh-CN/commands/fec-doc-sync.md +19 -0
- package/localized/zh-CN/commands/fec-init.md +70 -0
- package/localized/zh-CN/commands/fec-plan.md +94 -0
- package/localized/zh-CN/commands/fec-refactor-clean.md +19 -0
- package/localized/zh-CN/commands/fec-review.md +66 -0
- package/localized/zh-CN/commands/fec-scaffold.md +205 -0
- package/localized/zh-CN/commands/fec-tdd.md +21 -0
- package/localized/zh-CN/skills/TEMPLATE.md +155 -0
- package/localized/zh-CN/skills/eval_queries.json +1013 -0
- package/localized/zh-CN/skills/fec-accessibility-check/SKILL.md +39 -0
- package/localized/zh-CN/skills/fec-accessibility-check/references/report-template.md +23 -0
- package/localized/zh-CN/skills/fec-accessibility-check/references/screen-reader-testing.md +33 -0
- package/localized/zh-CN/skills/fec-alchemy/SKILL.md +74 -0
- package/localized/zh-CN/skills/fec-alchemy/assets/absorption-plan-template.md +47 -0
- package/localized/zh-CN/skills/fec-alchemy/assets/intake-template.md +55 -0
- package/localized/zh-CN/skills/fec-alchemy/assets/review-checklist.md +31 -0
- package/localized/zh-CN/skills/fec-alchemy/references/methodology.md +94 -0
- package/localized/zh-CN/skills/fec-alchemy/references/originality-and-licensing.md +57 -0
- package/localized/zh-CN/skills/fec-api-integration/SKILL.md +78 -0
- package/localized/zh-CN/skills/fec-api-integration/references/integration-patterns.md +80 -0
- package/localized/zh-CN/skills/fec-backend-requirements-handoff/SKILL.md +45 -0
- package/localized/zh-CN/skills/fec-browser-storage/SKILL.md +34 -0
- package/localized/zh-CN/skills/fec-browser-storage/references/storage-patterns.md +65 -0
- package/localized/zh-CN/skills/fec-canvas-threejs/SKILL.md +66 -0
- package/localized/zh-CN/skills/fec-canvas-threejs/references/rendering-patterns.md +67 -0
- package/localized/zh-CN/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +67 -0
- package/localized/zh-CN/skills/fec-code-review/SKILL.md +143 -0
- package/localized/zh-CN/skills/fec-code-review/references/report-template.md +29 -0
- package/localized/zh-CN/skills/fec-component-testing/SKILL.md +119 -0
- package/localized/zh-CN/skills/fec-data-fetching/SKILL.md +62 -0
- package/localized/zh-CN/skills/fec-data-fetching/references/query-patterns.md +103 -0
- package/localized/zh-CN/skills/fec-debug-framework/SKILL.md +157 -0
- package/localized/zh-CN/skills/fec-debug-framework/references/report-template.md +58 -0
- package/localized/zh-CN/skills/fec-dependency-upgrade/SKILL.md +34 -0
- package/localized/zh-CN/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +56 -0
- package/localized/zh-CN/skills/fec-doc-sync/SKILL.md +39 -0
- package/localized/zh-CN/skills/fec-drawio-studio/SKILL.md +73 -0
- package/localized/zh-CN/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
- package/localized/zh-CN/skills/fec-drawio-studio/data/brand-icons.json +878 -0
- package/localized/zh-CN/skills/fec-drawio-studio/data/shape-index.json +83570 -0
- package/localized/zh-CN/skills/fec-drawio-studio/references/data-residency.md +27 -0
- package/localized/zh-CN/skills/fec-drawio-studio/references/diagram-patterns.md +60 -0
- package/localized/zh-CN/skills/fec-drawio-studio/references/flowchart-quality.md +49 -0
- package/localized/zh-CN/skills/fec-drawio-studio/references/layout-and-export.md +72 -0
- package/localized/zh-CN/skills/fec-drawio-studio/references/troubleshooting.md +29 -0
- package/localized/zh-CN/skills/fec-drawio-studio/references/xml-and-mermaid.md +58 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/brand-symbols.mjs +99 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/diagram-lint.mjs +205 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/diagram-url.mjs +102 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/drawio-export.mjs +134 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/layout-graph.mjs +107 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/png-embed-fix.mjs +26 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-go-packages.mjs +36 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-js-modules.mjs +52 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-python-classes.mjs +30 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-python-modules.mjs +55 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/shape-query.mjs +121 -0
- package/localized/zh-CN/skills/fec-drawio-studio/scripts/studio-core.mjs +139 -0
- package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/corporate.json +49 -0
- package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/default.json +49 -0
- package/localized/zh-CN/skills/fec-drawio-studio/styles/built-in/handdrawn.json +49 -0
- package/localized/zh-CN/skills/fec-drawio-studio/styles/schema.json +112 -0
- package/localized/zh-CN/skills/fec-e2e-testing/SKILL.md +42 -0
- package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-ci-reporting.md +62 -0
- package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-special-scenarios.md +52 -0
- package/localized/zh-CN/skills/fec-e2e-testing/references/e2e-visual-regression.md +60 -0
- package/localized/zh-CN/skills/fec-e2e-testing/references/playwright-patterns.md +95 -0
- package/localized/zh-CN/skills/fec-form-handling/SKILL.md +76 -0
- package/localized/zh-CN/skills/fec-form-handling/references/advanced-form-patterns.md +101 -0
- package/localized/zh-CN/skills/fec-image-generation/SKILL.md +80 -0
- package/localized/zh-CN/skills/fec-image-generation/assets/interactive-diagram.html +371 -0
- package/localized/zh-CN/skills/fec-image-generation/references/artifact-routing.md +80 -0
- package/localized/zh-CN/skills/fec-image-generation/references/diagram-workflows.md +74 -0
- package/localized/zh-CN/skills/fec-image-generation/references/html-technical-diagrams.md +236 -0
- package/localized/zh-CN/skills/fec-image-generation/references/png-qa-autofix.md +30 -0
- package/localized/zh-CN/skills/fec-image-generation/scripts/export-diagram.mjs +364 -0
- package/localized/zh-CN/skills/fec-image-generation/scripts/interactive-diagram-server.mjs +654 -0
- package/localized/zh-CN/skills/fec-image-generation/scripts/png-qa.mjs +431 -0
- package/localized/zh-CN/skills/fec-image-generation/scripts/tech-diagram-render.mjs +1397 -0
- package/localized/zh-CN/skills/fec-implement-from-design/SKILL.md +129 -0
- package/localized/zh-CN/skills/fec-implement-from-design/references/design-plan-template.md +36 -0
- package/localized/zh-CN/skills/fec-legacy-to-modern-migration/SKILL.md +46 -0
- package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +110 -0
- package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +41 -0
- package/localized/zh-CN/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +48 -0
- package/localized/zh-CN/skills/fec-legacy-web-standard/SKILL.md +35 -0
- package/localized/zh-CN/skills/fec-legacy-web-standard/references/legacy-patterns.md +85 -0
- package/localized/zh-CN/skills/fec-list-virtualization/SKILL.md +34 -0
- package/localized/zh-CN/skills/fec-list-virtualization/references/virtualization-patterns.md +80 -0
- package/localized/zh-CN/skills/fec-monorepo-project-standard/SKILL.md +142 -0
- package/localized/zh-CN/skills/fec-motion-interaction/SKILL.md +73 -0
- package/localized/zh-CN/skills/fec-motion-interaction/references/motion-patterns.md +112 -0
- package/localized/zh-CN/skills/fec-nextjs-project-standard/SKILL.md +123 -0
- package/localized/zh-CN/skills/fec-nuxt-project-standard/SKILL.md +122 -0
- package/localized/zh-CN/skills/fec-performance-optimization/SKILL.md +80 -0
- package/localized/zh-CN/skills/fec-performance-optimization/references/framework-performance-patterns.md +38 -0
- package/localized/zh-CN/skills/fec-performance-optimization/references/report-template.md +59 -0
- package/localized/zh-CN/skills/fec-pwa-implementation/SKILL.md +35 -0
- package/localized/zh-CN/skills/fec-pwa-implementation/references/manifest-and-icons.md +53 -0
- package/localized/zh-CN/skills/fec-pwa-implementation/references/service-worker-workbox.md +68 -0
- package/localized/zh-CN/skills/fec-react-project-standard/SKILL.md +91 -0
- package/localized/zh-CN/skills/fec-react-project-standard/references/react-performance-patterns.md +35 -0
- package/localized/zh-CN/skills/fec-react-project-standard/references/react-project-structure.md +197 -0
- package/localized/zh-CN/skills/fec-react-project-standard/references/react-quality-patterns.md +131 -0
- package/localized/zh-CN/skills/fec-react-project-standard/references/react-runtime-patterns.md +293 -0
- package/localized/zh-CN/skills/fec-refactor-clean/SKILL.md +51 -0
- package/localized/zh-CN/skills/fec-refactor-clean/references/report-template.md +42 -0
- package/localized/zh-CN/skills/fec-responsive-layout/SKILL.md +34 -0
- package/localized/zh-CN/skills/fec-responsive-layout/references/responsive-layout-patterns.md +70 -0
- package/localized/zh-CN/skills/fec-route-protection/SKILL.md +135 -0
- package/localized/zh-CN/skills/fec-security-review/SKILL.md +38 -0
- package/localized/zh-CN/skills/fec-security-review/references/report-template.md +27 -0
- package/localized/zh-CN/skills/fec-security-review/references/security-checklist.md +64 -0
- package/localized/zh-CN/skills/fec-source-driven-development/SKILL.md +87 -0
- package/localized/zh-CN/skills/fec-state-management/SKILL.md +140 -0
- package/localized/zh-CN/skills/fec-state-management/references/state-patterns.md +109 -0
- package/localized/zh-CN/skills/fec-storybook-component-doc/SKILL.md +37 -0
- package/localized/zh-CN/skills/fec-storybook-component-doc/references/story-patterns.md +118 -0
- package/localized/zh-CN/skills/fec-svg-animation/SKILL.md +148 -0
- package/localized/zh-CN/skills/fec-tailwind-design-system/SKILL.md +34 -0
- package/localized/zh-CN/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +59 -0
- package/localized/zh-CN/skills/fec-tdd-workflow/SKILL.md +52 -0
- package/localized/zh-CN/skills/fec-testing-strategy/SKILL.md +45 -0
- package/localized/zh-CN/skills/fec-typescript-project-standard/SKILL.md +54 -0
- package/{skills/fec-typescript-type-safety → localized/zh-CN/skills/fec-typescript-project-standard}/references/type-safety-patterns.md +1 -1
- package/{skills/fec-typescript-type-safety/SKILL.md → localized/zh-CN/skills/fec-typescript-project-standard/references/type-safety.md} +5 -14
- package/localized/zh-CN/skills/fec-ui-design/SKILL.md +108 -0
- package/localized/zh-CN/skills/fec-ui-design/data/product-rules.json +231 -0
- package/localized/zh-CN/skills/fec-ui-design/data/stack-ui-rules.json +146 -0
- package/localized/zh-CN/skills/fec-ui-design/data/style-archetypes.json +373 -0
- package/localized/zh-CN/skills/fec-ui-design/data/ux-quality-rules.json +203 -0
- package/localized/zh-CN/skills/fec-ui-design/references/design-intelligence.md +97 -0
- package/localized/zh-CN/skills/fec-ui-design/references/master-page-overrides.md +30 -0
- package/localized/zh-CN/skills/fec-ui-design/references/pre-delivery-checklist.md +39 -0
- package/localized/zh-CN/skills/fec-ui-design/scripts/design-system.mjs +648 -0
- package/localized/zh-CN/skills/fec-validation-fix/SKILL.md +51 -0
- package/localized/zh-CN/skills/fec-validation-fix/references/report-template.md +43 -0
- package/localized/zh-CN/skills/fec-vite-project-standard/SKILL.md +83 -0
- package/localized/zh-CN/skills/fec-vue3-project-standard/SKILL.md +58 -0
- package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +162 -0
- package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +13 -0
- package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-project-structure.md +176 -0
- package/localized/zh-CN/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +216 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/SKILL.md +61 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/data/starter-themes.json +59 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/references/chapter-craft.md +37 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/references/content-plan.md +38 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/references/recording-and-audio.md +33 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/references/theme-system.md +36 -0
- package/localized/zh-CN/skills/fec-web-video-presentation/scripts/create-video-presentation.mjs +430 -0
- package/localized/zh-CN/skills/fec-web-workers/SKILL.md +35 -0
- package/localized/zh-CN/skills/fec-web-workers/references/advanced-workers.md +54 -0
- package/localized/zh-CN/skills/fec-web-workers/references/basic-worker.md +67 -0
- package/localized/zh-CN/skills/metadata.json +1646 -0
- package/localized/zh-CN/skills/relations.json +755 -0
- package/localized/zh-CN/templates/claude/CLAUDE.md +106 -0
- package/localized/zh-CN/templates/claude/settings.json +62 -0
- package/localized/zh-CN/templates/codex/AGENTS.md +105 -0
- package/localized/zh-CN/templates/codex/config.toml +32 -0
- package/localized/zh-CN/templates/openclaw/AGENTS.md +101 -0
- package/localized/zh-CN/templates/openclaw/OPENCLAW-CONFIG.md +12 -0
- package/localized/zh-CN/templates/shared/rules/fec-agent-workflow.md +54 -0
- package/localized/zh-CN/templates/shared/rules/fec-api-layer.md +99 -0
- package/localized/zh-CN/templates/shared/rules/fec-ci-cd.md +40 -0
- package/localized/zh-CN/templates/shared/rules/fec-code-comments.md +33 -0
- package/localized/zh-CN/templates/shared/rules/fec-design-system.md +72 -0
- package/localized/zh-CN/templates/shared/rules/fec-error-handling.md +56 -0
- package/localized/zh-CN/templates/shared/rules/fec-git-conventions.md +73 -0
- package/localized/zh-CN/templates/shared/rules/fec-i18n.md +64 -0
- package/localized/zh-CN/templates/shared/rules/fec-naming-conventions.md +120 -0
- package/localized/zh-CN/templates/shared/rules/fec-performance.md +101 -0
- package/localized/zh-CN/templates/shared/rules/fec-react.md +82 -0
- package/localized/zh-CN/templates/shared/rules/fec-refactoring.md +47 -0
- package/localized/zh-CN/templates/shared/rules/fec-rendering-patterns.md +40 -0
- package/localized/zh-CN/templates/shared/rules/fec-responsive-design.md +50 -0
- package/localized/zh-CN/templates/shared/rules/fec-source-driven-development.md +31 -0
- package/localized/zh-CN/templates/shared/rules/fec-state-management.md +60 -0
- package/localized/zh-CN/templates/shared/rules/fec-testing.md +98 -0
- package/localized/zh-CN/templates/shared/rules/fec-typescript.md +112 -0
- package/localized/zh-CN/templates/shared/rules/fec-vue.md +64 -0
- package/localized/zh-CN/templates/shared/rules/fec-working-modes.md +50 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -3
- package/skills/TEMPLATE.md +74 -74
- package/skills/eval_queries.json +717 -619
- package/skills/fec-accessibility-check/SKILL.md +21 -21
- package/skills/fec-accessibility-check/references/report-template.md +12 -12
- package/skills/fec-accessibility-check/references/screen-reader-testing.md +24 -24
- package/skills/fec-alchemy/SKILL.md +50 -50
- package/skills/fec-alchemy/assets/absorption-plan-template.md +32 -32
- package/skills/fec-alchemy/assets/intake-template.md +55 -55
- package/skills/fec-alchemy/assets/review-checklist.md +23 -23
- package/skills/fec-alchemy/references/methodology.md +66 -66
- package/skills/fec-alchemy/references/originality-and-licensing.md +42 -42
- package/skills/fec-api-integration/SKILL.md +61 -61
- package/skills/fec-api-integration/references/integration-patterns.md +30 -30
- package/skills/fec-backend-requirements-handoff/SKILL.md +45 -0
- package/skills/fec-browser-storage/SKILL.md +16 -16
- package/skills/fec-browser-storage/references/storage-patterns.md +16 -16
- package/skills/fec-canvas-threejs/SKILL.md +21 -21
- package/skills/fec-canvas-threejs/references/rendering-patterns.md +10 -10
- package/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +37 -37
- package/skills/fec-code-review/SKILL.md +94 -94
- package/skills/fec-code-review/references/report-template.md +13 -13
- package/skills/fec-component-testing/SKILL.md +39 -39
- package/skills/fec-data-fetching/SKILL.md +16 -16
- package/skills/fec-data-fetching/references/query-patterns.md +27 -27
- package/skills/fec-debug-framework/SKILL.md +95 -95
- package/skills/fec-debug-framework/references/report-template.md +34 -34
- package/skills/fec-dependency-upgrade/SKILL.md +17 -17
- package/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +31 -31
- package/skills/fec-doc-sync/SKILL.md +23 -23
- package/skills/fec-drawio-studio/SKILL.md +73 -0
- package/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
- package/skills/fec-drawio-studio/data/brand-icons.json +878 -0
- package/skills/fec-drawio-studio/data/shape-index.json +83570 -0
- package/skills/fec-drawio-studio/references/data-residency.md +27 -0
- package/skills/fec-drawio-studio/references/diagram-patterns.md +60 -0
- package/skills/fec-drawio-studio/references/flowchart-quality.md +49 -0
- package/skills/fec-drawio-studio/references/layout-and-export.md +72 -0
- package/skills/fec-drawio-studio/references/troubleshooting.md +29 -0
- package/skills/fec-drawio-studio/references/xml-and-mermaid.md +58 -0
- package/skills/fec-drawio-studio/scripts/brand-symbols.mjs +99 -0
- package/skills/fec-drawio-studio/scripts/diagram-lint.mjs +205 -0
- package/skills/fec-drawio-studio/scripts/diagram-url.mjs +102 -0
- package/skills/fec-drawio-studio/scripts/drawio-export.mjs +134 -0
- package/skills/fec-drawio-studio/scripts/layout-graph.mjs +107 -0
- package/skills/fec-drawio-studio/scripts/png-embed-fix.mjs +26 -0
- package/skills/fec-drawio-studio/scripts/scan-go-packages.mjs +36 -0
- package/skills/fec-drawio-studio/scripts/scan-js-modules.mjs +52 -0
- package/skills/fec-drawio-studio/scripts/scan-python-classes.mjs +30 -0
- package/skills/fec-drawio-studio/scripts/scan-python-modules.mjs +55 -0
- package/skills/fec-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
- package/skills/fec-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
- package/skills/fec-drawio-studio/scripts/shape-query.mjs +121 -0
- package/skills/fec-drawio-studio/scripts/studio-core.mjs +139 -0
- package/skills/fec-drawio-studio/styles/built-in/corporate.json +49 -0
- package/skills/fec-drawio-studio/styles/built-in/default.json +49 -0
- package/skills/fec-drawio-studio/styles/built-in/handdrawn.json +49 -0
- package/skills/fec-drawio-studio/styles/schema.json +112 -0
- package/skills/fec-e2e-testing/SKILL.md +24 -22
- package/skills/fec-e2e-testing/references/e2e-ci-reporting.md +62 -0
- package/skills/fec-e2e-testing/references/e2e-special-scenarios.md +52 -0
- package/skills/fec-e2e-testing/references/e2e-visual-regression.md +60 -0
- package/skills/fec-e2e-testing/references/playwright-patterns.md +6 -6
- package/skills/fec-form-handling/SKILL.md +21 -21
- package/skills/fec-form-handling/references/advanced-form-patterns.md +41 -41
- package/skills/fec-image-generation/SKILL.md +81 -0
- package/skills/fec-image-generation/assets/interactive-diagram.html +371 -0
- package/skills/fec-image-generation/references/artifact-routing.md +80 -0
- package/skills/fec-image-generation/references/diagram-workflows.md +74 -0
- package/skills/fec-image-generation/references/html-technical-diagrams.md +236 -0
- package/skills/fec-image-generation/references/png-qa-autofix.md +30 -0
- package/skills/fec-image-generation/scripts/export-diagram.mjs +364 -0
- package/skills/fec-image-generation/scripts/interactive-diagram-server.mjs +654 -0
- package/skills/fec-image-generation/scripts/png-qa.mjs +431 -0
- package/skills/fec-image-generation/scripts/tech-diagram-render.mjs +1397 -0
- package/skills/fec-implement-from-design/SKILL.md +81 -74
- package/skills/fec-implement-from-design/references/design-plan-template.md +16 -16
- package/skills/fec-legacy-to-modern-migration/SKILL.md +29 -173
- package/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +110 -0
- package/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +37 -37
- package/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +48 -0
- package/skills/fec-legacy-web-standard/SKILL.md +17 -17
- package/skills/fec-legacy-web-standard/references/legacy-patterns.md +16 -16
- package/skills/fec-list-virtualization/SKILL.md +16 -16
- package/skills/fec-list-virtualization/references/virtualization-patterns.md +31 -31
- package/skills/fec-monorepo-project-standard/SKILL.md +52 -52
- package/skills/fec-motion-interaction/SKILL.md +51 -44
- package/skills/fec-motion-interaction/references/motion-patterns.md +11 -11
- package/skills/fec-nextjs-project-standard/SKILL.md +64 -58
- package/skills/fec-nuxt-project-standard/SKILL.md +57 -57
- package/skills/fec-performance-optimization/SKILL.md +54 -50
- package/skills/fec-performance-optimization/references/framework-performance-patterns.md +38 -0
- package/skills/fec-performance-optimization/references/report-template.md +34 -28
- package/skills/fec-pwa-implementation/SKILL.md +17 -17
- package/skills/fec-pwa-implementation/references/manifest-and-icons.md +12 -12
- package/skills/fec-pwa-implementation/references/service-worker-workbox.md +13 -13
- package/skills/fec-react-project-standard/SKILL.md +72 -64
- package/skills/fec-react-project-standard/references/react-performance-patterns.md +35 -0
- package/skills/fec-react-project-standard/references/react-project-structure.md +197 -0
- package/skills/fec-react-project-standard/references/react-quality-patterns.md +131 -0
- package/skills/fec-react-project-standard/references/react-runtime-patterns.md +293 -0
- package/skills/fec-refactor-clean/SKILL.md +30 -30
- package/skills/fec-refactor-clean/references/report-template.md +23 -23
- package/skills/fec-responsive-layout/SKILL.md +17 -17
- package/skills/fec-responsive-layout/references/responsive-layout-patterns.md +39 -28
- package/skills/fec-route-protection/SKILL.md +26 -26
- package/skills/fec-security-review/SKILL.md +20 -20
- package/skills/fec-security-review/references/report-template.md +12 -12
- package/skills/fec-security-review/references/security-checklist.md +27 -27
- package/skills/fec-source-driven-development/SKILL.md +66 -40
- package/skills/fec-state-management/SKILL.md +34 -34
- package/skills/fec-state-management/references/state-patterns.md +19 -19
- package/skills/fec-storybook-component-doc/SKILL.md +19 -19
- package/skills/fec-storybook-component-doc/references/story-patterns.md +12 -12
- package/skills/fec-svg-animation/SKILL.md +32 -32
- package/skills/fec-tailwind-design-system/SKILL.md +17 -17
- package/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +36 -32
- package/skills/fec-tdd-workflow/SKILL.md +28 -28
- package/skills/fec-testing-strategy/SKILL.md +29 -29
- package/skills/fec-typescript-project-standard/SKILL.md +54 -0
- package/skills/fec-typescript-project-standard/references/type-safety-patterns.md +102 -0
- package/skills/fec-typescript-project-standard/references/type-safety.md +148 -0
- package/skills/fec-ui-design/SKILL.md +90 -72
- package/skills/fec-ui-design/data/style-archetypes.json +40 -0
- package/skills/fec-ui-design/data/ux-quality-rules.json +35 -0
- package/skills/fec-ui-design/references/design-intelligence.md +81 -21
- package/skills/fec-ui-design/references/master-page-overrides.md +15 -15
- package/skills/fec-ui-design/references/pre-delivery-checklist.md +38 -32
- package/skills/fec-ui-design/scripts/design-system.mjs +119 -1
- package/skills/fec-validation-fix/SKILL.md +26 -26
- package/skills/fec-validation-fix/references/report-template.md +25 -25
- package/skills/fec-vite-project-standard/SKILL.md +39 -39
- package/skills/fec-vue3-project-standard/SKILL.md +39 -30
- package/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +163 -0
- package/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +13 -0
- package/skills/fec-vue3-project-standard/references/vue3-project-structure.md +177 -0
- package/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +216 -0
- package/skills/fec-web-video-presentation/SKILL.md +61 -0
- package/skills/fec-web-video-presentation/data/starter-themes.json +59 -0
- package/skills/fec-web-video-presentation/references/chapter-craft.md +37 -0
- package/skills/fec-web-video-presentation/references/content-plan.md +38 -0
- package/skills/fec-web-video-presentation/references/recording-and-audio.md +33 -0
- package/skills/fec-web-video-presentation/references/theme-system.md +36 -0
- package/skills/fec-web-video-presentation/scripts/create-video-presentation.mjs +430 -0
- package/skills/fec-web-workers/SKILL.md +16 -16
- package/skills/fec-web-workers/references/advanced-workers.md +13 -13
- package/skills/fec-web-workers/references/basic-worker.md +8 -8
- package/skills/metadata.json +402 -220
- package/skills/relations.json +120 -25
- package/templates/claude/CLAUDE.md +60 -60
- package/templates/codex/AGENTS.md +76 -76
- package/templates/codex/config.toml +4 -4
- package/templates/openclaw/AGENTS.md +68 -68
- package/templates/openclaw/OPENCLAW-CONFIG.md +8 -8
- package/templates/shared/rules/fec-agent-workflow.md +40 -40
- package/templates/shared/rules/fec-api-layer.md +52 -52
- package/templates/shared/rules/fec-ci-cd.md +29 -117
- package/templates/shared/rules/fec-code-comments.md +22 -22
- package/templates/shared/rules/fec-design-system.md +65 -241
- package/templates/shared/rules/fec-error-handling.md +41 -185
- package/templates/shared/rules/fec-git-conventions.md +42 -42
- package/templates/shared/rules/fec-i18n.md +48 -96
- package/templates/shared/rules/fec-naming-conventions.md +91 -91
- package/templates/shared/rules/fec-performance.md +78 -78
- package/templates/shared/rules/fec-react.md +58 -58
- package/templates/shared/rules/fec-refactoring.md +34 -30
- package/templates/shared/rules/fec-rendering-patterns.md +40 -183
- package/templates/shared/rules/fec-responsive-design.md +37 -214
- package/templates/shared/rules/fec-source-driven-development.md +22 -22
- package/templates/shared/rules/fec-state-management.md +45 -148
- package/templates/shared/rules/fec-testing.md +64 -64
- package/templates/shared/rules/fec-typescript.md +98 -341
- package/templates/shared/rules/fec-vue.md +42 -42
- package/templates/shared/rules/fec-working-modes.md +34 -34
- package/skills/fec-e2e-testing/references/e2e-advanced.md +0 -176
- package/skills/fec-react-project-standard/references/react-project-details.md +0 -642
- package/skills/fec-vue3-project-standard/references/vue3-project-details.md +0 -547
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# UI/UX 交付前检查
|
|
2
|
+
|
|
3
|
+
## 严重
|
|
4
|
+
|
|
5
|
+
- 文本对比度:正文至少 4.5:1,大字号至少 3:1。
|
|
6
|
+
- 键盘可达:菜单、弹窗、标签页、抽屉和自定义控件都能键盘操作。
|
|
7
|
+
- 焦点可见:focus ring 不能被全局样式移除。
|
|
8
|
+
- 图标按钮:必须有可访问名称。
|
|
9
|
+
- 触摸目标:移动端主要交互至少 44x44px;空间允许时使用 48px。
|
|
10
|
+
|
|
11
|
+
## 高优先级
|
|
12
|
+
|
|
13
|
+
- 首屏:工具型界面直接展示核心工作区,不用营销 hero 替代功能。
|
|
14
|
+
- 首屏:营销、作品集和品牌页在常见小笔记本高度内显示主体、CTA 和下一屏线索。
|
|
15
|
+
- CTA:按钮文案在桌面端不换行,对比度合格,同一意图使用一致标签。
|
|
16
|
+
- 导航:桌面端保持单行,移动端折叠后仍能到达主要路径。
|
|
17
|
+
- 响应式:375px、768px、1024px、1440px 无水平溢出、遮挡或文本截断。
|
|
18
|
+
- 性能:图片有尺寸或 aspect-ratio;非首屏图片懒加载;列表过大时虚拟化。
|
|
19
|
+
- 动效:只动画 transform/opacity,尊重 `prefers-reduced-motion`。
|
|
20
|
+
- 状态:loading、empty、error、disabled、hover、focus、selected 都有设计。
|
|
21
|
+
|
|
22
|
+
## 中优先级
|
|
23
|
+
|
|
24
|
+
- 字体:正文不小于 16px;数字列、金额、计时器使用 tabular nums。
|
|
25
|
+
- 颜色:错误、成功、警告不只靠颜色表达。
|
|
26
|
+
- 表单:label 常驻,错误靠近字段,提交后有 loading/success/error。
|
|
27
|
+
- 导航:当前路由可识别,返回行为可预测,深层页面仍能回到主路径。
|
|
28
|
+
- 图表:有标题、单位、图例、tooltip 或明细表替代,色彩不依赖红绿区分。
|
|
29
|
+
|
|
30
|
+
## 反模式
|
|
31
|
+
|
|
32
|
+
- 用装饰光斑、紫色渐变、卡片堆叠掩盖信息结构不足。
|
|
33
|
+
- 连续三段以上复用三卡片、左右交错、split header 或同一种 reveal 动效。
|
|
34
|
+
- 视觉型页面只有文字和渐变,没有真实产品、真实状态、品牌应用或可检查媒体。
|
|
35
|
+
- Bento 用空格子补构图,或 feature grid 每个格子同权重、同背景、同节奏。
|
|
36
|
+
- hover 导致布局位移。
|
|
37
|
+
- `transition: all`、`will-change: all`。
|
|
38
|
+
- 低对比灰字、无意义透明度、单一色相界面。
|
|
39
|
+
- 空状态只有“暂无数据”,没有下一步动作。
|
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {{
|
|
9
|
+
* id: string;
|
|
10
|
+
* label?: string;
|
|
11
|
+
* keywords: string[];
|
|
12
|
+
* pattern?: string;
|
|
13
|
+
* patterns?: string[];
|
|
14
|
+
* risks: string[];
|
|
15
|
+
* style?: string;
|
|
16
|
+
* space?: string;
|
|
17
|
+
* components?: string[];
|
|
18
|
+
* motion: string;
|
|
19
|
+
* antiPatterns: string[];
|
|
20
|
+
* }} ProductRule
|
|
21
|
+
*
|
|
22
|
+
* @typedef {{
|
|
23
|
+
* id: string;
|
|
24
|
+
* label?: string;
|
|
25
|
+
* keywords: string[];
|
|
26
|
+
* usage?: string;
|
|
27
|
+
* description?: string;
|
|
28
|
+
* risks?: string[];
|
|
29
|
+
* avoid?: string[];
|
|
30
|
+
* antiPatterns?: string[];
|
|
31
|
+
* tokens?: { density?: string };
|
|
32
|
+
* }} StyleArchetype
|
|
33
|
+
*
|
|
34
|
+
* @typedef {{
|
|
35
|
+
* id?: string;
|
|
36
|
+
* category?: string;
|
|
37
|
+
* label?: string;
|
|
38
|
+
* checks: string[];
|
|
39
|
+
* }} UxQualityRule
|
|
40
|
+
*
|
|
41
|
+
* @typedef {{
|
|
42
|
+
* stack: string;
|
|
43
|
+
* label?: string;
|
|
44
|
+
* keywords: string[];
|
|
45
|
+
* guidance: string[];
|
|
46
|
+
* }} StackRule
|
|
47
|
+
*
|
|
48
|
+
* @typedef {{
|
|
49
|
+
* queryParts: string[];
|
|
50
|
+
* query: string;
|
|
51
|
+
* format: "markdown" | "json";
|
|
52
|
+
* project: string;
|
|
53
|
+
* page: string;
|
|
54
|
+
* stack: string;
|
|
55
|
+
* persist: boolean;
|
|
56
|
+
* outputDir: string;
|
|
57
|
+
* help: boolean;
|
|
58
|
+
* }} CliArgs
|
|
59
|
+
*
|
|
60
|
+
* @typedef {{
|
|
61
|
+
* id: string;
|
|
62
|
+
* label: string;
|
|
63
|
+
* checks: string[];
|
|
64
|
+
* }} ChecklistGroup
|
|
65
|
+
*
|
|
66
|
+
* @typedef {{
|
|
67
|
+
* project: string;
|
|
68
|
+
* page: string;
|
|
69
|
+
* query: string;
|
|
70
|
+
* designRead: string;
|
|
71
|
+
* designDials: {
|
|
72
|
+
* visualTension: number;
|
|
73
|
+
* motionIntensity: number;
|
|
74
|
+
* informationDensity: number;
|
|
75
|
+
* mediaAuthenticity: number;
|
|
76
|
+
* contentPersuasion: number;
|
|
77
|
+
* };
|
|
78
|
+
* product: { id: string; label: string; pattern: string; risks: string[] };
|
|
79
|
+
* style: { id: string; label: string; usage: string | undefined; risks: string[] };
|
|
80
|
+
* tokens: { color: string; typography: string; space: string; components: string[] };
|
|
81
|
+
* motion: string;
|
|
82
|
+
* chart: string;
|
|
83
|
+
* antiPatterns: string[];
|
|
84
|
+
* checklist: ChecklistGroup[];
|
|
85
|
+
* stackGuidance: StackRule | null;
|
|
86
|
+
* }} Recommendation
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
90
|
+
const skillDir = path.resolve(__dirname, "..");
|
|
91
|
+
const dataDir = path.join(skillDir, "data");
|
|
92
|
+
|
|
93
|
+
const productRules = /** @type {ProductRule[]} */ (readJson("product-rules.json"));
|
|
94
|
+
const styleArchetypes = /** @type {StyleArchetype[]} */ (readJson("style-archetypes.json"));
|
|
95
|
+
const uxQualityRules = /** @type {UxQualityRule[]} */ (readJson("ux-quality-rules.json"));
|
|
96
|
+
const stackRules = /** @type {StackRule[]} */ (readJson("stack-ui-rules.json"));
|
|
97
|
+
|
|
98
|
+
/** @type {Record<string, string>} */
|
|
99
|
+
const colorDirections = {
|
|
100
|
+
saas: "Neutral surfaces with a restrained trust accent, semantic status colors, and one operational highlight.",
|
|
101
|
+
fintech: "Ink, graphite, and calm blue-green tokens with explicit success, risk, warning, and pending states.",
|
|
102
|
+
healthcare: "Clean neutrals with soft clinical blues or greens, high contrast text, and sparing reassurance accents.",
|
|
103
|
+
ecommerce: "Product-led neutrals, one conversion accent, clear price/status colors, and image-friendly backgrounds.",
|
|
104
|
+
creative: "Flexible neutrals with a bolder accent system, gallery-safe surfaces, and controlled expressive moments.",
|
|
105
|
+
wellness: "Warm off-white surfaces, botanical or mineral accents, calm confirmation colors, and low-glare contrast.",
|
|
106
|
+
education: "Readable neutrals, progress color coding, friendly accents, and clear feedback colors.",
|
|
107
|
+
gaming: "High-contrast surfaces, faction or mode accents, explicit danger/reward colors, and readable HUD tokens.",
|
|
108
|
+
"data-dashboard": "Dense neutrals, chart-safe categorical palettes, alert colors with severity order, and subdued chrome.",
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** @type {Record<string, string>} */
|
|
112
|
+
const typographyDirections = {
|
|
113
|
+
saas: "Use a workhorse sans for UI text, tabular numerals for metrics, and compact headings for scan speed.",
|
|
114
|
+
fintech: "Use a precise sans with tabular numerals, conservative weights, and generous numeric spacing.",
|
|
115
|
+
healthcare: "Use a highly legible sans, moderate line height, and calm heading contrast.",
|
|
116
|
+
ecommerce: "Use readable product text, stronger merchandising headings, and stable price typography.",
|
|
117
|
+
creative: "Pair a characterful display face with a reliable UI sans if the brand can support it.",
|
|
118
|
+
wellness: "Use a soft humanist sans or restrained serif accent, with relaxed line height and readable controls.",
|
|
119
|
+
education: "Use friendly readable type, clear hierarchy, and progress labels that survive small screens.",
|
|
120
|
+
gaming: "Use expressive display only for short labels; keep gameplay, settings, and HUD text fast to parse.",
|
|
121
|
+
"data-dashboard": "Use compact UI type, tabular numerals, and strict alignment for tables and charts.",
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/** @type {Record<string, string>} */
|
|
125
|
+
const chartDirections = {
|
|
126
|
+
saas: "Prefer KPI trends, cohort funnels, and status breakdowns with clear comparison periods.",
|
|
127
|
+
fintech: "Use time-series, allocation, variance, and risk bands; disclose units and stale data states.",
|
|
128
|
+
healthcare: "Use trends and thresholds carefully, avoid alarmist color, and keep clinical context beside charts.",
|
|
129
|
+
ecommerce: "Use conversion funnels, product comparison, inventory status, and revenue trends.",
|
|
130
|
+
creative: "Use portfolio analytics sparingly; prioritize visual inspection before metrics.",
|
|
131
|
+
wellness: "Use booking, occupancy, habit, or progress views with gentle pacing and clear privacy boundaries.",
|
|
132
|
+
education: "Use progress, completion, mastery, and assignment timelines with learner-friendly labels.",
|
|
133
|
+
gaming: "Use leaderboards, loadouts, skill trees, and telemetry only when they support player decisions.",
|
|
134
|
+
"data-dashboard": "Choose chart type by task: trend, compare, compose, distribute, correlate, or inspect anomalies.",
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {string} fileName
|
|
139
|
+
* @returns {unknown}
|
|
140
|
+
*/
|
|
141
|
+
function readJson(fileName) {
|
|
142
|
+
return JSON.parse(fs.readFileSync(path.join(dataDir, fileName), "utf8"));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function main() {
|
|
146
|
+
const args = parseArgs(process.argv.slice(2));
|
|
147
|
+
if (args.help || !args.query) {
|
|
148
|
+
printUsage(args.help ? 0 : 1);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const recommendation = buildRecommendation(args);
|
|
153
|
+
const output = args.format === "json" ? `${JSON.stringify(recommendation, null, 2)}\n` : renderMarkdown(recommendation);
|
|
154
|
+
|
|
155
|
+
if (args.persist) persistRecommendation(recommendation, args);
|
|
156
|
+
|
|
157
|
+
process.stdout.write(output);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @param {string[]} argv
|
|
162
|
+
* @returns {CliArgs}
|
|
163
|
+
*/
|
|
164
|
+
function parseArgs(argv) {
|
|
165
|
+
/** @type {CliArgs} */
|
|
166
|
+
const result = {
|
|
167
|
+
queryParts: [],
|
|
168
|
+
query: "",
|
|
169
|
+
format: "markdown",
|
|
170
|
+
project: "",
|
|
171
|
+
page: "",
|
|
172
|
+
stack: "",
|
|
173
|
+
persist: false,
|
|
174
|
+
outputDir: process.cwd(),
|
|
175
|
+
help: false,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
179
|
+
const token = argv[index];
|
|
180
|
+
if (token === "--help" || token === "-h") result.help = true;
|
|
181
|
+
else if (token === "--persist") result.persist = true;
|
|
182
|
+
else if (token === "--format") {
|
|
183
|
+
const format = requireValue(argv, ++index, "--format");
|
|
184
|
+
if (format !== "markdown" && format !== "json") {
|
|
185
|
+
throw new Error(`Unsupported --format "${format}". Use markdown or json.`);
|
|
186
|
+
}
|
|
187
|
+
result.format = format;
|
|
188
|
+
}
|
|
189
|
+
else if (token === "--project") result.project = requireValue(argv, ++index, "--project");
|
|
190
|
+
else if (token === "--page") result.page = requireValue(argv, ++index, "--page");
|
|
191
|
+
else if (token === "--stack") result.stack = requireValue(argv, ++index, "--stack");
|
|
192
|
+
else if (token === "--output-dir") result.outputDir = requireValue(argv, ++index, "--output-dir");
|
|
193
|
+
else result.queryParts.push(token);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
result.query = result.queryParts.join(" ").trim();
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @param {string[]} argv
|
|
202
|
+
* @param {number} index
|
|
203
|
+
* @param {string} flag
|
|
204
|
+
* @returns {string}
|
|
205
|
+
*/
|
|
206
|
+
function requireValue(argv, index, flag) {
|
|
207
|
+
const value = argv[index];
|
|
208
|
+
if (!value || value.startsWith("--")) throw new Error(`Missing value for ${flag}`);
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @param {number} exitCode
|
|
214
|
+
* @returns {void}
|
|
215
|
+
*/
|
|
216
|
+
function printUsage(exitCode) {
|
|
217
|
+
const usage = [
|
|
218
|
+
'Usage: node skills/fec-ui-design/scripts/design-system.mjs "<query>" [options]',
|
|
219
|
+
"",
|
|
220
|
+
"Options:",
|
|
221
|
+
" --format markdown|json",
|
|
222
|
+
" --project <name>",
|
|
223
|
+
" --page <name>",
|
|
224
|
+
" --stack <stack>",
|
|
225
|
+
" --persist --output-dir <dir>",
|
|
226
|
+
"",
|
|
227
|
+
].join("\n");
|
|
228
|
+
process.stderr.write(usage);
|
|
229
|
+
process.exitCode = exitCode;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @param {CliArgs} args
|
|
234
|
+
* @returns {Recommendation}
|
|
235
|
+
*/
|
|
236
|
+
function buildRecommendation(args) {
|
|
237
|
+
const query = args.query;
|
|
238
|
+
const tokens = tokenize([query, args.project, args.page, args.stack].filter(Boolean).join(" "));
|
|
239
|
+
const product = chooseProduct(tokens);
|
|
240
|
+
const style = chooseStyle(tokens, product);
|
|
241
|
+
const designDials = deriveDesignDials(tokens, product, style);
|
|
242
|
+
const checklist = chooseChecklist(tokens, product);
|
|
243
|
+
const stackGuidance = chooseStack(args.stack, tokens);
|
|
244
|
+
const pattern = product.pattern ?? product.patterns?.[0] ?? "Task-first interface with explicit states and durable visual hierarchy";
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
project: args.project || titleCase(query),
|
|
248
|
+
page: args.page || "",
|
|
249
|
+
query,
|
|
250
|
+
designRead: renderDesignRead(product, style, designDials),
|
|
251
|
+
designDials,
|
|
252
|
+
product: {
|
|
253
|
+
id: product.id,
|
|
254
|
+
label: product.label ?? labelFromId(product.id),
|
|
255
|
+
pattern,
|
|
256
|
+
risks: product.risks,
|
|
257
|
+
},
|
|
258
|
+
style: {
|
|
259
|
+
id: style.id,
|
|
260
|
+
label: style.label ?? labelFromId(style.id),
|
|
261
|
+
usage: style.usage ?? style.description,
|
|
262
|
+
risks: style.risks ?? style.avoid ?? [],
|
|
263
|
+
},
|
|
264
|
+
tokens: {
|
|
265
|
+
color: colorDirections[product.id] ?? colorDirections.saas,
|
|
266
|
+
typography: typographyDirections[product.id] ?? typographyDirections.saas,
|
|
267
|
+
space: product.space ?? style.tokens?.density ?? "Match task density to user scan depth and touch requirements.",
|
|
268
|
+
components: product.components ?? ["Use existing components before adding new primitives", "Tokenize repeated spacing, color, radius, and state choices"],
|
|
269
|
+
},
|
|
270
|
+
motion: product.motion,
|
|
271
|
+
chart: chartDirections[product.id] ?? chartDirections["data-dashboard"],
|
|
272
|
+
antiPatterns: unique([...product.antiPatterns, ...(style.antiPatterns ?? style.avoid ?? [])]).slice(0, 8),
|
|
273
|
+
checklist,
|
|
274
|
+
stackGuidance,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @param {Set<string>} tokens
|
|
280
|
+
* @returns {ProductRule}
|
|
281
|
+
*/
|
|
282
|
+
function chooseProduct(tokens) {
|
|
283
|
+
let best = productRules[0];
|
|
284
|
+
let bestScore = -1;
|
|
285
|
+
|
|
286
|
+
for (const product of productRules) {
|
|
287
|
+
const keywordScore = score(tokens, [...product.keywords, product.id, product.label ?? ""]);
|
|
288
|
+
const intentScore = tokens.has(slug(product.pattern)) ? 1 : 0;
|
|
289
|
+
const total = keywordScore + intentScore;
|
|
290
|
+
if (total > bestScore) {
|
|
291
|
+
best = product;
|
|
292
|
+
bestScore = total;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return best;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @param {Set<string>} tokens
|
|
301
|
+
* @param {ProductRule} product
|
|
302
|
+
* @returns {StyleArchetype}
|
|
303
|
+
*/
|
|
304
|
+
function chooseStyle(tokens, product) {
|
|
305
|
+
const preferred = styleArchetypes.find((style) => style.id === product.style);
|
|
306
|
+
let best = preferred ?? styleArchetypes[0];
|
|
307
|
+
let bestScore = preferred ? 1 : 0;
|
|
308
|
+
|
|
309
|
+
for (const style of styleArchetypes) {
|
|
310
|
+
const total = score(tokens, [style.id, style.label, ...style.keywords]);
|
|
311
|
+
if (total > bestScore) {
|
|
312
|
+
best = style;
|
|
313
|
+
bestScore = total;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return best;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @param {Set<string>} tokens
|
|
322
|
+
* @param {ProductRule} product
|
|
323
|
+
* @returns {ChecklistGroup[]}
|
|
324
|
+
*/
|
|
325
|
+
function chooseChecklist(tokens, product) {
|
|
326
|
+
const priority = new Set(["accessibility", "interaction", "layout", "typography", "animation", "state-completeness"]);
|
|
327
|
+
if (product.id === "data-dashboard" || tokens.has("dashboard") || tokens.has("chart")) priority.add("charts");
|
|
328
|
+
if (tokens.has("form") || tokens.has("booking") || tokens.has("checkout")) priority.add("forms");
|
|
329
|
+
if (tokens.has("mobile") || tokens.has("app")) priority.add("navigation");
|
|
330
|
+
if (tokens.has("performance") || tokens.has("canvas") || tokens.has("three")) priority.add("performance");
|
|
331
|
+
if (isPromotional(tokens, product)) {
|
|
332
|
+
priority.add("first-viewport");
|
|
333
|
+
priority.add("cta-quality");
|
|
334
|
+
priority.add("section-variety");
|
|
335
|
+
priority.add("media-authenticity");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return uxQualityRules
|
|
339
|
+
.filter((rule) => {
|
|
340
|
+
const id = rule.id ?? rule.category;
|
|
341
|
+
return id ? priority.has(id) : false;
|
|
342
|
+
})
|
|
343
|
+
.map((rule) => {
|
|
344
|
+
const id = rule.id ?? rule.category ?? "general";
|
|
345
|
+
return {
|
|
346
|
+
id,
|
|
347
|
+
label: rule.label ?? labelFromId(id),
|
|
348
|
+
checks: rule.checks.slice(0, 4),
|
|
349
|
+
};
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* @param {Set<string>} tokens
|
|
355
|
+
* @param {ProductRule} product
|
|
356
|
+
* @param {StyleArchetype} style
|
|
357
|
+
* @returns {Recommendation["designDials"]}
|
|
358
|
+
*/
|
|
359
|
+
function deriveDesignDials(tokens, product, style) {
|
|
360
|
+
/** @type {Recommendation["designDials"]} */
|
|
361
|
+
const dials = {
|
|
362
|
+
visualTension: 5,
|
|
363
|
+
motionIntensity: 3,
|
|
364
|
+
informationDensity: 5,
|
|
365
|
+
mediaAuthenticity: 5,
|
|
366
|
+
contentPersuasion: 5,
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
if (["data-dashboard", "saas", "fintech", "healthcare"].includes(product.id)) {
|
|
370
|
+
dials.visualTension = 3;
|
|
371
|
+
dials.motionIntensity = product.id === "saas" ? 3 : 2;
|
|
372
|
+
dials.informationDensity = product.id === "data-dashboard" ? 8 : 6;
|
|
373
|
+
dials.mediaAuthenticity = 4;
|
|
374
|
+
dials.contentPersuasion = 4;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (["ecommerce", "creative", "wellness"].includes(product.id) || isPromotional(tokens, product)) {
|
|
378
|
+
dials.visualTension = product.id === "creative" ? 8 : 7;
|
|
379
|
+
dials.motionIntensity = product.id === "creative" ? 6 : 5;
|
|
380
|
+
dials.informationDensity = 4;
|
|
381
|
+
dials.mediaAuthenticity = 8;
|
|
382
|
+
dials.contentPersuasion = 8;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (product.id === "gaming" || style.id === "immersive") {
|
|
386
|
+
dials.visualTension = 8;
|
|
387
|
+
dials.motionIntensity = 7;
|
|
388
|
+
dials.informationDensity = 6;
|
|
389
|
+
dials.mediaAuthenticity = 7;
|
|
390
|
+
dials.contentPersuasion = 5;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (["minimal", "minimal-utilitarian"].includes(style.id)) {
|
|
394
|
+
dials.visualTension = Math.min(dials.visualTension, 4);
|
|
395
|
+
dials.motionIntensity = Math.min(dials.motionIntensity, 3);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (["editorial-premium", "image-led-landing", "brand-system-board"].includes(style.id)) {
|
|
399
|
+
dials.visualTension = Math.max(dials.visualTension, 7);
|
|
400
|
+
dials.mediaAuthenticity = Math.max(dials.mediaAuthenticity, 8);
|
|
401
|
+
dials.contentPersuasion = Math.max(dials.contentPersuasion, 7);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (tokens.has("regulated") || tokens.has("public") || tokens.has("government") || tokens.has("accessibility")) {
|
|
405
|
+
dials.visualTension = Math.min(dials.visualTension, 3);
|
|
406
|
+
dials.motionIntensity = Math.min(dials.motionIntensity, 2);
|
|
407
|
+
dials.informationDensity = Math.max(dials.informationDensity, 5);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return dials;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* @param {ProductRule} product
|
|
415
|
+
* @param {StyleArchetype} style
|
|
416
|
+
* @param {Recommendation["designDials"]} dials
|
|
417
|
+
* @returns {string}
|
|
418
|
+
*/
|
|
419
|
+
function renderDesignRead(product, style, dials) {
|
|
420
|
+
return [
|
|
421
|
+
`Reading this as ${product.label ?? labelFromId(product.id)} work`,
|
|
422
|
+
`with a ${style.label ?? labelFromId(style.id)} visual direction`,
|
|
423
|
+
`and dial targets ${dials.visualTension}/${dials.motionIntensity}/${dials.informationDensity}/${dials.mediaAuthenticity}/${dials.contentPersuasion}`,
|
|
424
|
+
].join(", ");
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* @param {Set<string>} tokens
|
|
429
|
+
* @param {ProductRule} product
|
|
430
|
+
* @returns {boolean}
|
|
431
|
+
*/
|
|
432
|
+
function isPromotional(tokens, product) {
|
|
433
|
+
return product.id === "creative"
|
|
434
|
+
|| product.id === "ecommerce"
|
|
435
|
+
|| tokens.has("landing")
|
|
436
|
+
|| tokens.has("marketing")
|
|
437
|
+
|| tokens.has("portfolio")
|
|
438
|
+
|| tokens.has("brand")
|
|
439
|
+
|| tokens.has("website")
|
|
440
|
+
|| tokens.has("hero");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* @param {string} stack
|
|
445
|
+
* @param {Set<string>} tokens
|
|
446
|
+
* @returns {StackRule | null}
|
|
447
|
+
*/
|
|
448
|
+
function chooseStack(stack, tokens) {
|
|
449
|
+
const desired = normalizeStack(stack);
|
|
450
|
+
const direct = desired
|
|
451
|
+
? stackRules.find((rule) => normalizeStack(rule.stack) === desired || rule.keywords.some((keyword) => normalizeStack(keyword) === desired))
|
|
452
|
+
: undefined;
|
|
453
|
+
if (direct) return direct;
|
|
454
|
+
|
|
455
|
+
for (const rule of stackRules) {
|
|
456
|
+
if ([rule.stack, ...rule.keywords].some((alias) => {
|
|
457
|
+
const normalized = slug(alias);
|
|
458
|
+
if (normalized === "spa" || normalized.length < 3) return false;
|
|
459
|
+
return tokens.has(normalized) || tokens.has(String(alias).toLowerCase());
|
|
460
|
+
})) return rule;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @param {Recommendation} model
|
|
468
|
+
* @returns {string}
|
|
469
|
+
*/
|
|
470
|
+
function renderMarkdown(model) {
|
|
471
|
+
const lines = [
|
|
472
|
+
`# Design System Recommendation: ${model.project}`,
|
|
473
|
+
"",
|
|
474
|
+
`- Design read: ${model.designRead}`,
|
|
475
|
+
`- Product category: ${model.product.label} (${model.product.id})`,
|
|
476
|
+
`- Recommended pattern: ${model.product.pattern}`,
|
|
477
|
+
`- Style archetype: ${model.style.label} (${model.style.id})`,
|
|
478
|
+
"",
|
|
479
|
+
"## Design Dials",
|
|
480
|
+
"",
|
|
481
|
+
`- Visual tension: ${model.designDials.visualTension}/10`,
|
|
482
|
+
`- Motion intensity: ${model.designDials.motionIntensity}/10`,
|
|
483
|
+
`- Information density: ${model.designDials.informationDensity}/10`,
|
|
484
|
+
`- Media authenticity: ${model.designDials.mediaAuthenticity}/10`,
|
|
485
|
+
`- Content persuasion: ${model.designDials.contentPersuasion}/10`,
|
|
486
|
+
"",
|
|
487
|
+
"## Token Direction",
|
|
488
|
+
"",
|
|
489
|
+
`- Color: ${model.tokens.color}`,
|
|
490
|
+
`- Typography: ${model.tokens.typography}`,
|
|
491
|
+
`- Space: ${model.tokens.space}`,
|
|
492
|
+
`- Components: ${model.tokens.components.join("; ")}`,
|
|
493
|
+
"",
|
|
494
|
+
"## Motion Guidance",
|
|
495
|
+
"",
|
|
496
|
+
model.motion,
|
|
497
|
+
"",
|
|
498
|
+
"## Chart Guidance",
|
|
499
|
+
"",
|
|
500
|
+
model.chart,
|
|
501
|
+
"",
|
|
502
|
+
"## Anti-Patterns",
|
|
503
|
+
"",
|
|
504
|
+
...model.antiPatterns.map((item) => `- ${item}`),
|
|
505
|
+
"",
|
|
506
|
+
"## Pre-Delivery Checklist",
|
|
507
|
+
"",
|
|
508
|
+
...model.checklist.flatMap((group) => [`### ${group.label}`, "", ...group.checks.map((check) => `- ${check}`), ""]),
|
|
509
|
+
];
|
|
510
|
+
|
|
511
|
+
if (model.stackGuidance) {
|
|
512
|
+
lines.push("## Stack UI Guidance", "");
|
|
513
|
+
lines.push(`- Stack: ${model.stackGuidance.label ?? labelFromId(model.stackGuidance.stack)} (${model.stackGuidance.stack})`);
|
|
514
|
+
lines.push(...model.stackGuidance.guidance.map((item) => `- ${item}`), "");
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return `${lines.join("\n")}\n`;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* @param {Recommendation} model
|
|
522
|
+
* @returns {string}
|
|
523
|
+
*/
|
|
524
|
+
function renderPageOverride(model) {
|
|
525
|
+
const pageName = model.page || "page";
|
|
526
|
+
return [
|
|
527
|
+
`# Page Override: ${pageName}`,
|
|
528
|
+
"",
|
|
529
|
+
`Master: ../MASTER.md`,
|
|
530
|
+
`Product category: ${model.product.label} (${model.product.id})`,
|
|
531
|
+
"",
|
|
532
|
+
"## Page Intent",
|
|
533
|
+
"",
|
|
534
|
+
`Use the Master direction, then adapt layout and component density for ${pageName}. Keep overrides narrow and delete any rule that merely repeats the Master.`,
|
|
535
|
+
`Design read: ${model.designRead}.`,
|
|
536
|
+
"",
|
|
537
|
+
"## Override Strategy",
|
|
538
|
+
"",
|
|
539
|
+
`- Primary pattern: ${model.product.pattern}`,
|
|
540
|
+
`- Dials: visual ${model.designDials.visualTension}/10, motion ${model.designDials.motionIntensity}/10, density ${model.designDials.informationDensity}/10, media ${model.designDials.mediaAuthenticity}/10, persuasion ${model.designDials.contentPersuasion}/10`,
|
|
541
|
+
`- Visual emphasis: ${model.style.usage}`,
|
|
542
|
+
`- Chart behavior: ${model.chart}`,
|
|
543
|
+
"",
|
|
544
|
+
"## State QA",
|
|
545
|
+
"",
|
|
546
|
+
"- Loading, empty, error, disabled, hover, focus, selected, and reduced-motion states are visible.",
|
|
547
|
+
"- Mobile, tablet, and desktop layouts preserve task order and readable tap targets.",
|
|
548
|
+
"",
|
|
549
|
+
].join("\n");
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* @param {Recommendation} model
|
|
554
|
+
* @param {CliArgs} args
|
|
555
|
+
* @returns {void}
|
|
556
|
+
*/
|
|
557
|
+
function persistRecommendation(model, args) {
|
|
558
|
+
const projectSlug = slug(args.project || model.project || "project");
|
|
559
|
+
const projectDir = path.join(path.resolve(args.outputDir), "design-system", projectSlug);
|
|
560
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
561
|
+
fs.writeFileSync(path.join(projectDir, "MASTER.md"), renderMarkdown(model), "utf8");
|
|
562
|
+
|
|
563
|
+
if (args.page) {
|
|
564
|
+
const pagesDir = path.join(projectDir, "pages");
|
|
565
|
+
fs.mkdirSync(pagesDir, { recursive: true });
|
|
566
|
+
fs.writeFileSync(path.join(pagesDir, `${slug(args.page)}.md`), renderPageOverride(model), "utf8");
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* @param {string} value
|
|
572
|
+
* @returns {Set<string>}
|
|
573
|
+
*/
|
|
574
|
+
function tokenize(value) {
|
|
575
|
+
return new Set(
|
|
576
|
+
value
|
|
577
|
+
.toLowerCase()
|
|
578
|
+
.split(/[^a-z0-9]+/g)
|
|
579
|
+
.filter(Boolean),
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* @param {Set<string>} tokens
|
|
585
|
+
* @param {Array<string | undefined>} keywords
|
|
586
|
+
* @returns {number}
|
|
587
|
+
*/
|
|
588
|
+
function score(tokens, keywords) {
|
|
589
|
+
return keywords.reduce((total, keyword) => total + (tokens.has(slug(keyword)) || tokens.has(String(keyword).toLowerCase()) ? 1 : 0), 0);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* @param {unknown} value
|
|
594
|
+
* @returns {string}
|
|
595
|
+
*/
|
|
596
|
+
function slug(value) {
|
|
597
|
+
return String(value)
|
|
598
|
+
.trim()
|
|
599
|
+
.toLowerCase()
|
|
600
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
601
|
+
.replace(/^-+|-+$/g, "");
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* @param {string} value
|
|
606
|
+
* @returns {string}
|
|
607
|
+
*/
|
|
608
|
+
function normalizeStack(value) {
|
|
609
|
+
return value ? slug(value).replace(/-?js$/, "") : "";
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* @param {string} value
|
|
614
|
+
* @returns {string}
|
|
615
|
+
*/
|
|
616
|
+
function titleCase(value) {
|
|
617
|
+
return String(value)
|
|
618
|
+
.split(/\s+/g)
|
|
619
|
+
.filter(Boolean)
|
|
620
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
621
|
+
.join(" ");
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* @param {Array<string | undefined | null | false>} values
|
|
626
|
+
* @returns {string[]}
|
|
627
|
+
*/
|
|
628
|
+
function unique(values) {
|
|
629
|
+
/** @type {string[]} */
|
|
630
|
+
const strings = [];
|
|
631
|
+
for (const value of values) {
|
|
632
|
+
if (typeof value === "string" && value.length > 0) strings.push(value);
|
|
633
|
+
}
|
|
634
|
+
return [...new Set(strings)];
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* @param {unknown} value
|
|
639
|
+
* @returns {string}
|
|
640
|
+
*/
|
|
641
|
+
function labelFromId(value) {
|
|
642
|
+
return String(value)
|
|
643
|
+
.split("-")
|
|
644
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
645
|
+
.join(" ");
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
main();
|