mirror of
https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git
synced 2026-08-01 19:06:14 +00:00
* fix(cli): install all 7 skills via uipro init, not just the orchestrator `uipro init` rendered only the orchestrator (ui-ux-pro-max) and never delivered the 6 sibling skills (banner-design, brand, design, design-system, slides, ui-styling), so users got 1 of 7 skills (#362). - sync-assets.mjs: bundle the 6 sub-skills into cli/assets/skills/ as static copies (source of truth: .claude/skills/), with sync + check coverage. Excludes ui-styling/canvas-fonts (~5.8MB of TTF) and __pycache__/.pyc cruft — a skill registers from its SKILL.md, not its fonts — so the bundle adds ~0.9MB, not ~6.6MB. - template.ts: after rendering the orchestrator, install each bundled sub-skill as a sibling. The skills parent is derived from the platform's skillPath (skills/ for most, prompts/ for copilot, steering/ for kiro) rather than hardcoded. - uninstall.ts: remove the sub-skills too. Verified: check:assets in sync, tsc passes, and a per-platform install harness delivers all 7 skills to the correct parent dir with no fonts. Closes #362 * fix(cli): filter excluded files from target side of check:assets check:assets filtered sourceFiles with isExcludedAssetFile but not targetFiles, so a stray cli/assets/scripts/__pycache__/*.pyc (generated by a local Python run) was reported as an "extra asset file" and failed the gate. Apply the same predicate to targetFiles in both the dirsToSync and sub-skill loops. Verified: check:assets now passes with __pycache__/*.pyc present in the target tree; typecheck passes. * fix(cli): uninstall from each platform's real skills dir, not hardcoded skills/ removeSkillDir() hardcoded <folder>/skills/<name>, but the installer places skills under each platform config's skillPath parent — copilot in .github/prompts/, kiro in .kiro/steering/. So uninstall left those platforms' skills (orchestrator + sub-skills) behind. Derive the install parent from loadPlatformConfig(aiType).folderStructure (same source the installer uses), and keep the legacy <folder>/skills/ cleanup (incl. .shared/) for older installs. Deduped via a Set. Verified: typecheck passes; an install+uninstall harness removes all 7 skills with zero leftovers for claude (.claude/skills), copilot (.github/prompts) and kiro (.kiro/steering). * fix(cli): re-sync bundled sub-skills after #385 stripped ckm- names #385 merged to main and removed the ckm- prefix from the six .claude/skills/*/SKILL.md name fields. This branch's bundled copies under cli/assets/skills/ still carried the old ckm- names, so after the PR merges with main the source no longer matched the bundle and the check-asset-sync CI gate failed (stale asset file: skills/*/SKILL.md). Merge main and regenerate the bundle so cli/assets/skills matches the current .claude/skills source of truth. check:assets and typecheck pass.
100 lines
2.5 KiB
JavaScript
100 lines
2.5 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* embed-tokens.cjs
|
|
* Reads design-tokens.css and outputs embeddable inline CSS.
|
|
* Use when generating standalone HTML files (infographics, slides, etc.)
|
|
*
|
|
* Usage:
|
|
* node embed-tokens.cjs # Output full CSS
|
|
* node embed-tokens.cjs --minimal # Output only commonly used tokens
|
|
* node embed-tokens.cjs --style # Wrap in <style> tags
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Find project root (look for assets/design-tokens.css)
|
|
function findProjectRoot(startDir) {
|
|
let dir = startDir;
|
|
while (dir !== '/') {
|
|
if (fs.existsSync(path.join(dir, 'assets', 'design-tokens.css'))) {
|
|
return dir;
|
|
}
|
|
dir = path.dirname(dir);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
const projectRoot = findProjectRoot(process.cwd());
|
|
if (!projectRoot) {
|
|
console.error('Error: Could not find assets/design-tokens.css');
|
|
process.exit(1);
|
|
}
|
|
|
|
const tokensPath = path.join(projectRoot, 'assets', 'design-tokens.css');
|
|
|
|
// Minimal tokens commonly used in infographics/slides
|
|
const MINIMAL_TOKENS = [
|
|
'--primitive-spacing-',
|
|
'--primitive-fontSize-',
|
|
'--primitive-fontWeight-',
|
|
'--primitive-lineHeight-',
|
|
'--primitive-radius-',
|
|
'--primitive-shadow-glow-',
|
|
'--primitive-gradient-',
|
|
'--primitive-duration-',
|
|
'--color-primary',
|
|
'--color-secondary',
|
|
'--color-accent',
|
|
'--color-background',
|
|
'--color-surface',
|
|
'--color-foreground',
|
|
'--color-border',
|
|
'--typography-font-',
|
|
'--card-',
|
|
];
|
|
|
|
function extractTokens(css, minimal = false) {
|
|
// Extract :root block
|
|
const rootMatch = css.match(/:root\s*\{([^}]+)\}/g);
|
|
if (!rootMatch) return '';
|
|
|
|
let allVars = [];
|
|
for (const block of rootMatch) {
|
|
const vars = block.match(/--[\w-]+:\s*[^;]+;/g) || [];
|
|
allVars = allVars.concat(vars);
|
|
}
|
|
|
|
if (minimal) {
|
|
allVars = allVars.filter(v =>
|
|
MINIMAL_TOKENS.some(token => v.includes(token))
|
|
);
|
|
}
|
|
|
|
// Dedupe
|
|
allVars = [...new Set(allVars)];
|
|
|
|
return `:root {\n ${allVars.join('\n ')}\n}`;
|
|
}
|
|
|
|
// Parse args
|
|
const args = process.argv.slice(2);
|
|
const minimal = args.includes('--minimal');
|
|
const wrapStyle = args.includes('--style');
|
|
|
|
try {
|
|
const css = fs.readFileSync(tokensPath, 'utf-8');
|
|
let output = extractTokens(css, minimal);
|
|
|
|
if (wrapStyle) {
|
|
output = `<style>\n/* Design Tokens (embedded for standalone HTML) */\n${output}\n</style>`;
|
|
} else {
|
|
output = `/* Design Tokens (embedded for standalone HTML) */\n${output}`;
|
|
}
|
|
|
|
console.log(output);
|
|
} catch (err) {
|
|
console.error(`Error reading tokens: ${err.message}`);
|
|
process.exit(1);
|
|
}
|