@getcoherent/cli 0.3.7 → 0.3.9
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/index.js +69 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2368,6 +2368,7 @@ export default config
|
|
|
2368
2368
|
await writeFile(join5(projectPath, "postcss.config.mjs"), postcssContent);
|
|
2369
2369
|
}
|
|
2370
2370
|
await scaffolder.generateRootLayout();
|
|
2371
|
+
await configureNextImages(projectPath);
|
|
2371
2372
|
const welcomeMarkdown = getWelcomeMarkdown();
|
|
2372
2373
|
const homePageContent = generateWelcomeComponent(welcomeMarkdown);
|
|
2373
2374
|
await writeFile(join5(projectPath, "app", "page.tsx"), homePageContent);
|
|
@@ -2421,6 +2422,31 @@ export default config
|
|
|
2421
2422
|
process.exit(1);
|
|
2422
2423
|
}
|
|
2423
2424
|
}
|
|
2425
|
+
async function configureNextImages(projectPath) {
|
|
2426
|
+
const tsPath = join5(projectPath, "next.config.ts");
|
|
2427
|
+
const jsPath = join5(projectPath, "next.config.js");
|
|
2428
|
+
const mjsPath = join5(projectPath, "next.config.mjs");
|
|
2429
|
+
let configPath = "";
|
|
2430
|
+
if (existsSync8(tsPath)) configPath = tsPath;
|
|
2431
|
+
else if (existsSync8(mjsPath)) configPath = mjsPath;
|
|
2432
|
+
else if (existsSync8(jsPath)) configPath = jsPath;
|
|
2433
|
+
else return;
|
|
2434
|
+
const content = `import type { NextConfig } from "next";
|
|
2435
|
+
|
|
2436
|
+
const nextConfig: NextConfig = {
|
|
2437
|
+
images: {
|
|
2438
|
+
remotePatterns: [
|
|
2439
|
+
{ protocol: "https", hostname: "i.pravatar.cc" },
|
|
2440
|
+
{ protocol: "https", hostname: "images.unsplash.com" },
|
|
2441
|
+
{ protocol: "https", hostname: "picsum.photos" },
|
|
2442
|
+
],
|
|
2443
|
+
},
|
|
2444
|
+
};
|
|
2445
|
+
|
|
2446
|
+
export default nextConfig;
|
|
2447
|
+
`;
|
|
2448
|
+
await writeFile(configPath, content);
|
|
2449
|
+
}
|
|
2424
2450
|
|
|
2425
2451
|
// src/commands/chat.ts
|
|
2426
2452
|
import chalk13 from "chalk";
|
|
@@ -4507,6 +4533,7 @@ pageCode rules (shadcn/ui blocks quality):
|
|
|
4507
4533
|
- Login/form pattern: outer div(flex min-h-svh flex-col items-center justify-center p-6 md:p-10) > inner div(w-full max-w-sm) > Card with form.
|
|
4508
4534
|
- Dashboard pattern: main(mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6 flex flex-1 flex-col gap-4) > page header(h1 text-2xl font-bold tracking-tight + p text-sm text-muted-foreground) > stats grid(grid gap-4 md:grid-cols-2 lg:grid-cols-4) > content cards.
|
|
4509
4535
|
- No placeholders: real contextual copy only. Use the EXACT text, language, and content from the user's request.
|
|
4536
|
+
- IMAGES: For avatar/profile photos, use https://i.pravatar.cc/150?u=<unique-seed> (e.g. ?u=sarah.johnson). For hero/product images, use https://picsum.photos/800/400?random=N. Use standard <img> tags with className, NOT Next.js <Image>. Always provide alt text.
|
|
4510
4537
|
- Hover/focus on every interactive element (hover:bg-muted, focus-visible:ring-2 focus-visible:ring-ring).
|
|
4511
4538
|
- LANGUAGE: Match the language of the user's request. English request \u2192 English page. Russian request \u2192 Russian page. Never switch languages.
|
|
4512
4539
|
|
|
@@ -7090,6 +7117,42 @@ function stripInlineLayoutElements(code) {
|
|
|
7090
7117
|
}
|
|
7091
7118
|
return { code: result, stripped };
|
|
7092
7119
|
}
|
|
7120
|
+
function enforceWidthWrapper(code, route) {
|
|
7121
|
+
if (route === "/" || route === "/home") return { code, fixed: false };
|
|
7122
|
+
if (/<section[\s>]/i.test(code) && (/<section[\s>]/gi.exec(code) || []).length >= 2) {
|
|
7123
|
+
return { code, fixed: false };
|
|
7124
|
+
}
|
|
7125
|
+
const narrowWidths = /max-w-(xs|sm|md|lg|xl|2xl|3xl|4xl|5xl|6xl)\b/;
|
|
7126
|
+
const hasMax7xl = /max-w-7xl/.test(code);
|
|
7127
|
+
if (hasMax7xl) return { code, fixed: false };
|
|
7128
|
+
const mainMatch = code.match(/<main\s+className="([^"]*)"/);
|
|
7129
|
+
if (mainMatch) {
|
|
7130
|
+
const currentClasses = mainMatch[1];
|
|
7131
|
+
if (narrowWidths.test(currentClasses)) {
|
|
7132
|
+
const fixed = currentClasses.replace(narrowWidths, "max-w-7xl");
|
|
7133
|
+
return { code: code.replace(mainMatch[0], `<main className="${fixed}"`), fixed: true };
|
|
7134
|
+
}
|
|
7135
|
+
if (!currentClasses.includes("max-w-")) {
|
|
7136
|
+
const newClasses = `mx-auto max-w-7xl ${currentClasses}`;
|
|
7137
|
+
return { code: code.replace(mainMatch[0], `<main className="${newClasses}"`), fixed: true };
|
|
7138
|
+
}
|
|
7139
|
+
}
|
|
7140
|
+
const returnMatch = code.match(/return\s*\(\s*\n?\s*<(div|main)\s+className="([^"]*)"/);
|
|
7141
|
+
if (returnMatch) {
|
|
7142
|
+
const [fullMatch, tag, currentClasses] = returnMatch;
|
|
7143
|
+
if (narrowWidths.test(currentClasses)) {
|
|
7144
|
+
const fixed = currentClasses.replace(narrowWidths, "max-w-7xl");
|
|
7145
|
+
return { code: code.replace(fullMatch, `return (
|
|
7146
|
+
<${tag} className="${fixed}"`), fixed: true };
|
|
7147
|
+
}
|
|
7148
|
+
if (!currentClasses.includes("max-w-")) {
|
|
7149
|
+
const newClasses = `mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 ${currentClasses}`;
|
|
7150
|
+
return { code: code.replace(fullMatch, `return (
|
|
7151
|
+
<${tag} className="${newClasses}"`), fixed: true };
|
|
7152
|
+
}
|
|
7153
|
+
}
|
|
7154
|
+
return { code, fixed: false };
|
|
7155
|
+
}
|
|
7093
7156
|
async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider, originalMessage) {
|
|
7094
7157
|
switch (request.type) {
|
|
7095
7158
|
case "modify-layout-block": {
|
|
@@ -7464,8 +7527,11 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
|
|
|
7464
7527
|
codeToWrite = autoFixed;
|
|
7465
7528
|
const { code: layoutStripped, stripped } = stripInlineLayoutElements(codeToWrite);
|
|
7466
7529
|
codeToWrite = layoutStripped;
|
|
7530
|
+
const { code: widthFixed, fixed: widthWasFixed } = enforceWidthWrapper(codeToWrite, route);
|
|
7531
|
+
codeToWrite = widthFixed;
|
|
7467
7532
|
const allFixes = [...postFixes, ...autoFixes];
|
|
7468
7533
|
if (stripped.length > 0) allFixes.push(`stripped inline ${stripped.join(", ")} (layout owns these)`);
|
|
7534
|
+
if (widthWasFixed) allFixes.push("enforced max-w-7xl width consistency");
|
|
7469
7535
|
if (allFixes.length > 0) {
|
|
7470
7536
|
console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
|
|
7471
7537
|
allFixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
|
|
@@ -7631,8 +7697,11 @@ ${pagesCtx}`
|
|
|
7631
7697
|
codeToWrite = autoFixed;
|
|
7632
7698
|
const { code: layoutStripped, stripped } = stripInlineLayoutElements(codeToWrite);
|
|
7633
7699
|
codeToWrite = layoutStripped;
|
|
7700
|
+
const { code: widthFixed2, fixed: widthWasFixed2 } = enforceWidthWrapper(codeToWrite, route);
|
|
7701
|
+
codeToWrite = widthFixed2;
|
|
7634
7702
|
const allFixes = [...postFixes, ...autoFixes];
|
|
7635
7703
|
if (stripped.length > 0) allFixes.push(`stripped inline ${stripped.join(", ")} (layout owns these)`);
|
|
7704
|
+
if (widthWasFixed2) allFixes.push("enforced max-w-7xl width consistency");
|
|
7636
7705
|
if (allFixes.length > 0) {
|
|
7637
7706
|
console.log(chalk11.dim(" \u{1F527} Post-generation fixes:"));
|
|
7638
7707
|
allFixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
|