@nguyenphp/antigravity-marketing 1.0.16 ā 1.0.18
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 +10 -5
- package/bin/index.js +4 -4
- package/package.json +1 -1
- package/templates/.agent/agents/backend-specialist.md +263 -0
- package/templates/.agent/agents/database-architect.md +226 -0
- package/templates/.agent/agents/debugger.md +225 -0
- package/templates/.agent/agents/devops-engineer.md +242 -0
- package/templates/.agent/agents/documentation-writer.md +104 -0
- package/templates/.agent/agents/explorer-agent.md +73 -0
- package/templates/.agent/agents/frontend-specialist.md +527 -0
- package/templates/.agent/agents/game-developer.md +162 -0
- package/templates/.agent/agents/mobile-developer.md +377 -0
- package/templates/.agent/agents/orchestrator.md +400 -0
- package/templates/.agent/agents/penetration-tester.md +188 -0
- package/templates/.agent/agents/performance-optimizer.md +187 -0
- package/templates/.agent/agents/project-planner.md +403 -0
- package/templates/.agent/agents/security-auditor.md +170 -0
- package/templates/.agent/agents/seo-specialist.md +111 -0
- package/templates/.agent/agents/test-engineer.md +158 -0
- package/templates/.agent/rules/GEMINI.md +248 -0
- package/templates/.agent/skills/analytics-marketing/SKILL.md +172 -324
- package/templates/.agent/skills/api-patterns/SKILL.md +81 -0
- package/templates/.agent/skills/api-patterns/api-style.md +42 -0
- package/templates/.agent/skills/api-patterns/auth.md +24 -0
- package/templates/.agent/skills/api-patterns/documentation.md +26 -0
- package/templates/.agent/skills/api-patterns/graphql.md +41 -0
- package/templates/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/templates/.agent/skills/api-patterns/response.md +37 -0
- package/templates/.agent/skills/api-patterns/rest.md +40 -0
- package/templates/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/templates/.agent/skills/api-patterns/security-testing.md +122 -0
- package/templates/.agent/skills/api-patterns/trpc.md +41 -0
- package/templates/.agent/skills/api-patterns/versioning.md +22 -0
- package/templates/.agent/skills/app-builder/SKILL.md +75 -0
- package/templates/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/templates/.agent/skills/app-builder/feature-building.md +53 -0
- package/templates/.agent/skills/app-builder/project-detection.md +34 -0
- package/templates/.agent/skills/app-builder/scaffolding.md +118 -0
- package/templates/.agent/skills/app-builder/tech-stack.md +40 -0
- package/templates/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/templates/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/templates/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/templates/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/templates/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/templates/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/templates/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/templates/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/templates/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/templates/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/templates/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/templates/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/templates/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/templates/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/templates/.agent/skills/architecture/SKILL.md +55 -0
- package/templates/.agent/skills/architecture/context-discovery.md +43 -0
- package/templates/.agent/skills/architecture/examples.md +94 -0
- package/templates/.agent/skills/architecture/pattern-selection.md +68 -0
- package/templates/.agent/skills/architecture/patterns-reference.md +50 -0
- package/templates/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/templates/.agent/skills/banner-design/SKILL.md +192 -0
- package/templates/.agent/skills/banner-design/references/banner-sizes-and-styles.md +118 -0
- package/templates/.agent/skills/bash-linux/SKILL.md +199 -0
- package/templates/.agent/skills/behavioral-modes/SKILL.md +242 -0
- package/templates/.agent/skills/brainstorming/SKILL.md +163 -0
- package/templates/.agent/skills/brainstorming/dynamic-questioning.md +350 -0
- package/templates/.agent/skills/brand/SKILL.md +97 -0
- package/templates/.agent/skills/brand/references/approval-checklist.md +169 -0
- package/templates/.agent/skills/brand/references/asset-organization.md +157 -0
- package/templates/.agent/skills/brand/references/brand-guideline-template.md +140 -0
- package/templates/.agent/skills/brand/references/color-palette-management.md +186 -0
- package/templates/.agent/skills/brand/references/consistency-checklist.md +94 -0
- package/templates/.agent/skills/brand/references/logo-usage-rules.md +185 -0
- package/templates/.agent/skills/brand/references/messaging-framework.md +85 -0
- package/templates/.agent/skills/brand/references/typography-specifications.md +214 -0
- package/templates/.agent/skills/brand/references/update.md +118 -0
- package/templates/.agent/skills/brand/references/visual-identity.md +96 -0
- package/templates/.agent/skills/brand/references/voice-framework.md +88 -0
- package/templates/.agent/skills/brand/scripts/extract-colors.cjs +341 -0
- package/templates/.agent/skills/brand/scripts/inject-brand-context.cjs +349 -0
- package/templates/.agent/skills/brand/scripts/sync-brand-to-tokens.cjs +266 -0
- package/templates/.agent/skills/brand/scripts/validate-asset.cjs +387 -0
- package/templates/.agent/skills/brand/templates/brand-guidelines-starter.md +275 -0
- package/templates/.agent/skills/clean-code/SKILL.md +201 -0
- package/templates/.agent/skills/code-review-checklist/SKILL.md +109 -0
- package/templates/.agent/skills/copywriting/SKILL.md +250 -0
- package/templates/.agent/skills/database-design/SKILL.md +52 -0
- package/templates/.agent/skills/database-design/database-selection.md +43 -0
- package/templates/.agent/skills/database-design/indexing.md +39 -0
- package/templates/.agent/skills/database-design/migrations.md +48 -0
- package/templates/.agent/skills/database-design/optimization.md +36 -0
- package/templates/.agent/skills/database-design/orm-selection.md +30 -0
- package/templates/.agent/skills/database-design/schema-design.md +56 -0
- package/templates/.agent/skills/database-design/scripts/schema_validator.py +172 -0
- package/templates/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/templates/.agent/skills/docker-expert/SKILL.md +409 -0
- package/templates/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/templates/.agent/skills/frontend-design/color-system.md +311 -0
- package/templates/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/templates/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/templates/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/.agent/skills/frontend-design/typography-system.md +345 -0
- package/templates/.agent/skills/frontend-design/ux-psychology.md +541 -0
- package/templates/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/templates/.agent/skills/frontend-slides/SKILL.md +92 -0
- package/templates/.agent/skills/frontend-slides/STYLE_PRESETS.md +347 -0
- package/templates/.agent/skills/frontend-slides/animation-patterns.md +110 -0
- package/templates/.agent/skills/frontend-slides/examples/n8n-jupviec-automation.html +789 -0
- package/templates/.agent/skills/frontend-slides/examples/n8n-jupviec-automation.pptx +0 -0
- package/templates/.agent/skills/frontend-slides/html-template.md +347 -0
- package/templates/.agent/skills/frontend-slides/scripts/export-pptx.py +58 -0
- package/templates/.agent/skills/frontend-slides/scripts/extract-pptx.py +96 -0
- package/templates/.agent/skills/frontend-slides/viewport-base.css +153 -0
- package/templates/.agent/skills/game-development/2d-games/SKILL.md +119 -0
- package/templates/.agent/skills/game-development/3d-games/SKILL.md +135 -0
- package/templates/.agent/skills/game-development/SKILL.md +167 -0
- package/templates/.agent/skills/game-development/game-art/SKILL.md +185 -0
- package/templates/.agent/skills/game-development/game-audio/SKILL.md +190 -0
- package/templates/.agent/skills/game-development/game-design/SKILL.md +129 -0
- package/templates/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
- package/templates/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
- package/templates/.agent/skills/game-development/pc-games/SKILL.md +144 -0
- package/templates/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
- package/templates/.agent/skills/game-development/web-games/SKILL.md +150 -0
- package/templates/.agent/skills/geo-fundamentals/SKILL.md +156 -0
- package/templates/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/.agent/skills/growth-engine/SKILL.md +244 -0
- package/templates/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/templates/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/.agent/skills/lint-and-validate/SKILL.md +45 -0
- package/templates/.agent/skills/lint-and-validate/scripts/lint_runner.py +172 -0
- package/templates/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/templates/.agent/skills/mobile-design/SKILL.md +394 -0
- package/templates/.agent/skills/mobile-design/decision-trees.md +516 -0
- package/templates/.agent/skills/mobile-design/mobile-backend.md +491 -0
- package/templates/.agent/skills/mobile-design/mobile-color-system.md +420 -0
- package/templates/.agent/skills/mobile-design/mobile-debugging.md +122 -0
- package/templates/.agent/skills/mobile-design/mobile-design-thinking.md +357 -0
- package/templates/.agent/skills/mobile-design/mobile-navigation.md +458 -0
- package/templates/.agent/skills/mobile-design/mobile-performance.md +767 -0
- package/templates/.agent/skills/mobile-design/mobile-testing.md +356 -0
- package/templates/.agent/skills/mobile-design/mobile-typography.md +433 -0
- package/templates/.agent/skills/mobile-design/platform-android.md +666 -0
- package/templates/.agent/skills/mobile-design/platform-ios.md +561 -0
- package/templates/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/.agent/skills/mobile-design/touch-psychology.md +537 -0
- package/templates/.agent/skills/nestjs-expert/SKILL.md +552 -0
- package/templates/.agent/skills/nextjs-best-practices/SKILL.md +203 -0
- package/templates/.agent/skills/nodejs-best-practices/SKILL.md +333 -0
- package/templates/.agent/skills/parallel-agents/SKILL.md +175 -0
- package/templates/.agent/skills/performance-profiling/SKILL.md +143 -0
- package/templates/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/.agent/skills/plan-writing/SKILL.md +152 -0
- package/templates/.agent/skills/powershell-windows/SKILL.md +167 -0
- package/templates/.agent/skills/ppc-advertising/SKILL.md +183 -475
- package/templates/.agent/skills/prisma-expert/SKILL.md +355 -0
- package/templates/.agent/skills/python-patterns/SKILL.md +441 -0
- package/templates/.agent/skills/react-patterns/SKILL.md +198 -0
- package/templates/.agent/skills/red-team-tactics/SKILL.md +199 -0
- package/templates/.agent/skills/remotion-best-practices/SKILL.md +45 -111
- package/templates/.agent/skills/remotion-best-practices/rules/3d.md +4 -4
- package/templates/.agent/skills/remotion-best-practices/rules/animations.md +5 -7
- package/templates/.agent/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/templates/.agent/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/templates/.agent/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
- package/templates/.agent/skills/remotion-best-practices/rules/assets.md +78 -0
- package/templates/.agent/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
- package/templates/.agent/skills/remotion-best-practices/rules/audio.md +1 -4
- package/templates/.agent/skills/remotion-best-practices/rules/calculate-metadata.md +47 -17
- package/templates/.agent/skills/remotion-best-practices/rules/can-decode.md +75 -0
- package/templates/.agent/skills/remotion-best-practices/rules/charts.md +80 -48
- package/templates/.agent/skills/remotion-best-practices/rules/compositions.md +22 -14
- package/templates/.agent/skills/remotion-best-practices/rules/display-captions.md +79 -21
- package/templates/.agent/skills/remotion-best-practices/rules/extract-frames.md +229 -0
- package/templates/.agent/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
- package/templates/.agent/skills/remotion-best-practices/rules/fonts.md +96 -54
- package/templates/.agent/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/templates/.agent/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/templates/.agent/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
- package/templates/.agent/skills/remotion-best-practices/rules/gifs.md +21 -18
- package/templates/.agent/skills/remotion-best-practices/rules/images.md +6 -2
- package/templates/.agent/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
- package/templates/.agent/skills/remotion-best-practices/rules/light-leaks.md +73 -0
- package/templates/.agent/skills/remotion-best-practices/rules/lottie.md +10 -7
- package/templates/.agent/skills/remotion-best-practices/rules/maps.md +412 -0
- package/templates/.agent/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
- package/templates/.agent/skills/remotion-best-practices/rules/measuring-text.md +140 -0
- package/templates/.agent/skills/remotion-best-practices/rules/parameters.md +109 -0
- package/templates/.agent/skills/remotion-best-practices/rules/sequencing.md +13 -1
- package/templates/.agent/skills/remotion-best-practices/rules/sfx.md +26 -0
- package/templates/.agent/skills/remotion-best-practices/rules/subtitles.md +36 -0
- package/templates/.agent/skills/remotion-best-practices/rules/tailwind.md +11 -0
- package/templates/.agent/skills/remotion-best-practices/rules/text-animations.md +4 -115
- package/templates/.agent/skills/remotion-best-practices/rules/timing.md +19 -19
- package/templates/.agent/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
- package/templates/.agent/skills/remotion-best-practices/rules/transitions.md +117 -42
- package/templates/.agent/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
- package/templates/.agent/skills/remotion-best-practices/rules/trimming.md +51 -0
- package/templates/.agent/skills/remotion-best-practices/rules/voiceover.md +99 -0
- package/templates/.agent/skills/seo-fundamentals/SKILL.md +83 -441
- package/templates/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/.agent/skills/server-management/SKILL.md +161 -0
- package/templates/.agent/skills/systematic-debugging/SKILL.md +109 -0
- package/templates/.agent/skills/tdd-workflow/SKILL.md +149 -0
- package/templates/.agent/skills/testing-patterns/SKILL.md +178 -0
- package/templates/.agent/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/.agent/skills/typescript-expert/SKILL.md +429 -0
- package/templates/.agent/skills/ui-ux-pro-max/SKILL.md +585 -170
- package/templates/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/templates/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/templates/.agent/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/templates/.agent/skills/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/templates/.agent/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/templates/.agent/skills/vue-expert/SKILL.md +374 -0
- package/templates/.agent/skills/vulnerability-scanner/SKILL.md +276 -0
- package/templates/.agent/skills/vulnerability-scanner/checklists.md +121 -0
- package/templates/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/.agent/skills/webapp-testing/SKILL.md +187 -0
- package/templates/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -0
- package/templates/.agent/workflows/brainstorm.md +113 -0
- package/templates/.agent/workflows/create.md +59 -0
- package/templates/.agent/workflows/debug.md +103 -0
- package/templates/.agent/workflows/deploy.md +176 -0
- package/templates/.agent/workflows/enhance.md +63 -0
- package/templates/.agent/workflows/orchestrate.md +237 -0
- package/templates/.agent/workflows/plan.md +89 -0
- package/templates/.agent/workflows/preview.md +80 -0
- package/templates/.agent/workflows/status.md +86 -0
- package/templates/.agent/workflows/test.md +144 -0
- package/templates/.agent/workflows/ui-ux-pro-max.md +231 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* inject-brand-context.cjs
|
|
4
|
+
*
|
|
5
|
+
* Extracts brand context from markdown brand guidelines
|
|
6
|
+
* and outputs a formatted system prompt addition.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node inject-brand-context.cjs [path-to-guidelines]
|
|
10
|
+
* node inject-brand-context.cjs --json [path-to-guidelines]
|
|
11
|
+
*
|
|
12
|
+
* Default path: docs/brand-guidelines.md
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require("fs");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
|
|
18
|
+
// Default brand guidelines path
|
|
19
|
+
const DEFAULT_GUIDELINES_PATH = "docs/brand-guidelines.md";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract hex colors from text
|
|
23
|
+
*/
|
|
24
|
+
function extractHexColors(text) {
|
|
25
|
+
const hexPattern = /#[0-9A-Fa-f]{6}\b/g;
|
|
26
|
+
return [...new Set(text.match(hexPattern) || [])];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Extract color data from markdown table
|
|
31
|
+
*/
|
|
32
|
+
function extractColorsFromTable(content) {
|
|
33
|
+
const colors = {
|
|
34
|
+
primary: [],
|
|
35
|
+
secondary: [],
|
|
36
|
+
neutral: [],
|
|
37
|
+
semantic: [],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Find color tables
|
|
41
|
+
const primaryMatch = content.match(
|
|
42
|
+
/### Primary Colors[\s\S]*?\|[\s\S]*?(?=###|$)/i
|
|
43
|
+
);
|
|
44
|
+
const secondaryMatch = content.match(
|
|
45
|
+
/### Secondary Colors[\s\S]*?\|[\s\S]*?(?=###|$)/i
|
|
46
|
+
);
|
|
47
|
+
const neutralMatch = content.match(
|
|
48
|
+
/### Neutral[\s\S]*?\|[\s\S]*?(?=###|$)/i
|
|
49
|
+
);
|
|
50
|
+
const semanticMatch = content.match(
|
|
51
|
+
/### Semantic[\s\S]*?\|[\s\S]*?(?=###|$)/i
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (primaryMatch) colors.primary = extractHexColors(primaryMatch[0]);
|
|
55
|
+
if (secondaryMatch) colors.secondary = extractHexColors(secondaryMatch[0]);
|
|
56
|
+
if (neutralMatch) colors.neutral = extractHexColors(neutralMatch[0]);
|
|
57
|
+
if (semanticMatch) colors.semantic = extractHexColors(semanticMatch[0]);
|
|
58
|
+
|
|
59
|
+
return colors;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Extract typography info
|
|
64
|
+
*/
|
|
65
|
+
function extractTypography(content) {
|
|
66
|
+
const typography = {
|
|
67
|
+
heading: null,
|
|
68
|
+
body: null,
|
|
69
|
+
mono: null,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Look for font definitions
|
|
73
|
+
const headingMatch = content.match(/--font-heading:\s*['"]([^'"]+)['"]/);
|
|
74
|
+
const bodyMatch = content.match(/--font-body:\s*['"]([^'"]+)['"]/);
|
|
75
|
+
const monoMatch = content.match(/--font-mono:\s*['"]([^'"]+)['"]/);
|
|
76
|
+
|
|
77
|
+
// Fallback: look in tables
|
|
78
|
+
const fontStackMatch = content.match(/### Font Stack[\s\S]*?(?=###|##|$)/i);
|
|
79
|
+
if (fontStackMatch) {
|
|
80
|
+
const stackText = fontStackMatch[0];
|
|
81
|
+
const headingAlt = stackText.match(/heading[^']*['"]([^'"]+)['"]/i);
|
|
82
|
+
const bodyAlt = stackText.match(/body[^']*['"]([^'"]+)['"]/i);
|
|
83
|
+
|
|
84
|
+
if (headingAlt) typography.heading = headingAlt[1];
|
|
85
|
+
if (bodyAlt) typography.body = bodyAlt[1];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (headingMatch) typography.heading = headingMatch[1];
|
|
89
|
+
if (bodyMatch) typography.body = bodyMatch[1];
|
|
90
|
+
if (monoMatch) typography.mono = monoMatch[1];
|
|
91
|
+
|
|
92
|
+
return typography;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Extract voice/tone information
|
|
97
|
+
*/
|
|
98
|
+
function extractVoice(content) {
|
|
99
|
+
const voice = {
|
|
100
|
+
traits: [],
|
|
101
|
+
prohibited: [],
|
|
102
|
+
personality: "",
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Extract personality traits from table
|
|
106
|
+
const personalityMatch = content.match(
|
|
107
|
+
/### Brand Personality[\s\S]*?\|[\s\S]*?(?=###|##|$)/i
|
|
108
|
+
);
|
|
109
|
+
if (personalityMatch) {
|
|
110
|
+
const traits = personalityMatch[0].match(
|
|
111
|
+
/\*\*([^*]+)\*\*\s*\|\s*([^|]+)/g
|
|
112
|
+
);
|
|
113
|
+
if (traits) {
|
|
114
|
+
voice.traits = traits.map((t) => {
|
|
115
|
+
const match = t.match(/\*\*([^*]+)\*\*/);
|
|
116
|
+
return match ? match[1].trim() : "";
|
|
117
|
+
}).filter(Boolean);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Extract prohibited terms
|
|
122
|
+
const prohibitedMatch = content.match(
|
|
123
|
+
/### Prohibited[\s\S]*?(?=###|##|$)/i
|
|
124
|
+
);
|
|
125
|
+
if (prohibitedMatch) {
|
|
126
|
+
const terms = prohibitedMatch[0].match(/\|\s*([^|]+)\s*\|/g);
|
|
127
|
+
if (terms) {
|
|
128
|
+
voice.prohibited = terms
|
|
129
|
+
.map((t) => t.replace(/\|/g, "").trim())
|
|
130
|
+
.filter((t) => t && !t.includes("Avoid") && !t.includes("---"));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Fallback: look for Forbidden Phrases
|
|
135
|
+
const forbiddenMatch = content.match(
|
|
136
|
+
/### Forbidden Phrases[\s\S]*?(?=###|##|$)/i
|
|
137
|
+
);
|
|
138
|
+
if (forbiddenMatch && voice.prohibited.length === 0) {
|
|
139
|
+
const items = forbiddenMatch[0].match(/-\s*["']?([^"'\n(]+)/g);
|
|
140
|
+
if (items) {
|
|
141
|
+
voice.prohibited = items
|
|
142
|
+
.map((item) => item.replace(/^-\s*["']?/, "").trim())
|
|
143
|
+
.filter(Boolean);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
voice.personality = voice.traits.join(", ");
|
|
148
|
+
|
|
149
|
+
return voice;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Extract core attributes
|
|
154
|
+
*/
|
|
155
|
+
function extractCoreAttributes(content) {
|
|
156
|
+
const attributes = [];
|
|
157
|
+
|
|
158
|
+
const attributesMatch = content.match(
|
|
159
|
+
/### Core Attributes[\s\S]*?\|[\s\S]*?(?=###|##|$)/i
|
|
160
|
+
);
|
|
161
|
+
if (attributesMatch) {
|
|
162
|
+
const rows = attributesMatch[0].match(
|
|
163
|
+
/\|\s*\*\*([^*]+)\*\*\s*\|\s*([^|]+)\|/g
|
|
164
|
+
);
|
|
165
|
+
if (rows) {
|
|
166
|
+
rows.forEach((row) => {
|
|
167
|
+
const match = row.match(/\*\*([^*]+)\*\*\s*\|\s*([^|]+)/);
|
|
168
|
+
if (match) {
|
|
169
|
+
attributes.push({
|
|
170
|
+
name: match[1].trim(),
|
|
171
|
+
description: match[2].trim(),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return attributes;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Extract AI image generation context
|
|
183
|
+
*/
|
|
184
|
+
function extractImageStyle(content) {
|
|
185
|
+
const imageStyle = {
|
|
186
|
+
basePrompt: "",
|
|
187
|
+
keywords: [],
|
|
188
|
+
mood: [],
|
|
189
|
+
donts: [],
|
|
190
|
+
examplePrompts: [],
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Extract base prompt template (content between ``` blocks after "Base Prompt Template")
|
|
194
|
+
const basePromptMatch = content.match(
|
|
195
|
+
/### Base Prompt Template[\s\S]*?```\n?([\s\S]*?)```/i
|
|
196
|
+
);
|
|
197
|
+
if (basePromptMatch) {
|
|
198
|
+
imageStyle.basePrompt = basePromptMatch[1].trim().replace(/\n/g, " ");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Extract style keywords from table
|
|
202
|
+
const keywordsMatch = content.match(
|
|
203
|
+
/### Style Keywords[\s\S]*?\|[\s\S]*?(?=###|##|$)/i
|
|
204
|
+
);
|
|
205
|
+
if (keywordsMatch) {
|
|
206
|
+
const keywordRows = keywordsMatch[0].match(/\|\s*\*\*[^*]+\*\*\s*\|\s*([^|]+)\|/g);
|
|
207
|
+
if (keywordRows) {
|
|
208
|
+
keywordRows.forEach((row) => {
|
|
209
|
+
const match = row.match(/\|\s*\*\*[^*]+\*\*\s*\|\s*([^|]+)\|/);
|
|
210
|
+
if (match) {
|
|
211
|
+
const keywords = match[1].split(",").map((k) => k.trim()).filter(Boolean);
|
|
212
|
+
imageStyle.keywords.push(...keywords);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Extract visual mood descriptors (bullet points)
|
|
219
|
+
const moodMatch = content.match(
|
|
220
|
+
/### Visual Mood Descriptors[\s\S]*?(?=###|##|$)/i
|
|
221
|
+
);
|
|
222
|
+
if (moodMatch) {
|
|
223
|
+
const moodItems = moodMatch[0].match(/-\s*([^\n]+)/g);
|
|
224
|
+
if (moodItems) {
|
|
225
|
+
imageStyle.mood = moodItems.map((item) => item.replace(/^-\s*/, "").trim());
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Extract visual don'ts from table
|
|
230
|
+
const dontsMatch = content.match(
|
|
231
|
+
/### Visual Don'ts[\s\S]*?\|[\s\S]*?(?=###|##|$)/i
|
|
232
|
+
);
|
|
233
|
+
if (dontsMatch) {
|
|
234
|
+
const dontRows = dontsMatch[0].match(/\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|/g);
|
|
235
|
+
if (dontRows) {
|
|
236
|
+
dontRows.forEach((row) => {
|
|
237
|
+
const match = row.match(/\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|/);
|
|
238
|
+
if (match && !match[1].includes("Avoid") && !match[1].includes("---")) {
|
|
239
|
+
imageStyle.donts.push(match[1].trim());
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Extract example prompts (content between ``` blocks after specific headers)
|
|
246
|
+
const exampleMatch = content.match(/### Example Prompts[\s\S]*?(?=##|$)/i);
|
|
247
|
+
if (exampleMatch) {
|
|
248
|
+
const prompts = exampleMatch[0].match(/\*\*([^*]+)\*\*:\s*```\n?([\s\S]*?)```/g);
|
|
249
|
+
if (prompts) {
|
|
250
|
+
prompts.forEach((p) => {
|
|
251
|
+
const match = p.match(/\*\*([^*]+)\*\*:\s*```\n?([\s\S]*?)```/);
|
|
252
|
+
if (match) {
|
|
253
|
+
imageStyle.examplePrompts.push({
|
|
254
|
+
type: match[1].trim(),
|
|
255
|
+
prompt: match[2].trim().replace(/\n/g, " "),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return imageStyle;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Generate system prompt addition
|
|
267
|
+
*/
|
|
268
|
+
function generatePromptAddition(brandContext) {
|
|
269
|
+
const { colors, typography, voice, attributes, imageStyle } = brandContext;
|
|
270
|
+
|
|
271
|
+
let prompt = `
|
|
272
|
+
BRAND CONTEXT:
|
|
273
|
+
==============
|
|
274
|
+
|
|
275
|
+
VISUAL IDENTITY:
|
|
276
|
+
- Primary Colors: ${colors.primary.join(", ") || "Not specified"}
|
|
277
|
+
- Secondary Colors: ${colors.secondary.join(", ") || "Not specified"}
|
|
278
|
+
- Typography: ${typography.heading || typography.body || "System fonts"}
|
|
279
|
+
|
|
280
|
+
BRAND VOICE:
|
|
281
|
+
- Personality: ${voice.personality || "Professional"}
|
|
282
|
+
- Core Attributes: ${attributes.map((a) => a.name).join(", ") || "Not specified"}
|
|
283
|
+
|
|
284
|
+
CONTENT RULES:
|
|
285
|
+
- Prohibited Terms: ${voice.prohibited.join(", ") || "None specified"}
|
|
286
|
+
`;
|
|
287
|
+
|
|
288
|
+
// Add image style context if available
|
|
289
|
+
if (imageStyle && imageStyle.basePrompt) {
|
|
290
|
+
prompt += `
|
|
291
|
+
IMAGE GENERATION:
|
|
292
|
+
- Base Prompt: ${imageStyle.basePrompt}
|
|
293
|
+
- Style Keywords: ${imageStyle.keywords.slice(0, 10).join(", ") || "Not specified"}
|
|
294
|
+
- Visual Mood: ${imageStyle.mood.slice(0, 5).join("; ") || "Not specified"}
|
|
295
|
+
- Avoid: ${imageStyle.donts.join(", ") || "None specified"}
|
|
296
|
+
`;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
prompt += `
|
|
300
|
+
Apply these brand guidelines to all generated content.
|
|
301
|
+
Maintain consistent voice, colors, and messaging.
|
|
302
|
+
`;
|
|
303
|
+
|
|
304
|
+
return prompt.trim();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Main function
|
|
309
|
+
*/
|
|
310
|
+
function main() {
|
|
311
|
+
const args = process.argv.slice(2);
|
|
312
|
+
const jsonOutput = args.includes("--json");
|
|
313
|
+
const guidelinesPath = args.find((a) => !a.startsWith("--")) || DEFAULT_GUIDELINES_PATH;
|
|
314
|
+
|
|
315
|
+
// Resolve path
|
|
316
|
+
const resolvedPath = path.isAbsolute(guidelinesPath)
|
|
317
|
+
? guidelinesPath
|
|
318
|
+
: path.join(process.cwd(), guidelinesPath);
|
|
319
|
+
|
|
320
|
+
// Check if file exists
|
|
321
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
322
|
+
console.error(`Error: Brand guidelines not found at ${resolvedPath}`);
|
|
323
|
+
console.error(`Create brand guidelines at ${DEFAULT_GUIDELINES_PATH} or specify a path.`);
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Read file
|
|
328
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
329
|
+
|
|
330
|
+
// Extract brand context
|
|
331
|
+
const brandContext = {
|
|
332
|
+
colors: extractColorsFromTable(content),
|
|
333
|
+
typography: extractTypography(content),
|
|
334
|
+
voice: extractVoice(content),
|
|
335
|
+
attributes: extractCoreAttributes(content),
|
|
336
|
+
imageStyle: extractImageStyle(content),
|
|
337
|
+
source: resolvedPath,
|
|
338
|
+
extractedAt: new Date().toISOString(),
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// Output
|
|
342
|
+
if (jsonOutput) {
|
|
343
|
+
console.log(JSON.stringify(brandContext, null, 2));
|
|
344
|
+
} else {
|
|
345
|
+
console.log(generatePromptAddition(brandContext));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
main();
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* sync-brand-to-tokens.cjs
|
|
4
|
+
*
|
|
5
|
+
* Syncs brand-guidelines.md colors ā design-tokens.json ā design-tokens.css
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node sync-brand-to-tokens.cjs
|
|
9
|
+
* node sync-brand-to-tokens.cjs --dry-run
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const { execSync } = require('child_process');
|
|
15
|
+
|
|
16
|
+
// Paths
|
|
17
|
+
const BRAND_GUIDELINES = 'docs/brand-guidelines.md';
|
|
18
|
+
const DESIGN_TOKENS_JSON = 'assets/design-tokens.json';
|
|
19
|
+
const DESIGN_TOKENS_CSS = 'assets/design-tokens.css';
|
|
20
|
+
const GENERATE_TOKENS_SCRIPT = '.claude/skills/design-system/scripts/generate-tokens.cjs';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Extract color info from brand guidelines markdown
|
|
24
|
+
*/
|
|
25
|
+
function extractColorsFromMarkdown(content) {
|
|
26
|
+
const colors = {
|
|
27
|
+
primary: { name: 'primary', shades: {} },
|
|
28
|
+
secondary: { name: 'secondary', shades: {} },
|
|
29
|
+
accent: { name: 'accent', shades: {} }
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Extract primary color name and hex from Quick Reference table
|
|
33
|
+
const quickRefMatch = content.match(/Primary Color\s*\|\s*#([A-Fa-f0-9]{6})\s*\(([^)]+)\)/);
|
|
34
|
+
if (quickRefMatch) {
|
|
35
|
+
colors.primary.name = quickRefMatch[2].toLowerCase().replace(/\s+/g, '-');
|
|
36
|
+
colors.primary.base = `#${quickRefMatch[1]}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const secondaryMatch = content.match(/Secondary Color\s*\|\s*#([A-Fa-f0-9]{6})\s*\(([^)]+)\)/);
|
|
40
|
+
if (secondaryMatch) {
|
|
41
|
+
colors.secondary.name = secondaryMatch[2].toLowerCase().replace(/\s+/g, '-');
|
|
42
|
+
colors.secondary.base = `#${secondaryMatch[1]}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const accentMatch = content.match(/Accent Color\s*\|\s*#([A-Fa-f0-9]{6})\s*\(([^)]+)\)/);
|
|
46
|
+
if (accentMatch) {
|
|
47
|
+
colors.accent.name = accentMatch[2].toLowerCase().replace(/\s+/g, '-');
|
|
48
|
+
colors.accent.base = `#${accentMatch[1]}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Extract all shades from Primary Colors table
|
|
52
|
+
const primarySection = content.match(/### Primary Colors[\s\S]*?\|[\s\S]*?(?=###|$)/i);
|
|
53
|
+
if (primarySection) {
|
|
54
|
+
const hexMatches = primarySection[0].matchAll(/\*\*([^*]+)\*\*\s*\|\s*#([A-Fa-f0-9]{6})/g);
|
|
55
|
+
for (const match of hexMatches) {
|
|
56
|
+
const name = match[1].trim().toLowerCase();
|
|
57
|
+
const hex = `#${match[2]}`;
|
|
58
|
+
if (name.includes('dark')) colors.primary.dark = hex;
|
|
59
|
+
else if (name.includes('light')) colors.primary.light = hex;
|
|
60
|
+
else colors.primary.base = hex;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Extract secondary shades
|
|
65
|
+
const secondarySection = content.match(/### Secondary Colors[\s\S]*?\|[\s\S]*?(?=###|$)/i);
|
|
66
|
+
if (secondarySection) {
|
|
67
|
+
const hexMatches = secondarySection[0].matchAll(/\*\*([^*]+)\*\*\s*\|\s*#([A-Fa-f0-9]{6})/g);
|
|
68
|
+
for (const match of hexMatches) {
|
|
69
|
+
const name = match[1].trim().toLowerCase();
|
|
70
|
+
const hex = `#${match[2]}`;
|
|
71
|
+
if (name.includes('dark')) colors.secondary.dark = hex;
|
|
72
|
+
else if (name.includes('light')) colors.secondary.light = hex;
|
|
73
|
+
else colors.secondary.base = hex;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Extract accent shades
|
|
78
|
+
const accentSection = content.match(/### Accent Colors[\s\S]*?\|[\s\S]*?(?=###|$)/i);
|
|
79
|
+
if (accentSection) {
|
|
80
|
+
const hexMatches = accentSection[0].matchAll(/\*\*([^*]+)\*\*\s*\|\s*#([A-Fa-f0-9]{6})/g);
|
|
81
|
+
for (const match of hexMatches) {
|
|
82
|
+
const name = match[1].trim().toLowerCase();
|
|
83
|
+
const hex = `#${match[2]}`;
|
|
84
|
+
if (name.includes('dark')) colors.accent.dark = hex;
|
|
85
|
+
else if (name.includes('light')) colors.accent.light = hex;
|
|
86
|
+
else colors.accent.base = hex;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return colors;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Generate color scale from base color (simple approach)
|
|
95
|
+
*/
|
|
96
|
+
function generateColorScale(baseHex, darkHex, lightHex) {
|
|
97
|
+
// Use provided shades or generate approximations
|
|
98
|
+
return {
|
|
99
|
+
"50": { "$value": lightHex || adjustBrightness(baseHex, 0.9), "$type": "color" },
|
|
100
|
+
"100": { "$value": lightHex || adjustBrightness(baseHex, 0.8), "$type": "color" },
|
|
101
|
+
"200": { "$value": adjustBrightness(baseHex, 0.6), "$type": "color" },
|
|
102
|
+
"300": { "$value": adjustBrightness(baseHex, 0.4), "$type": "color" },
|
|
103
|
+
"400": { "$value": adjustBrightness(baseHex, 0.2), "$type": "color" },
|
|
104
|
+
"500": { "$value": baseHex, "$type": "color" },
|
|
105
|
+
"600": { "$value": darkHex || adjustBrightness(baseHex, -0.15), "$type": "color" },
|
|
106
|
+
"700": { "$value": adjustBrightness(baseHex, -0.3), "$type": "color" },
|
|
107
|
+
"800": { "$value": adjustBrightness(baseHex, -0.45), "$type": "color" },
|
|
108
|
+
"900": { "$value": adjustBrightness(baseHex, -0.6), "$type": "color" }
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Adjust hex color brightness
|
|
114
|
+
*/
|
|
115
|
+
function adjustBrightness(hex, percent) {
|
|
116
|
+
const num = parseInt(hex.replace('#', ''), 16);
|
|
117
|
+
const r = Math.min(255, Math.max(0, (num >> 16) + Math.round(255 * percent)));
|
|
118
|
+
const g = Math.min(255, Math.max(0, ((num >> 8) & 0x00FF) + Math.round(255 * percent)));
|
|
119
|
+
const b = Math.min(255, Math.max(0, (num & 0x0000FF) + Math.round(255 * percent)));
|
|
120
|
+
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0').toUpperCase()}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Update design tokens JSON
|
|
125
|
+
*/
|
|
126
|
+
function updateDesignTokens(tokens, colors) {
|
|
127
|
+
// Update brand name
|
|
128
|
+
const brandName = `ClaudeKit Marketing - ${colors.primary.name.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}`;
|
|
129
|
+
tokens.brand = brandName;
|
|
130
|
+
|
|
131
|
+
// Update primitive colors with new names
|
|
132
|
+
const primitiveColors = tokens.primitive?.color || {};
|
|
133
|
+
|
|
134
|
+
// Remove old color keys, add new ones
|
|
135
|
+
delete primitiveColors.coral;
|
|
136
|
+
delete primitiveColors.purple;
|
|
137
|
+
delete primitiveColors.mint;
|
|
138
|
+
|
|
139
|
+
// Add new named colors
|
|
140
|
+
primitiveColors[colors.primary.name] = generateColorScale(
|
|
141
|
+
colors.primary.base,
|
|
142
|
+
colors.primary.dark,
|
|
143
|
+
colors.primary.light
|
|
144
|
+
);
|
|
145
|
+
primitiveColors[colors.secondary.name] = generateColorScale(
|
|
146
|
+
colors.secondary.base,
|
|
147
|
+
colors.secondary.dark,
|
|
148
|
+
colors.secondary.light
|
|
149
|
+
);
|
|
150
|
+
primitiveColors[colors.accent.name] = generateColorScale(
|
|
151
|
+
colors.accent.base,
|
|
152
|
+
colors.accent.dark,
|
|
153
|
+
colors.accent.light
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
tokens.primitive.color = primitiveColors;
|
|
157
|
+
|
|
158
|
+
// Update ALL semantic color references
|
|
159
|
+
if (tokens.semantic?.color) {
|
|
160
|
+
const sem = tokens.semantic.color;
|
|
161
|
+
const p = colors.primary.name;
|
|
162
|
+
const s = colors.secondary.name;
|
|
163
|
+
const a = colors.accent.name;
|
|
164
|
+
|
|
165
|
+
// Primary variants
|
|
166
|
+
sem.primary = { "$value": `{primitive.color.${p}.500}`, "$type": "color" };
|
|
167
|
+
sem['primary-hover'] = { "$value": `{primitive.color.${p}.600}`, "$type": "color" };
|
|
168
|
+
sem['primary-active'] = { "$value": `{primitive.color.${p}.700}`, "$type": "color" };
|
|
169
|
+
sem['primary-light'] = { "$value": `{primitive.color.${p}.400}`, "$type": "color" };
|
|
170
|
+
sem['primary-lighter'] = { "$value": `{primitive.color.${p}.100}`, "$type": "color" };
|
|
171
|
+
sem['primary-dark'] = { "$value": `{primitive.color.${p}.600}`, "$type": "color" };
|
|
172
|
+
|
|
173
|
+
// Secondary variants
|
|
174
|
+
sem.secondary = { "$value": `{primitive.color.${s}.500}`, "$type": "color" };
|
|
175
|
+
sem['secondary-hover'] = { "$value": `{primitive.color.${s}.600}`, "$type": "color" };
|
|
176
|
+
sem['secondary-light'] = { "$value": `{primitive.color.${s}.300}`, "$type": "color" };
|
|
177
|
+
sem['secondary-dark'] = { "$value": `{primitive.color.${s}.600}`, "$type": "color" };
|
|
178
|
+
|
|
179
|
+
// Accent variants
|
|
180
|
+
sem.accent = { "$value": `{primitive.color.${a}.500}`, "$type": "color" };
|
|
181
|
+
sem['accent-hover'] = { "$value": `{primitive.color.${a}.600}`, "$type": "color" };
|
|
182
|
+
sem['accent-light'] = { "$value": `{primitive.color.${a}.300}`, "$type": "color" };
|
|
183
|
+
|
|
184
|
+
// Status colors (use accent for success, primary for error/info)
|
|
185
|
+
sem.success = { "$value": `{primitive.color.${a}.500}`, "$type": "color" };
|
|
186
|
+
sem['success-light'] = { "$value": `{primitive.color.${a}.300}`, "$type": "color" };
|
|
187
|
+
sem.error = { "$value": `{primitive.color.${p}.500}`, "$type": "color" };
|
|
188
|
+
sem['error-light'] = { "$value": `{primitive.color.${p}.300}`, "$type": "color" };
|
|
189
|
+
sem.info = { "$value": `{primitive.color.${s}.500}`, "$type": "color" };
|
|
190
|
+
sem['info-light'] = { "$value": `{primitive.color.${s}.300}`, "$type": "color" };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Update component references (button uses primary color with opacity)
|
|
194
|
+
if (tokens.component?.button?.secondary) {
|
|
195
|
+
const primaryBase = colors.primary.base;
|
|
196
|
+
tokens.component.button.secondary['bg-hover'] = {
|
|
197
|
+
"$value": `${primaryBase}1A`,
|
|
198
|
+
"$type": "color"
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return tokens;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Main
|
|
207
|
+
*/
|
|
208
|
+
function main() {
|
|
209
|
+
const dryRun = process.argv.includes('--dry-run');
|
|
210
|
+
|
|
211
|
+
console.log('š Syncing brand guidelines ā design tokens\n');
|
|
212
|
+
|
|
213
|
+
// Read brand guidelines
|
|
214
|
+
const guidelinesPath = path.resolve(process.cwd(), BRAND_GUIDELINES);
|
|
215
|
+
if (!fs.existsSync(guidelinesPath)) {
|
|
216
|
+
console.error(`ā Brand guidelines not found: ${guidelinesPath}`);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
const guidelinesContent = fs.readFileSync(guidelinesPath, 'utf-8');
|
|
220
|
+
|
|
221
|
+
// Extract colors
|
|
222
|
+
const colors = extractColorsFromMarkdown(guidelinesContent);
|
|
223
|
+
console.log('š Extracted colors:');
|
|
224
|
+
console.log(` Primary: ${colors.primary.name} (${colors.primary.base})`);
|
|
225
|
+
console.log(` Secondary: ${colors.secondary.name} (${colors.secondary.base})`);
|
|
226
|
+
console.log(` Accent: ${colors.accent.name} (${colors.accent.base})\n`);
|
|
227
|
+
|
|
228
|
+
// Read existing tokens
|
|
229
|
+
const tokensPath = path.resolve(process.cwd(), DESIGN_TOKENS_JSON);
|
|
230
|
+
let tokens = {};
|
|
231
|
+
if (fs.existsSync(tokensPath)) {
|
|
232
|
+
tokens = JSON.parse(fs.readFileSync(tokensPath, 'utf-8'));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Update tokens
|
|
236
|
+
tokens = updateDesignTokens(tokens, colors);
|
|
237
|
+
|
|
238
|
+
if (dryRun) {
|
|
239
|
+
console.log('š Would update design-tokens.json:');
|
|
240
|
+
console.log(JSON.stringify(tokens.primitive.color, null, 2).slice(0, 500) + '...');
|
|
241
|
+
console.log('\nāļø Dry run - no files changed');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Write updated tokens
|
|
246
|
+
fs.writeFileSync(tokensPath, JSON.stringify(tokens, null, 2));
|
|
247
|
+
console.log(`ā
Updated: ${DESIGN_TOKENS_JSON}`);
|
|
248
|
+
|
|
249
|
+
// Regenerate CSS
|
|
250
|
+
const generateScript = path.resolve(process.cwd(), GENERATE_TOKENS_SCRIPT);
|
|
251
|
+
if (fs.existsSync(generateScript)) {
|
|
252
|
+
try {
|
|
253
|
+
execSync(`node ${generateScript} --config ${DESIGN_TOKENS_JSON} -o ${DESIGN_TOKENS_CSS}`, {
|
|
254
|
+
cwd: process.cwd(),
|
|
255
|
+
stdio: 'inherit'
|
|
256
|
+
});
|
|
257
|
+
console.log(`ā
Regenerated: ${DESIGN_TOKENS_CSS}`);
|
|
258
|
+
} catch (e) {
|
|
259
|
+
console.error('ā ļø Failed to regenerate CSS:', e.message);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
console.log('\n⨠Brand sync complete!');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
main();
|