@decantr/cli 1.5.0 → 1.5.2
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/dist/bin.js +2 -2
- package/dist/{chunk-SUNMRG3P.js → chunk-66RIAQLH.js} +1378 -254
- package/dist/{chunk-6K6ZPDT4.js → chunk-6RJSFLT4.js} +262 -87
- package/dist/heal-54MKDDSQ.js +155 -0
- package/dist/index.js +2 -2
- package/dist/{upgrade-I2RUTNAT.js → upgrade-25IURU4X.js} +1 -1
- package/package.json +6 -6
- package/LICENSE +0 -21
- package/dist/heal-ZG5VJZ5J.js +0 -60
|
@@ -298,11 +298,11 @@ function generateTokensCSS(themeData, mode) {
|
|
|
298
298
|
"--d-radius-lg": "0.75rem",
|
|
299
299
|
"--d-radius-xl": "1rem",
|
|
300
300
|
"--d-radius-full": "9999px",
|
|
301
|
-
// Shadows
|
|
302
|
-
"--d-shadow-sm": "0 1px 2px rgba(0,0,0,0.05)",
|
|
303
|
-
"--d-shadow": "0 1px 3px rgba(0,0,0,0.1)",
|
|
304
|
-
"--d-shadow-md": "0 4px 6px rgba(0,0,0,0.1)",
|
|
305
|
-
"--d-shadow-lg": "0 10px 15px rgba(0,0,0,0.1)",
|
|
301
|
+
// Shadows — dark mode needs higher opacity to be visible on dark backgrounds
|
|
302
|
+
"--d-shadow-sm": tokenMode === "light" ? "0 1px 2px rgba(0,0,0,0.05)" : "0 1px 2px rgba(0,0,0,0.2)",
|
|
303
|
+
"--d-shadow": tokenMode === "light" ? "0 1px 3px rgba(0,0,0,0.1)" : "0 1px 3px rgba(0,0,0,0.25)",
|
|
304
|
+
"--d-shadow-md": tokenMode === "light" ? "0 4px 6px rgba(0,0,0,0.1)" : "0 4px 6px rgba(0,0,0,0.3)",
|
|
305
|
+
"--d-shadow-lg": tokenMode === "light" ? "0 10px 15px rgba(0,0,0,0.1)" : "0 10px 15px rgba(0,0,0,0.4)",
|
|
306
306
|
// Status colors
|
|
307
307
|
"--d-success": themeData.tokens?.base?.success || "#22c55e",
|
|
308
308
|
"--d-error": themeData.tokens?.base?.danger || "#ef4444",
|
|
@@ -319,7 +319,19 @@ ${lines}
|
|
|
319
319
|
`;
|
|
320
320
|
if (mode === "auto") {
|
|
321
321
|
const lightTokens = buildTokens("light");
|
|
322
|
-
const paletteKeys = [
|
|
322
|
+
const paletteKeys = [
|
|
323
|
+
"--d-bg",
|
|
324
|
+
"--d-surface",
|
|
325
|
+
"--d-surface-raised",
|
|
326
|
+
"--d-border",
|
|
327
|
+
"--d-text",
|
|
328
|
+
"--d-text-muted",
|
|
329
|
+
"--d-primary-hover",
|
|
330
|
+
"--d-shadow-sm",
|
|
331
|
+
"--d-shadow",
|
|
332
|
+
"--d-shadow-md",
|
|
333
|
+
"--d-shadow-lg"
|
|
334
|
+
];
|
|
323
335
|
const lightLines = Object.entries(lightTokens).filter(([key]) => paletteKeys.includes(key)).map(([key, value]) => ` ${key}: ${value};`).join("\n");
|
|
324
336
|
css += `
|
|
325
337
|
@media (prefers-color-scheme: light) {
|
|
@@ -357,6 +369,65 @@ function generateDecoratorsCSS(recipeData, themeName) {
|
|
|
357
369
|
`);
|
|
358
370
|
return css.join("\n");
|
|
359
371
|
}
|
|
372
|
+
function generateGlobalCSS(personality) {
|
|
373
|
+
const personalityText = personality.join(" ").toLowerCase();
|
|
374
|
+
let fontBody = "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
|
|
375
|
+
if (personalityText.includes("inter")) {
|
|
376
|
+
fontBody = `'Inter', ${fontBody}`;
|
|
377
|
+
} else if (personalityText.includes("geist")) {
|
|
378
|
+
fontBody = `'Geist', ${fontBody}`;
|
|
379
|
+
}
|
|
380
|
+
return `/* Generated by @decantr/cli \u2014 global reset + body styles */
|
|
381
|
+
|
|
382
|
+
*, *::before, *::after {
|
|
383
|
+
box-sizing: border-box;
|
|
384
|
+
margin: 0;
|
|
385
|
+
padding: 0;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
html {
|
|
389
|
+
color-scheme: dark;
|
|
390
|
+
-webkit-font-smoothing: antialiased;
|
|
391
|
+
-moz-osx-font-smoothing: grayscale;
|
|
392
|
+
text-rendering: optimizeLegibility;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
body {
|
|
396
|
+
font-family: ${fontBody};
|
|
397
|
+
background: var(--d-bg);
|
|
398
|
+
color: var(--d-text);
|
|
399
|
+
line-height: 1.6;
|
|
400
|
+
min-height: 100dvh;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
img, picture, video, canvas, svg {
|
|
404
|
+
display: block;
|
|
405
|
+
max-width: 100%;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
input, button, textarea, select {
|
|
409
|
+
font: inherit;
|
|
410
|
+
color: inherit;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
:focus-visible {
|
|
414
|
+
outline: 2px solid var(--d-primary);
|
|
415
|
+
outline-offset: 2px;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.sr-only {
|
|
419
|
+
position: absolute;
|
|
420
|
+
width: 1px;
|
|
421
|
+
height: 1px;
|
|
422
|
+
padding: 0;
|
|
423
|
+
margin: -1px;
|
|
424
|
+
overflow: hidden;
|
|
425
|
+
clip: rect(0, 0, 0, 0);
|
|
426
|
+
white-space: nowrap;
|
|
427
|
+
border-width: 0;
|
|
428
|
+
}
|
|
429
|
+
`;
|
|
430
|
+
}
|
|
360
431
|
function generateDecoratorsContext(recipeData, recipeName) {
|
|
361
432
|
const lines = [];
|
|
362
433
|
lines.push(`# Recipe Decorators: ${recipeName}`);
|
|
@@ -390,6 +461,12 @@ function generateDecoratorsContext(recipeData, recipeName) {
|
|
|
390
461
|
function generateDecoratorRule(name, description) {
|
|
391
462
|
const rules = [];
|
|
392
463
|
const descLower = description.toLowerCase();
|
|
464
|
+
const nameLower = name.toLowerCase();
|
|
465
|
+
const isCard = descLower.includes("card") || descLower.includes("panel") || nameLower.includes("card") || nameLower.includes("panel");
|
|
466
|
+
const isInput = descLower.includes("input") || descLower.includes("field") || descLower.includes("textarea") || nameLower.includes("input") || nameLower.includes("textarea");
|
|
467
|
+
const isGlass = descLower.includes("glassmorphic") || descLower.includes("glass") || nameLower.includes("glass");
|
|
468
|
+
const isInteractive = isCard || isInput || isGlass;
|
|
469
|
+
const isNonInteractive = descLower.includes("divider") || descLower.includes("skeleton") || descLower.includes("keyframe") || descLower.includes("canvas") || nameLower.includes("divider") || nameLower.includes("skeleton") || nameLower.includes("canvas");
|
|
393
470
|
if (descLower.includes("monospace") || descLower.includes("mono font")) {
|
|
394
471
|
rules.push("font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace");
|
|
395
472
|
}
|
|
@@ -402,6 +479,16 @@ function generateDecoratorRule(name, description) {
|
|
|
402
479
|
} else if (descLower.includes("primary-tinted") || descLower.includes("primary background")) {
|
|
403
480
|
rules.push("background: color-mix(in srgb, var(--d-primary) 15%, var(--d-surface))");
|
|
404
481
|
}
|
|
482
|
+
if (isInput) {
|
|
483
|
+
if (!rules.some((r) => r.startsWith("background"))) {
|
|
484
|
+
rules.push("background: var(--d-surface)");
|
|
485
|
+
}
|
|
486
|
+
rules.push("color: var(--d-text)");
|
|
487
|
+
rules.push("padding: 0.5rem 0.75rem");
|
|
488
|
+
rules.push("border-radius: var(--d-radius)");
|
|
489
|
+
rules.push("width: 100%");
|
|
490
|
+
rules.push("outline: none");
|
|
491
|
+
}
|
|
405
492
|
const leftBorderMatch = descLower.match(/(\d+)px\s+left\s+border/);
|
|
406
493
|
if (leftBorderMatch) {
|
|
407
494
|
rules.push(`border-left: ${leftBorderMatch[1]}px solid var(--d-primary)`);
|
|
@@ -415,23 +502,40 @@ function generateDecoratorRule(name, description) {
|
|
|
415
502
|
const radiusMatch = descLower.match(/(\d+)px radius/);
|
|
416
503
|
if (radiusMatch) {
|
|
417
504
|
rules.push(`border-radius: ${radiusMatch[1]}px`);
|
|
418
|
-
} else if (descLower.includes("radius") || descLower.includes("rounded")) {
|
|
505
|
+
} else if ((descLower.includes("radius") || descLower.includes("rounded")) && !isInput) {
|
|
419
506
|
rules.push("border-radius: var(--d-radius)");
|
|
420
507
|
}
|
|
421
|
-
if (descLower.includes("hover shadow") || descLower.includes("shadow transition")) {
|
|
422
|
-
rules.push("transition: box-shadow 0.15s ease");
|
|
423
|
-
}
|
|
424
508
|
if (descLower.includes("elevation") || descLower.includes("shadow")) {
|
|
425
509
|
rules.push("box-shadow: var(--d-shadow)");
|
|
426
510
|
}
|
|
511
|
+
if (isInteractive && !isNonInteractive) {
|
|
512
|
+
rules.push("transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease");
|
|
513
|
+
}
|
|
427
514
|
if (descLower.includes("entrance animation") || descLower.includes("fade")) {
|
|
428
515
|
rules.push("animation: decantr-fade-in 0.2s ease-out");
|
|
429
516
|
}
|
|
430
517
|
if (descLower.includes("pulse animation") || descLower.includes("skeleton")) {
|
|
431
518
|
rules.push("animation: decantr-pulse 1.5s ease-in-out infinite");
|
|
432
519
|
}
|
|
433
|
-
|
|
520
|
+
const blurMatch = descLower.match(/blur\((\d+)px\)/);
|
|
521
|
+
if (blurMatch) {
|
|
522
|
+
rules.push(`backdrop-filter: blur(${blurMatch[1]}px)`);
|
|
523
|
+
rules.push(`-webkit-backdrop-filter: blur(${blurMatch[1]}px)`);
|
|
524
|
+
} else if (isGlass) {
|
|
525
|
+
rules.push("backdrop-filter: blur(12px)");
|
|
526
|
+
rules.push("-webkit-backdrop-filter: blur(12px)");
|
|
527
|
+
} else if (descLower.includes("blur")) {
|
|
434
528
|
rules.push("backdrop-filter: blur(8px)");
|
|
529
|
+
rules.push("-webkit-backdrop-filter: blur(8px)");
|
|
530
|
+
}
|
|
531
|
+
if (descLower.includes("semi-transparent") || descLower.includes("glassmorphic")) {
|
|
532
|
+
const bgIdx = rules.findIndex((r) => r.startsWith("background:"));
|
|
533
|
+
const rgbaBg = "background: rgba(31, 31, 35, 0.8)";
|
|
534
|
+
if (bgIdx !== -1) {
|
|
535
|
+
rules[bgIdx] = rgbaBg;
|
|
536
|
+
} else {
|
|
537
|
+
rules.push(rgbaBg);
|
|
538
|
+
}
|
|
435
539
|
}
|
|
436
540
|
if (descLower.includes("right-aligned")) {
|
|
437
541
|
rules.push("margin-left: auto");
|
|
@@ -455,9 +559,33 @@ function generateDecoratorRule(name, description) {
|
|
|
455
559
|
if (rules.length === 0) {
|
|
456
560
|
return `/* .${name}: ${description} */`;
|
|
457
561
|
}
|
|
458
|
-
|
|
562
|
+
let css = `.${name} {
|
|
459
563
|
${rules.join(";\n ")};
|
|
460
564
|
}`;
|
|
565
|
+
if (isInteractive && !isNonInteractive) {
|
|
566
|
+
const stateRules = [];
|
|
567
|
+
if (isCard || isGlass) {
|
|
568
|
+
stateRules.push(`.${name}:hover {
|
|
569
|
+
border-color: var(--d-primary-hover, var(--d-border));
|
|
570
|
+
box-shadow: var(--d-shadow-md);
|
|
571
|
+
}`);
|
|
572
|
+
}
|
|
573
|
+
if (isInput) {
|
|
574
|
+
stateRules.push(`.${name}:focus {
|
|
575
|
+
border-color: var(--d-primary);
|
|
576
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--d-primary) 25%, transparent);
|
|
577
|
+
}`);
|
|
578
|
+
stateRules.push(`.${name}::placeholder {
|
|
579
|
+
color: var(--d-text-muted);
|
|
580
|
+
}`);
|
|
581
|
+
stateRules.push(`.${name}:disabled {
|
|
582
|
+
opacity: 0.5;
|
|
583
|
+
cursor: not-allowed;
|
|
584
|
+
}`);
|
|
585
|
+
}
|
|
586
|
+
css += "\n\n" + stateRules.join("\n\n");
|
|
587
|
+
}
|
|
588
|
+
return css;
|
|
461
589
|
}
|
|
462
590
|
function serializeLayoutItem(item) {
|
|
463
591
|
if (typeof item === "string") {
|
|
@@ -1006,33 +1134,29 @@ function generateTaskContext(templateName, essence) {
|
|
|
1006
1134
|
};
|
|
1007
1135
|
return renderTemplate(template, vars);
|
|
1008
1136
|
}
|
|
1009
|
-
function
|
|
1010
|
-
const template = loadTemplate(
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1016
|
-
|
|
1137
|
+
function generateTaskContextV3(templateName, essence) {
|
|
1138
|
+
const template = loadTemplate(templateName);
|
|
1139
|
+
const pages = essence.blueprint.sections && essence.blueprint.sections.length > 0 ? essence.blueprint.sections.flatMap((s) => s.pages) : essence.blueprint.pages || [];
|
|
1140
|
+
const defaultShell = essence.blueprint.sections?.[0]?.shell || essence.blueprint.shell || "sidebar-main";
|
|
1141
|
+
const layout = pages[0]?.layout?.map(serializeLayoutItem).join(", ") || "none";
|
|
1142
|
+
const scaffoldStructure = pages.map((p) => {
|
|
1143
|
+
const patterns = p.layout.length > 0 ? `
|
|
1144
|
+
- Patterns: ${p.layout.map(serializeLayoutItem).join(", ")}` : "";
|
|
1145
|
+
return `- **${p.id}** (${defaultShell})${patterns}`;
|
|
1146
|
+
}).join("\n");
|
|
1147
|
+
const densityLevel = essence.dna.spacing?.density || "comfortable";
|
|
1148
|
+
const contentGap = essence.dna.spacing?.content_gap || "_gap4";
|
|
1017
1149
|
const vars = {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
GUARD_MODE: essence.guard.mode,
|
|
1029
|
-
ENFORCE_STYLE: String(essence.guard.enforce_style),
|
|
1030
|
-
ENFORCE_RECIPE: String(essence.guard.enforce_recipe),
|
|
1031
|
-
DNA_ENFORCEMENT: dnaEnforcement,
|
|
1032
|
-
BLUEPRINT_ENFORCEMENT: blueprintEnforcement,
|
|
1033
|
-
DENSITY: essence.density.level,
|
|
1034
|
-
CONTENT_GAP: essence.density.content_gap,
|
|
1035
|
-
LAST_UPDATED: (/* @__PURE__ */ new Date()).toISOString()
|
|
1150
|
+
TARGET: essence.meta.target || "react",
|
|
1151
|
+
THEME_STYLE: essence.dna.theme.style,
|
|
1152
|
+
THEME_MODE: essence.dna.theme.mode,
|
|
1153
|
+
THEME_RECIPE: essence.dna.theme.recipe || essence.dna.theme.style,
|
|
1154
|
+
DEFAULT_SHELL: defaultShell,
|
|
1155
|
+
GUARD_MODE: essence.meta.guard.mode,
|
|
1156
|
+
LAYOUT: layout,
|
|
1157
|
+
DENSITY: densityLevel,
|
|
1158
|
+
CONTENT_GAP: contentGap,
|
|
1159
|
+
SCAFFOLD_STRUCTURE: scaffoldStructure
|
|
1036
1160
|
};
|
|
1037
1161
|
return renderTemplate(template, vars);
|
|
1038
1162
|
}
|
|
@@ -1116,15 +1240,6 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
|
|
|
1116
1240
|
const scaffoldPath = join(contextDir, "task-scaffold.md");
|
|
1117
1241
|
writeFileSync(scaffoldPath, generateTaskContext("task-scaffold.md.template", essence));
|
|
1118
1242
|
contextFiles.push(scaffoldPath);
|
|
1119
|
-
const addPagePath = join(contextDir, "task-add-page.md");
|
|
1120
|
-
writeFileSync(addPagePath, generateTaskContext("task-add-page.md.template", essence));
|
|
1121
|
-
contextFiles.push(addPagePath);
|
|
1122
|
-
const modifyPath = join(contextDir, "task-modify.md");
|
|
1123
|
-
writeFileSync(modifyPath, generateTaskContext("task-modify.md.template", essence));
|
|
1124
|
-
contextFiles.push(modifyPath);
|
|
1125
|
-
const summaryPath = join(contextDir, "essence-summary.md");
|
|
1126
|
-
writeFileSync(summaryPath, generateEssenceSummary(essence));
|
|
1127
|
-
contextFiles.push(summaryPath);
|
|
1128
1243
|
if (composedSections) {
|
|
1129
1244
|
essenceV3.version = "3.1.0";
|
|
1130
1245
|
essenceV3.blueprint = {
|
|
@@ -1133,7 +1248,7 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
|
|
|
1133
1248
|
routes: routeMap || {}
|
|
1134
1249
|
};
|
|
1135
1250
|
if (blueprintData?.personality?.length) {
|
|
1136
|
-
essenceV3.dna.personality = blueprintData.personality;
|
|
1251
|
+
essenceV3.dna.personality = typeof blueprintData.personality === "string" ? [blueprintData.personality] : blueprintData.personality;
|
|
1137
1252
|
}
|
|
1138
1253
|
if (blueprintData?.design_constraints) {
|
|
1139
1254
|
essenceV3.dna.constraints = blueprintData.design_constraints;
|
|
@@ -1146,7 +1261,7 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
|
|
|
1146
1261
|
}
|
|
1147
1262
|
writeFileSync(essencePath, JSON.stringify(essenceV3, null, 2) + "\n");
|
|
1148
1263
|
}
|
|
1149
|
-
const refreshResult = await refreshDerivedFiles(projectRoot, essenceV3, registry, themeData, recipeData);
|
|
1264
|
+
const refreshResult = await refreshDerivedFiles(projectRoot, essenceV3, registry, themeData, recipeData, { isInitialScaffold: true });
|
|
1150
1265
|
contextFiles.push(...refreshResult.contextFiles);
|
|
1151
1266
|
const gitignoreUpdated = updateGitignore(projectRoot);
|
|
1152
1267
|
return {
|
|
@@ -1348,7 +1463,7 @@ When available, use these tools:
|
|
|
1348
1463
|
gitignoreUpdated
|
|
1349
1464
|
};
|
|
1350
1465
|
}
|
|
1351
|
-
async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThemeData, prefetchedRecipeData) {
|
|
1466
|
+
async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThemeData, prefetchedRecipeData, options) {
|
|
1352
1467
|
const decantrDir = join(projectRoot, ".decantr");
|
|
1353
1468
|
const contextDir = join(decantrDir, "context");
|
|
1354
1469
|
mkdirSync(contextDir, { recursive: true });
|
|
@@ -1452,14 +1567,30 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1452
1567
|
if (hasRealRecipeData || !existsSync(decoratorsPath)) {
|
|
1453
1568
|
writeFileSync(decoratorsPath, generateDecoratorsCSS(recipeData, themeName));
|
|
1454
1569
|
}
|
|
1455
|
-
const
|
|
1570
|
+
const globalPath = join(stylesDir, "global.css");
|
|
1571
|
+
if (!existsSync(globalPath)) {
|
|
1572
|
+
writeFileSync(globalPath, generateGlobalCSS(personality));
|
|
1573
|
+
}
|
|
1574
|
+
const cssFiles = [tokensPath, decoratorsPath, globalPath];
|
|
1456
1575
|
const decoratorsMdPath = join(contextDir, "decorators.md");
|
|
1457
1576
|
writeFileSync(decoratorsMdPath, generateDecoratorsContext(recipeData, recipeName));
|
|
1458
1577
|
const decantrMdPath = join(projectRoot, "DECANTR.md");
|
|
1459
1578
|
writeFileSync(decantrMdPath, generateDecantrMdV31(guardMode, CSS_APPROACH_CONTENT));
|
|
1460
|
-
const
|
|
1461
|
-
|
|
1462
|
-
|
|
1579
|
+
const hasSections = essence.blueprint.sections && essence.blueprint.sections.length > 0;
|
|
1580
|
+
const contextFiles = [decoratorsMdPath];
|
|
1581
|
+
if (!hasSections) {
|
|
1582
|
+
const summaryPath = join(contextDir, "essence-summary.md");
|
|
1583
|
+
writeFileSync(summaryPath, generateEssenceSummaryV3(essence));
|
|
1584
|
+
contextFiles.push(summaryPath);
|
|
1585
|
+
}
|
|
1586
|
+
if (!options?.isInitialScaffold) {
|
|
1587
|
+
const addPagePath = join(contextDir, "task-add-page.md");
|
|
1588
|
+
writeFileSync(addPagePath, generateTaskContextV3("task-add-page.md.template", essence));
|
|
1589
|
+
contextFiles.push(addPagePath);
|
|
1590
|
+
const modifyPath = join(contextDir, "task-modify.md");
|
|
1591
|
+
writeFileSync(modifyPath, generateTaskContextV3("task-modify.md.template", essence));
|
|
1592
|
+
contextFiles.push(modifyPath);
|
|
1593
|
+
}
|
|
1463
1594
|
const blueprint = essence.blueprint;
|
|
1464
1595
|
const sections = blueprint.sections && blueprint.sections.length > 0 ? blueprint.sections : [];
|
|
1465
1596
|
if (sections.length > 0) {
|
|
@@ -1492,21 +1623,28 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1492
1623
|
slots = synthetic;
|
|
1493
1624
|
}
|
|
1494
1625
|
}
|
|
1495
|
-
|
|
1626
|
+
const spec = {
|
|
1496
1627
|
description: inner.description || "",
|
|
1497
1628
|
components: inner.components || [],
|
|
1498
1629
|
slots
|
|
1499
1630
|
};
|
|
1631
|
+
if (!spec.components || spec.components.length === 0) {
|
|
1632
|
+
const syntheticComps = generateSyntheticComponents(name, spec.description);
|
|
1633
|
+
if (syntheticComps.length > 0) spec.components = syntheticComps;
|
|
1634
|
+
}
|
|
1635
|
+
patternSpecs[name] = spec;
|
|
1500
1636
|
} else {
|
|
1501
1637
|
const synthetic = generateSyntheticSlots(name, "");
|
|
1502
|
-
|
|
1503
|
-
|
|
1638
|
+
const syntheticComps = generateSyntheticComponents(name, "");
|
|
1639
|
+
if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
|
|
1640
|
+
patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
|
|
1504
1641
|
}
|
|
1505
1642
|
}
|
|
1506
1643
|
} catch {
|
|
1507
1644
|
const synthetic = generateSyntheticSlots(name, "");
|
|
1508
|
-
|
|
1509
|
-
|
|
1645
|
+
const syntheticComps = generateSyntheticComponents(name, "");
|
|
1646
|
+
if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
|
|
1647
|
+
patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
|
|
1510
1648
|
}
|
|
1511
1649
|
}
|
|
1512
1650
|
}
|
|
@@ -1666,21 +1804,28 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
|
|
|
1666
1804
|
slots = synthetic;
|
|
1667
1805
|
}
|
|
1668
1806
|
}
|
|
1669
|
-
|
|
1807
|
+
const spec = {
|
|
1670
1808
|
description: inner.description || "",
|
|
1671
1809
|
components: inner.components || [],
|
|
1672
1810
|
slots
|
|
1673
1811
|
};
|
|
1812
|
+
if (!spec.components || spec.components.length === 0) {
|
|
1813
|
+
const syntheticComps = generateSyntheticComponents(name, spec.description);
|
|
1814
|
+
if (syntheticComps.length > 0) spec.components = syntheticComps;
|
|
1815
|
+
}
|
|
1816
|
+
patternSpecs[name] = spec;
|
|
1674
1817
|
} else {
|
|
1675
1818
|
const synthetic = generateSyntheticSlots(name, "");
|
|
1676
|
-
|
|
1677
|
-
|
|
1819
|
+
const syntheticComps = generateSyntheticComponents(name, "");
|
|
1820
|
+
if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
|
|
1821
|
+
patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
|
|
1678
1822
|
}
|
|
1679
1823
|
}
|
|
1680
1824
|
} catch {
|
|
1681
1825
|
const synthetic = generateSyntheticSlots(name, "");
|
|
1682
|
-
|
|
1683
|
-
|
|
1826
|
+
const syntheticComps = generateSyntheticComponents(name, "");
|
|
1827
|
+
if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
|
|
1828
|
+
patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
|
|
1684
1829
|
}
|
|
1685
1830
|
}
|
|
1686
1831
|
}
|
|
@@ -1810,6 +1955,27 @@ function generateSyntheticSlots(patternId, description) {
|
|
|
1810
1955
|
}
|
|
1811
1956
|
return syntheticSlots;
|
|
1812
1957
|
}
|
|
1958
|
+
function generateSyntheticComponents(patternId, description) {
|
|
1959
|
+
const desc = description.toLowerCase();
|
|
1960
|
+
const syntheticComponents = [];
|
|
1961
|
+
if (patternId.includes("hero")) syntheticComponents.push("Button", "Icon", "Image");
|
|
1962
|
+
if (patternId.includes("feature")) syntheticComponents.push("Card", "Icon", "Text");
|
|
1963
|
+
if (patternId.includes("pricing")) syntheticComponents.push("Card", "Button", "Badge");
|
|
1964
|
+
if (patternId.includes("testimonial")) syntheticComponents.push("Card", "Avatar", "Text");
|
|
1965
|
+
if (patternId.includes("cta")) syntheticComponents.push("Button", "Text");
|
|
1966
|
+
if (patternId.includes("form") || patternId.includes("contact")) syntheticComponents.push("Input", "Textarea", "Button", "Label");
|
|
1967
|
+
if (patternId.includes("team")) syntheticComponents.push("Card", "Avatar", "Text");
|
|
1968
|
+
if (patternId.includes("settings") || patternId.includes("security")) syntheticComponents.push("Card", "Toggle", "Input", "Button");
|
|
1969
|
+
if (patternId.includes("message") || patternId.includes("chat")) syntheticComponents.push("Avatar", "Text", "CodeBlock");
|
|
1970
|
+
if (patternId.includes("input") && desc.includes("chat")) syntheticComponents.push("Textarea", "Button", "Icon");
|
|
1971
|
+
if (patternId.includes("header") && desc.includes("chat")) syntheticComponents.push("Button", "Icon", "Text");
|
|
1972
|
+
if (patternId.includes("content") || patternId.includes("legal")) syntheticComponents.push("Heading", "Text", "List");
|
|
1973
|
+
if (patternId.includes("how-it-works") || patternId.includes("steps")) syntheticComponents.push("Card", "Icon", "Text", "Badge");
|
|
1974
|
+
if (patternId.includes("values")) syntheticComponents.push("Card", "Icon", "Text");
|
|
1975
|
+
if (patternId.includes("story") || patternId.includes("about")) syntheticComponents.push("Text", "Image");
|
|
1976
|
+
if (patternId.includes("empty") || patternId.includes("new")) syntheticComponents.push("Icon", "Text", "Button");
|
|
1977
|
+
return [...new Set(syntheticComponents)];
|
|
1978
|
+
}
|
|
1813
1979
|
function generateSectionContext(input) {
|
|
1814
1980
|
const { section, decorators, guardConfig, personality, themeName, recipeName, zoneContext, patternSpecs, recipeHints, constraints, shellInfo } = input;
|
|
1815
1981
|
const lines = [];
|
|
@@ -1837,8 +2003,9 @@ function generateSectionContext(input) {
|
|
|
1837
2003
|
lines.push(`**Theme tokens:** see \`src/styles/tokens.css\` \u2014 use \`var(--d-primary)\`, \`var(--d-bg)\`, etc.`);
|
|
1838
2004
|
lines.push("");
|
|
1839
2005
|
if (decorators.length > 0) {
|
|
1840
|
-
const names = decorators.map((d) => d.name).join(", ");
|
|
1841
|
-
lines.push(`**Decorators:** see \`src/styles/decorators.css\`
|
|
2006
|
+
const names = decorators.map((d) => `\`${d.name}\``).join(", ");
|
|
2007
|
+
lines.push(`**Decorators:** ${names} (see \`src/styles/decorators.css\`)`);
|
|
2008
|
+
lines.push("Usage: `className={css('_flex _col') + ' carbon-card'}` \u2014 atoms via css(), decorators as plain class strings.");
|
|
1842
2009
|
} else {
|
|
1843
2010
|
lines.push("**Decorators:** none defined.");
|
|
1844
2011
|
}
|
|
@@ -1871,11 +2038,7 @@ function generateSectionContext(input) {
|
|
|
1871
2038
|
lines.push("");
|
|
1872
2039
|
}
|
|
1873
2040
|
if (personality.length > 0) {
|
|
1874
|
-
lines.push("
|
|
1875
|
-
lines.push("");
|
|
1876
|
-
lines.push(personality.join(", "));
|
|
1877
|
-
lines.push("");
|
|
1878
|
-
lines.push("---");
|
|
2041
|
+
lines.push("**Personality:** See scaffold.md for personality and visual direction.");
|
|
1879
2042
|
lines.push("");
|
|
1880
2043
|
}
|
|
1881
2044
|
if (constraints && Object.keys(constraints).length > 0) {
|
|
@@ -1888,6 +2051,34 @@ function generateSectionContext(input) {
|
|
|
1888
2051
|
lines.push("---");
|
|
1889
2052
|
lines.push("");
|
|
1890
2053
|
}
|
|
2054
|
+
const uniquePatterns = /* @__PURE__ */ new Map();
|
|
2055
|
+
for (const page of section.pages) {
|
|
2056
|
+
const patternNames = page.layout.flatMap(extractPatternNames);
|
|
2057
|
+
for (const name of patternNames) {
|
|
2058
|
+
if (patternSpecs[name] && !uniquePatterns.has(name)) {
|
|
2059
|
+
uniquePatterns.set(name, patternSpecs[name]);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
if (uniquePatterns.size > 0) {
|
|
2064
|
+
lines.push("## Pattern Reference");
|
|
2065
|
+
lines.push("");
|
|
2066
|
+
for (const [patternName, spec] of uniquePatterns) {
|
|
2067
|
+
lines.push(`### ${patternName}`);
|
|
2068
|
+
lines.push("");
|
|
2069
|
+
lines.push(spec.description);
|
|
2070
|
+
lines.push("");
|
|
2071
|
+
lines.push(`**Components:** ${spec.components.join(", ")}`);
|
|
2072
|
+
lines.push("");
|
|
2073
|
+
lines.push("**Layout slots:**");
|
|
2074
|
+
for (const [slot, desc] of Object.entries(spec.slots)) {
|
|
2075
|
+
lines.push(`- \`${slot}\`: ${desc}`);
|
|
2076
|
+
}
|
|
2077
|
+
lines.push("");
|
|
2078
|
+
}
|
|
2079
|
+
lines.push("---");
|
|
2080
|
+
lines.push("");
|
|
2081
|
+
}
|
|
1891
2082
|
lines.push("## Pages");
|
|
1892
2083
|
lines.push("");
|
|
1893
2084
|
for (const page of section.pages) {
|
|
@@ -1908,22 +2099,6 @@ function generateSectionContext(input) {
|
|
|
1908
2099
|
}
|
|
1909
2100
|
lines.push("");
|
|
1910
2101
|
}
|
|
1911
|
-
const patternNames = page.layout.flatMap(extractPatternNames);
|
|
1912
|
-
for (const patternName of patternNames) {
|
|
1913
|
-
const spec = patternSpecs[patternName];
|
|
1914
|
-
if (!spec) continue;
|
|
1915
|
-
lines.push(`#### Pattern: ${patternName}`);
|
|
1916
|
-
lines.push("");
|
|
1917
|
-
lines.push(spec.description);
|
|
1918
|
-
lines.push("");
|
|
1919
|
-
lines.push(`**Components:** ${spec.components.join(", ")}`);
|
|
1920
|
-
lines.push("");
|
|
1921
|
-
lines.push("**Layout slots:**");
|
|
1922
|
-
for (const [slot, desc] of Object.entries(spec.slots)) {
|
|
1923
|
-
lines.push(`- \`${slot}\`: ${desc}`);
|
|
1924
|
-
}
|
|
1925
|
-
lines.push("");
|
|
1926
|
-
}
|
|
1927
2102
|
}
|
|
1928
2103
|
return lines.join("\n");
|
|
1929
2104
|
}
|