@getcoherent/cli 0.6.50 → 0.6.52
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/{chunk-VLBVBF6V.js → chunk-IFJK5OPI.js} +2 -2
- package/dist/{chunk-E23FJX2I.js → chunk-NLL3SHN3.js} +17 -19
- package/dist/{chunk-NOM47EB4.js → chunk-U5SNPHVU.js} +90 -4
- package/dist/{chunk-4I7ATX6G.js → chunk-UZGT5APM.js} +2 -2
- package/dist/{code-generator-YSGVHVNN.js → code-generator-IZ6XM6WG.js} +4 -4
- package/dist/{design-constraints-HGNEY3W3.js → design-constraints-PFZDW2XW.js} +1 -1
- package/dist/index.js +23 -13
- package/dist/{plan-generator-PIDLFRWZ.js → plan-generator-D2UBTVCN.js} +3 -3
- package/dist/{quality-validator-2KIT6QKA.js → quality-validator-IM6YFKLI.js} +3 -1
- package/package.json +10 -10
- package/LICENSE +0 -21
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
CORE_CONSTRAINTS,
|
|
3
3
|
getDesignQualityForType,
|
|
4
4
|
inferPageTypeFromRoute
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NLL3SHN3.js";
|
|
6
6
|
import {
|
|
7
7
|
autoFixCode
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-U5SNPHVU.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/chat/plan-generator.ts
|
|
11
11
|
import { z } from "zod";
|
|
@@ -28,10 +28,8 @@ TYPOGRAPHY (most impactful rules):
|
|
|
28
28
|
- Create hierarchy through font WEIGHT (medium \u2192 semibold \u2192 bold), NOT font SIZE.
|
|
29
29
|
|
|
30
30
|
COLORS \u2014 ONLY SEMANTIC TOKENS (zero raw colors):
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
- Borders: border (no color suffix \u2014 uses CSS variable). border-b for headers.
|
|
34
|
-
- BANNED: bg-gray-*, bg-blue-*, bg-slate-*, text-gray-*, ANY raw Tailwind color. The validator REJECTS these.
|
|
31
|
+
- Allowed: bg-background, bg-muted, bg-muted/50, bg-card, bg-primary, bg-secondary, bg-destructive, bg-success, bg-warning. text-foreground, text-muted-foreground, text-primary-foreground, text-destructive, text-success. border (bare), border-border. Opacity modifiers OK (bg-primary/50). ring-*, shadow-*, fill-*, stroke-* with same token names.
|
|
32
|
+
- BANNED: ANY raw Tailwind color (bg-gray-*, text-blue-*, etc.), inline style colors, hex values, bg-white, bg-black. The validator REJECTS all of these.
|
|
35
33
|
|
|
36
34
|
SPACING (restricted palette \u2014 only multiples of 4px):
|
|
37
35
|
- Page content padding: p-4 lg:p-6. Gap between major sections: gap-6 md:gap-8.
|
|
@@ -115,7 +113,7 @@ var DESIGN_QUALITY_COMMON = `
|
|
|
115
113
|
|
|
116
114
|
### Visual Depth & Layers
|
|
117
115
|
- Cards: bg-card border border-border/15 rounded-xl (not rounded-md)
|
|
118
|
-
- Cards on dark pages: bg-
|
|
116
|
+
- Cards on dark pages: bg-card border-border/10 backdrop-blur-sm
|
|
119
117
|
- Cards MUST have hover state: hover:border-border/30 transition-colors
|
|
120
118
|
- Sections alternate between bg-background and bg-muted/5 for rhythm
|
|
121
119
|
- Section dividers: border-t border-border/10 (subtle, not heavy)
|
|
@@ -127,18 +125,18 @@ var DESIGN_QUALITY_COMMON = `
|
|
|
127
125
|
- CTA buttons: use the Button component, NEVER raw <button> or <a> styled as button
|
|
128
126
|
|
|
129
127
|
### Accent Color Discipline
|
|
130
|
-
- ONE accent color per page (primary
|
|
131
|
-
- Use for: CTAs,
|
|
132
|
-
- NEVER mix
|
|
128
|
+
- ONE accent color per page (primary)
|
|
129
|
+
- Use for: CTAs, check icons, feature icon backgrounds, active states
|
|
130
|
+
- NEVER mix multiple accent colors on same page
|
|
133
131
|
- Badge: outline style (border-border/30 bg-transparent) not filled color
|
|
134
|
-
- Status icons: text-
|
|
132
|
+
- Status icons: text-success for positive, text-destructive for negative
|
|
135
133
|
|
|
136
134
|
### Dark Theme Implementation
|
|
137
135
|
- html element: className="dark"
|
|
138
136
|
- Background: use CSS variables from globals.css dark section
|
|
139
137
|
- Text: text-foreground for primary, text-muted-foreground for secondary
|
|
140
138
|
- NEVER hardcode dark colors (bg-gray-900) \u2014 always use semantic tokens
|
|
141
|
-
- Cards and elevated elements: slightly lighter than background (bg-card
|
|
139
|
+
- Cards and elevated elements: slightly lighter than background (bg-card)
|
|
142
140
|
`;
|
|
143
141
|
var DESIGN_QUALITY_MARKETING = `
|
|
144
142
|
## DESIGN QUALITY \u2014 MARKETING PAGES
|
|
@@ -155,15 +153,15 @@ var DESIGN_QUALITY_MARKETING = `
|
|
|
155
153
|
|
|
156
154
|
### Icons in Feature Cards
|
|
157
155
|
- Wrap in colored container: bg-primary/10 rounded-lg p-2.5
|
|
158
|
-
- Icon color: text-primary
|
|
156
|
+
- Icon color: text-primary
|
|
159
157
|
- Icon size: h-5 w-5 inside the container
|
|
160
158
|
- NEVER bare icons floating in a card without container
|
|
161
159
|
|
|
162
160
|
### Terminal / Code Blocks
|
|
163
161
|
- Background: bg-zinc-950 (near-black, not gray)
|
|
164
162
|
- Border: border-border/10 rounded-xl
|
|
165
|
-
- Text: font-mono text-sm text-emerald-400
|
|
166
|
-
- Prompt: text-emerald-500 "$ " prefix (
|
|
163
|
+
- Text: font-mono text-sm text-emerald-400 (EXCEPTION: terminal blocks use raw green for aesthetics)
|
|
164
|
+
- Prompt: text-emerald-500 "$ " prefix (EXCEPTION: terminal prompt uses raw green)
|
|
167
165
|
- Title bar (optional): flex with 3 dots (bg-zinc-700 rounded-full w-2.5 h-2.5) + title text-zinc-500 text-[11px]
|
|
168
166
|
- Copy button: text-zinc-500 hover:text-zinc-300
|
|
169
167
|
|
|
@@ -177,8 +175,8 @@ var DESIGN_QUALITY_MARKETING = `
|
|
|
177
175
|
|
|
178
176
|
### Comparison Sections (before/after, with/without)
|
|
179
177
|
- Two cards side by side: grid md:grid-cols-2 gap-6
|
|
180
|
-
- Negative card: neutral border, items with X icon text-
|
|
181
|
-
- Positive card: accent border (border-
|
|
178
|
+
- Negative card: neutral border, items with X icon text-destructive
|
|
179
|
+
- Positive card: accent border (border-primary/20), items with Check icon text-success
|
|
182
180
|
- Header of each card: text-sm font-semibold uppercase tracking-wider
|
|
183
181
|
|
|
184
182
|
### Step/Process Sections
|
|
@@ -493,7 +491,7 @@ var RULES_DATA_DISPLAY = `
|
|
|
493
491
|
DATA DISPLAY RULES:
|
|
494
492
|
|
|
495
493
|
STAT / METRIC CARDS: See the Stats Grid reference pattern in DESIGN QUALITY \u2014 APP PAGES. Follow that exact pattern.
|
|
496
|
-
- Trend up: text-
|
|
494
|
+
- Trend up: text-success.
|
|
497
495
|
- Trend down: text-destructive.
|
|
498
496
|
- Trend icon: ArrowUp / ArrowDown className="size-3 inline mr-1".
|
|
499
497
|
- No actions on stat cards. Click entire card to drill down (if applicable).
|
|
@@ -530,12 +528,12 @@ MOCK DATA IN COMPONENTS:
|
|
|
530
528
|
- NEVER store display strings ("2 hours ago", "Yesterday") in data \u2014 always compute from ISO date.
|
|
531
529
|
|
|
532
530
|
STATUS INDICATORS (dot + text):
|
|
533
|
-
- Pattern: <div className="flex items-center gap-2"><div className="size-2 rounded-full bg-
|
|
534
|
-
- Colors: bg-
|
|
531
|
+
- Pattern: <div className="flex items-center gap-2"><div className="size-2 rounded-full bg-success" /><span className="text-sm">Active</span></div>
|
|
532
|
+
- Colors: bg-success (active/online), bg-destructive (error/offline), bg-warning (warning), bg-muted-foreground (inactive).
|
|
535
533
|
- Alternative: use Badge variants for status in tables/lists (preferred over dots).
|
|
536
534
|
|
|
537
535
|
TREND INDICATORS:
|
|
538
|
-
- Up (positive): <span className="text-sm text-
|
|
536
|
+
- Up (positive): <span className="text-sm text-success flex items-center"><ArrowUp className="size-3 mr-1" />12.5%</span>
|
|
539
537
|
- Down (negative): <span className="text-sm text-destructive flex items-center"><ArrowDown className="size-3 mr-1" />3.2%</span>
|
|
540
538
|
- Neutral: <span className="text-sm text-muted-foreground">0%</span>
|
|
541
539
|
- Always include arrow icon + sign (+ or -) + percentage.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// src/utils/quality-validator.ts
|
|
2
|
+
import { readdir, readFile } from "fs/promises";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
|
|
1
5
|
// src/utils/component-rules.ts
|
|
2
6
|
function extractJsxElementProps(code, openTagStart) {
|
|
3
7
|
let i = openTagStart;
|
|
@@ -155,7 +159,12 @@ function applyComponentRules(code) {
|
|
|
155
159
|
}
|
|
156
160
|
|
|
157
161
|
// src/utils/quality-validator.ts
|
|
158
|
-
var RAW_COLOR_RE = /(?:(?:
|
|
162
|
+
var RAW_COLOR_RE = /(?:(?:[a-z][a-z0-9-]*:)*)?(?:bg|text|border|ring|outline|shadow|from|to|via|divide|placeholder|decoration|caret|fill|stroke|accent)-(gray|blue|red|green|yellow|purple|pink|indigo|orange|slate|zinc|stone|neutral|emerald|teal|cyan|sky|violet|fuchsia|rose|amber|lime)-\d+/g;
|
|
163
|
+
var RAW_BW_COLOR_RE = /(?:(?:[a-z][a-z0-9-]*:)*)?(?:bg|text|border|ring|outline|shadow|divide|fill|stroke)-(white|black)\b/g;
|
|
164
|
+
var INLINE_STYLE_COLOR_RE = /style=\{[^}]*(color|background|backgroundColor|borderColor)\s*:\s*['"]?(#[0-9a-fA-F]{3,8}|rgb|hsl|red|blue|orange|green|purple|yellow|pink|white|black|gray|grey)\b/gi;
|
|
165
|
+
var ARBITRARY_COLOR_RE = /\b(?:bg|text|border|ring|shadow|fill|stroke|from|to|via)-\[(?:#[0-9a-fA-F]{3,8}|rgb|hsl|color-mix)/gi;
|
|
166
|
+
var SVG_COLOR_RE = /\b(?:fill|stroke)=["'](?!none|currentColor|url|inherit|transparent)([^"']+)["']/g;
|
|
167
|
+
var COLOR_PROP_RE = /\b(?:color|accentColor|iconColor|fillColor)=["']#[0-9a-fA-F]{3,8}["']/g;
|
|
159
168
|
var HEX_IN_CLASS_RE = /className="[^"]*#[0-9a-fA-F]{3,8}[^"]*"/g;
|
|
160
169
|
var TEXT_BASE_RE = /\btext-base\b/g;
|
|
161
170
|
var HEAVY_SHADOW_RE = /\bshadow-(md|lg|xl|2xl)\b/g;
|
|
@@ -251,6 +260,51 @@ function validatePageQuality(code, validRoutes, pageType) {
|
|
|
251
260
|
"error"
|
|
252
261
|
).filter((issue) => !isTerminalContext(issue.line))
|
|
253
262
|
);
|
|
263
|
+
issues.push(
|
|
264
|
+
...checkLines(
|
|
265
|
+
code,
|
|
266
|
+
RAW_BW_COLOR_RE,
|
|
267
|
+
"RAW_COLOR",
|
|
268
|
+
"Use semantic tokens (bg-background, text-foreground) instead of white/black",
|
|
269
|
+
"error"
|
|
270
|
+
)
|
|
271
|
+
);
|
|
272
|
+
issues.push(
|
|
273
|
+
...checkLines(
|
|
274
|
+
code,
|
|
275
|
+
INLINE_STYLE_COLOR_RE,
|
|
276
|
+
"inline-style-color",
|
|
277
|
+
"Use semantic Tailwind classes instead of inline style colors",
|
|
278
|
+
"error"
|
|
279
|
+
)
|
|
280
|
+
);
|
|
281
|
+
issues.push(
|
|
282
|
+
...checkLines(
|
|
283
|
+
code,
|
|
284
|
+
ARBITRARY_COLOR_RE,
|
|
285
|
+
"arbitrary-color",
|
|
286
|
+
"Use semantic tokens instead of arbitrary color values like bg-[#hex]",
|
|
287
|
+
"error"
|
|
288
|
+
)
|
|
289
|
+
);
|
|
290
|
+
issues.push(
|
|
291
|
+
...checkLines(
|
|
292
|
+
code,
|
|
293
|
+
SVG_COLOR_RE,
|
|
294
|
+
"svg-raw-color",
|
|
295
|
+
"Use currentColor or CSS variables for SVG fill/stroke, not raw colors",
|
|
296
|
+
"error"
|
|
297
|
+
)
|
|
298
|
+
);
|
|
299
|
+
issues.push(
|
|
300
|
+
...checkLines(
|
|
301
|
+
code,
|
|
302
|
+
COLOR_PROP_RE,
|
|
303
|
+
"color-prop",
|
|
304
|
+
"Use semantic color tokens instead of hex values in color props",
|
|
305
|
+
"error"
|
|
306
|
+
)
|
|
307
|
+
);
|
|
254
308
|
issues.push(
|
|
255
309
|
...checkLines(
|
|
256
310
|
code,
|
|
@@ -613,7 +667,7 @@ function resolveHref(linkText, context) {
|
|
|
613
667
|
function replaceRawColors(classes, colorMap) {
|
|
614
668
|
let changed = false;
|
|
615
669
|
let result = classes;
|
|
616
|
-
const accentColorRe = /\b((?:(?:
|
|
670
|
+
const accentColorRe = /\b((?:(?:[a-z][a-z0-9-]*:)*)?)(bg|text|border|ring|outline|shadow|from|to|via|divide|placeholder|decoration|caret|fill|stroke|accent)-(emerald|blue|violet|indigo|purple|teal|cyan|sky|rose|amber|red|green|yellow|pink|orange|fuchsia|lime)-(\d+)(?:\/\d+)?\b/g;
|
|
617
671
|
result = result.replace(accentColorRe, (m, statePrefix, prefix, color, shade) => {
|
|
618
672
|
const bareNoOpacity = m.replace(statePrefix, "").replace(/\/\d+$/, "");
|
|
619
673
|
if (colorMap[bareNoOpacity]) {
|
|
@@ -668,7 +722,7 @@ function replaceRawColors(classes, colorMap) {
|
|
|
668
722
|
}
|
|
669
723
|
return m;
|
|
670
724
|
});
|
|
671
|
-
const neutralColorRe = /\b((?:(?:
|
|
725
|
+
const neutralColorRe = /\b((?:(?:[a-z][a-z0-9-]*:)*)?)(bg|text|border|ring|outline|shadow|divide|placeholder|decoration|caret|fill|stroke|accent)-(zinc|slate|gray|neutral|stone)-(\d+)(?:\/\d+)?\b/g;
|
|
672
726
|
result = result.replace(neutralColorRe, (m, statePrefix, prefix, _color, shade) => {
|
|
673
727
|
const bareNoOpacity = m.replace(statePrefix, "").replace(/\/\d+$/, "");
|
|
674
728
|
if (colorMap[bareNoOpacity]) {
|
|
@@ -1041,6 +1095,15 @@ ${fixed}`;
|
|
|
1041
1095
|
return fullMatch;
|
|
1042
1096
|
});
|
|
1043
1097
|
if (hadColorFix) fixes.push("raw colors \u2192 semantic tokens");
|
|
1098
|
+
if (hadColorFix) {
|
|
1099
|
+
const postFixIssues = validatePageQuality(fixed);
|
|
1100
|
+
const postFixErrors = postFixIssues.filter(
|
|
1101
|
+
(i) => i.severity === "error" && ["raw-color", "inline-style-color", "arbitrary-color", "svg-raw-color", "color-prop"].includes(i.type)
|
|
1102
|
+
);
|
|
1103
|
+
if (postFixErrors.length > 0) {
|
|
1104
|
+
fixes.push(`post-fix re-validation found ${postFixErrors.length} remaining color issue(s)`);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1044
1107
|
const selectRe = /<select\b[^>]*>([\s\S]*?)<\/select>/g;
|
|
1045
1108
|
let hadSelectFix = false;
|
|
1046
1109
|
fixed = fixed.replace(selectRe, (_match, inner) => {
|
|
@@ -1455,11 +1518,34 @@ function verifyIncrementalEdit(before, after) {
|
|
|
1455
1518
|
}
|
|
1456
1519
|
return issues;
|
|
1457
1520
|
}
|
|
1521
|
+
async function validateSharedComponents(projectRoot) {
|
|
1522
|
+
const sharedDir = join(projectRoot, "components", "shared");
|
|
1523
|
+
let files;
|
|
1524
|
+
try {
|
|
1525
|
+
const entries = await readdir(sharedDir);
|
|
1526
|
+
files = entries.filter((f) => f.endsWith(".tsx"));
|
|
1527
|
+
} catch {
|
|
1528
|
+
return [];
|
|
1529
|
+
}
|
|
1530
|
+
const allIssues = [];
|
|
1531
|
+
for (const file of files) {
|
|
1532
|
+
const code = await readFile(join(sharedDir, file), "utf-8");
|
|
1533
|
+
const issues = validatePageQuality(code);
|
|
1534
|
+
for (const issue of issues) {
|
|
1535
|
+
allIssues.push({
|
|
1536
|
+
...issue,
|
|
1537
|
+
message: `[shared/${file}] ${issue.message}`
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
return allIssues;
|
|
1542
|
+
}
|
|
1458
1543
|
|
|
1459
1544
|
export {
|
|
1460
1545
|
validatePageQuality,
|
|
1461
1546
|
autoFixCode,
|
|
1462
1547
|
formatIssues,
|
|
1463
1548
|
checkDesignConsistency,
|
|
1464
|
-
verifyIncrementalEdit
|
|
1549
|
+
verifyIncrementalEdit,
|
|
1550
|
+
validateSharedComponents
|
|
1465
1551
|
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getPageGroup,
|
|
7
7
|
installPackages,
|
|
8
8
|
sanitizeMetadataStrings
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IFJK5OPI.js";
|
|
10
10
|
import {
|
|
11
11
|
toKebabCase
|
|
12
12
|
} from "./chunk-4TLYDTT3.js";
|
|
@@ -2147,7 +2147,7 @@ async function regeneratePage(pageId, config, projectRoot) {
|
|
|
2147
2147
|
const code = await generator.generate(page, appType);
|
|
2148
2148
|
const route = page.route || "/";
|
|
2149
2149
|
const isAuth = isAuthRoute(route) || isAuthRoute(page.name || page.id || "");
|
|
2150
|
-
const { loadPlan: loadPlanForPath } = await import("./plan-generator-
|
|
2150
|
+
const { loadPlan: loadPlanForPath } = await import("./plan-generator-D2UBTVCN.js");
|
|
2151
2151
|
const planForPath = loadPlanForPath(projectRoot);
|
|
2152
2152
|
const filePath = routeToFsPath(projectRoot, route, planForPath || isAuth);
|
|
2153
2153
|
await mkdir3(dirname3(filePath), { recursive: true });
|
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
regeneratePage,
|
|
13
13
|
scanAndInstallSharedDeps,
|
|
14
14
|
validateAndFixGeneratedCode
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-UZGT5APM.js";
|
|
16
|
+
import "./chunk-IFJK5OPI.js";
|
|
17
17
|
import "./chunk-4TLYDTT3.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-NLL3SHN3.js";
|
|
19
|
+
import "./chunk-U5SNPHVU.js";
|
|
20
20
|
import "./chunk-3RG5ZIWI.js";
|
|
21
21
|
export {
|
|
22
22
|
buildAppLayoutCode,
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
warnIfVolatile,
|
|
35
35
|
warnInlineDuplicates,
|
|
36
36
|
writeFile
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-UZGT5APM.js";
|
|
38
38
|
import {
|
|
39
39
|
COHERENT_REQUIRED_PACKAGES,
|
|
40
40
|
ensureUseClientIfNeeded,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
sanitizeMetadataStrings,
|
|
53
53
|
savePlan,
|
|
54
54
|
updateArchitecturePlan
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-IFJK5OPI.js";
|
|
56
56
|
import {
|
|
57
57
|
isValidTsx,
|
|
58
58
|
safeWrite
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
getDesignQualityForType,
|
|
75
75
|
inferPageTypeFromRoute,
|
|
76
76
|
selectContextualRules
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-NLL3SHN3.js";
|
|
78
78
|
import {
|
|
79
79
|
fixGlobalsCss,
|
|
80
80
|
generateV4GlobalsCss,
|
|
@@ -87,7 +87,7 @@ import {
|
|
|
87
87
|
formatIssues,
|
|
88
88
|
validatePageQuality,
|
|
89
89
|
verifyIncrementalEdit
|
|
90
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-U5SNPHVU.js";
|
|
91
91
|
import {
|
|
92
92
|
__require
|
|
93
93
|
} from "./chunk-3RG5ZIWI.js";
|
|
@@ -3941,7 +3941,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
|
|
|
3941
3941
|
if (plan && plan.sharedComponents.length > 0) {
|
|
3942
3942
|
spinner.start(`Phase 4.5/6 \u2014 Generating ${plan.sharedComponents.length} shared components from plan...`);
|
|
3943
3943
|
try {
|
|
3944
|
-
const { generateSharedComponentsFromPlan } = await import("./plan-generator-
|
|
3944
|
+
const { generateSharedComponentsFromPlan } = await import("./plan-generator-D2UBTVCN.js");
|
|
3945
3945
|
const generated = await generateSharedComponentsFromPlan(
|
|
3946
3946
|
plan,
|
|
3947
3947
|
styleContext,
|
|
@@ -4696,6 +4696,16 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
|
|
|
4696
4696
|
console.log(chalk8.dim(" \u{1F527} Post-generation fixes:"));
|
|
4697
4697
|
fixes.forEach((f) => console.log(chalk8.dim(` ${f}`)));
|
|
4698
4698
|
}
|
|
4699
|
+
const colorIssueTypes = ["raw-color", "inline-style-color", "arbitrary-color", "svg-raw-color", "color-prop"];
|
|
4700
|
+
const colorIssues = validatePageQuality(fixedCode).filter(
|
|
4701
|
+
(i) => i.severity === "error" && colorIssueTypes.includes(i.type)
|
|
4702
|
+
);
|
|
4703
|
+
if (colorIssues.length > 0) {
|
|
4704
|
+
console.warn(
|
|
4705
|
+
`\u26A0 Component has ${colorIssues.length} color issue(s) after auto-fix:
|
|
4706
|
+
` + colorIssues.map((i) => ` L${i.line}: ${i.message}`).join("\n")
|
|
4707
|
+
);
|
|
4708
|
+
}
|
|
4699
4709
|
await writeFile(fullPath, fixedCode);
|
|
4700
4710
|
printSharedComponentReport({
|
|
4701
4711
|
id: resolved.id,
|
|
@@ -5859,7 +5869,7 @@ async function chatCommand(message, options) {
|
|
|
5859
5869
|
spinner.start(`Creating shared component: ${componentName}...`);
|
|
5860
5870
|
const { createAIProvider: createAIProvider2 } = await import("./ai-provider-CGSIYFZT.js");
|
|
5861
5871
|
const { generateSharedComponent: generateSharedComponent6 } = await import("@getcoherent/core");
|
|
5862
|
-
const { autoFixCode: autoFixCode2 } = await import("./quality-validator-
|
|
5872
|
+
const { autoFixCode: autoFixCode2 } = await import("./quality-validator-IM6YFKLI.js");
|
|
5863
5873
|
const { extractPropsInterface, extractDependencies } = await import("./component-extractor-VYJLT5NR.js");
|
|
5864
5874
|
const aiProvider = await createAIProvider2(provider ?? "auto");
|
|
5865
5875
|
const prompt = `Generate a React component called "${componentName}". Description: ${message}.
|
|
@@ -6328,7 +6338,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6328
6338
|
}
|
|
6329
6339
|
try {
|
|
6330
6340
|
const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
|
|
6331
|
-
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-
|
|
6341
|
+
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-PFZDW2XW.js");
|
|
6332
6342
|
const manifest2 = await loadManifest6(projectRoot);
|
|
6333
6343
|
const reuseplan = projectRoot ? loadPlan(projectRoot) : null;
|
|
6334
6344
|
if (manifest2.shared.length > 0) {
|
|
@@ -8468,8 +8478,8 @@ async function fixCommand(opts = {}) {
|
|
|
8468
8478
|
console.log(chalk15.green(` \u2714 ${verb} syntax: ${syntaxFixed} file(s) (use client, metadata, quotes)`));
|
|
8469
8479
|
}
|
|
8470
8480
|
try {
|
|
8471
|
-
const { loadPlan: loadPlan2 } = await import("./plan-generator-
|
|
8472
|
-
const { ensurePlanGroupLayouts: ensurePlanGroupLayouts2 } = await import("./code-generator-
|
|
8481
|
+
const { loadPlan: loadPlan2 } = await import("./plan-generator-D2UBTVCN.js");
|
|
8482
|
+
const { ensurePlanGroupLayouts: ensurePlanGroupLayouts2 } = await import("./code-generator-IZ6XM6WG.js");
|
|
8473
8483
|
const plan = loadPlan2(projectRoot);
|
|
8474
8484
|
if (plan) {
|
|
8475
8485
|
if (!dsm) {
|
|
@@ -8523,7 +8533,7 @@ async function fixCommand(opts = {}) {
|
|
|
8523
8533
|
const publicExists = existsSync13(publicLayoutPath);
|
|
8524
8534
|
const needsPublicLayout = !publicExists || !readFileSync10(publicLayoutPath, "utf-8").includes("<Header");
|
|
8525
8535
|
if (needsPublicLayout) {
|
|
8526
|
-
const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-
|
|
8536
|
+
const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-IZ6XM6WG.js");
|
|
8527
8537
|
mkdirSync7(resolve8(projectRoot, "app", "(public)"), { recursive: true });
|
|
8528
8538
|
const publicResult = safeWrite(publicLayoutPath, buildPublicLayoutCodeForSidebar(), projectRoot, backups);
|
|
8529
8539
|
if (publicResult.ok) {
|
|
@@ -8572,7 +8582,7 @@ async function fixCommand(opts = {}) {
|
|
|
8572
8582
|
}
|
|
8573
8583
|
const themeTogglePath = resolve8(projectRoot, "components", "shared", "theme-toggle.tsx");
|
|
8574
8584
|
if (!existsSync13(themeTogglePath)) {
|
|
8575
|
-
const { generateThemeToggleCode } = await import("./code-generator-
|
|
8585
|
+
const { generateThemeToggleCode } = await import("./code-generator-IZ6XM6WG.js");
|
|
8576
8586
|
mkdirSync7(resolve8(projectRoot, "components", "shared"), { recursive: true });
|
|
8577
8587
|
const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
|
|
8578
8588
|
if (themeResult.ok) {
|
|
@@ -8593,7 +8603,7 @@ async function fixCommand(opts = {}) {
|
|
|
8593
8603
|
const isMinimal = appLayoutCode.length < 500 && !appLayoutCode.includes("Header") && !appLayoutCode.includes("Footer") && !appLayoutCode.includes("Sidebar") && !appLayoutCode.includes("SidebarProvider") && !appLayoutCode.includes("SidebarTrigger") && !appLayoutCode.includes("Sheet");
|
|
8594
8604
|
const navType = dsm.getConfig().navigation?.type || "header";
|
|
8595
8605
|
if (isMinimal && navType !== "none") {
|
|
8596
|
-
const { buildAppLayoutCode, buildGroupLayoutCode } = await import("./code-generator-
|
|
8606
|
+
const { buildAppLayoutCode, buildGroupLayoutCode } = await import("./code-generator-IZ6XM6WG.js");
|
|
8597
8607
|
const isSidebar = navType === "sidebar" || navType === "both";
|
|
8598
8608
|
const newLayout = isSidebar ? buildAppLayoutCode(navType, dsm.getConfig().name) : buildGroupLayoutCode("header", dsm.getConfig().pages?.map((p) => p.name) || [], dsm.getConfig().name);
|
|
8599
8609
|
if (!dryRun) {
|
|
@@ -9140,7 +9150,7 @@ async function checkCommand(opts = {}) {
|
|
|
9140
9150
|
if (!skipShared) {
|
|
9141
9151
|
try {
|
|
9142
9152
|
const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
|
|
9143
|
-
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-
|
|
9153
|
+
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-PFZDW2XW.js");
|
|
9144
9154
|
const manifest = await loadManifest9(projectRoot);
|
|
9145
9155
|
const appDir = resolve9(projectRoot, "app");
|
|
9146
9156
|
const pageFiles = existsSync14(appDir) ? findTsxFiles(appDir) : [];
|
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
routeToKey,
|
|
12
12
|
savePlan,
|
|
13
13
|
updateArchitecturePlan
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-IFJK5OPI.js";
|
|
15
|
+
import "./chunk-NLL3SHN3.js";
|
|
16
|
+
import "./chunk-U5SNPHVU.js";
|
|
17
17
|
import "./chunk-3RG5ZIWI.js";
|
|
18
18
|
export {
|
|
19
19
|
ArchitecturePlanSchema,
|
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
checkDesignConsistency,
|
|
4
4
|
formatIssues,
|
|
5
5
|
validatePageQuality,
|
|
6
|
+
validateSharedComponents,
|
|
6
7
|
verifyIncrementalEdit
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-U5SNPHVU.js";
|
|
8
9
|
import "./chunk-3RG5ZIWI.js";
|
|
9
10
|
export {
|
|
10
11
|
autoFixCode,
|
|
11
12
|
checkDesignConsistency,
|
|
12
13
|
formatIssues,
|
|
13
14
|
validatePageQuality,
|
|
15
|
+
validateSharedComponents,
|
|
14
16
|
verifyIncrementalEdit
|
|
15
17
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.6.
|
|
6
|
+
"version": "0.6.52",
|
|
7
7
|
"description": "CLI interface for Coherent Design Method",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "./dist/index.js",
|
|
@@ -33,8 +33,15 @@
|
|
|
33
33
|
],
|
|
34
34
|
"author": "Coherent Design Method",
|
|
35
35
|
"license": "MIT",
|
|
36
|
+
"scripts": {
|
|
37
|
+
"dev": "tsup --watch",
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "vitest"
|
|
41
|
+
},
|
|
36
42
|
"dependencies": {
|
|
37
43
|
"@anthropic-ai/sdk": "^0.32.0",
|
|
44
|
+
"@getcoherent/core": "workspace:*",
|
|
38
45
|
"chalk": "^5.3.0",
|
|
39
46
|
"chokidar": "^4.0.1",
|
|
40
47
|
"commander": "^11.1.0",
|
|
@@ -42,8 +49,7 @@
|
|
|
42
49
|
"open": "^10.1.0",
|
|
43
50
|
"ora": "^7.0.1",
|
|
44
51
|
"prompts": "^2.4.2",
|
|
45
|
-
"zod": "^3.22.4"
|
|
46
|
-
"@getcoherent/core": "0.6.50"
|
|
52
|
+
"zod": "^3.22.4"
|
|
47
53
|
},
|
|
48
54
|
"devDependencies": {
|
|
49
55
|
"@types/node": "^20.11.0",
|
|
@@ -52,11 +58,5 @@
|
|
|
52
58
|
"react": "^19.2.4",
|
|
53
59
|
"tsup": "^8.0.1",
|
|
54
60
|
"typescript": "^5.3.3"
|
|
55
|
-
},
|
|
56
|
-
"scripts": {
|
|
57
|
-
"dev": "tsup --watch",
|
|
58
|
-
"build": "tsup",
|
|
59
|
-
"typecheck": "tsc --noEmit",
|
|
60
|
-
"test": "vitest"
|
|
61
61
|
}
|
|
62
|
-
}
|
|
62
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Sergei Kovtun
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|