@getcoherent/cli 0.5.7 → 0.5.8

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.
Files changed (2) hide show
  1. package/dist/index.js +122 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -657,7 +657,8 @@ ${out}`;
657
657
  return out;
658
658
  }
659
659
  function sanitizeMetadataStrings(code) {
660
- let out = code.replace(/(:\s*'.+)\\'(\s*)$/gm, "$1'$2");
660
+ let out = code.replace(/\\'(\s*[}\],])/g, "'$1");
661
+ out = out.replace(/(:\s*'.+)\\'(\s*)$/gm, "$1'$2");
661
662
  for (const key of ["description", "title"]) {
662
663
  const re = new RegExp(`\\b${key}:\\s*'((?:[^'\\\\]|'(?![,}]))*)'`, "gs");
663
664
  out = out.replace(re, (_, inner) => `${key}: '${inner.replace(/'/g, "\\'")}'`);
@@ -665,7 +666,9 @@ function sanitizeMetadataStrings(code) {
665
666
  return out;
666
667
  }
667
668
  function fixEscapedClosingQuotes(code) {
668
- return code.replace(/(:\s*'.+)\\'(\s*)$/gm, "$1'$2");
669
+ let out = code.replace(/\\'(\s*[}\],])/g, "'$1");
670
+ out = out.replace(/(:\s*'.+)\\'(\s*)$/gm, "$1'$2");
671
+ return out;
669
672
  }
670
673
  function fixUnescapedLtInJsx(code) {
671
674
  let out = code;
@@ -3598,6 +3601,7 @@ LINKS & INTERACTIVE STATES (consistency is critical):
3598
3601
 
3599
3602
  ICONS:
3600
3603
  - Size: ALWAYS size-4 (16px). Color: ALWAYS text-muted-foreground. Import: ALWAYS from lucide-react.
3604
+ - ALWAYS add shrink-0 to icon className to prevent flex containers from squishing them.
3601
3605
 
3602
3606
  ANTI-PATTERNS (NEVER DO):
3603
3607
  - text-base as body text \u2192 use text-sm
@@ -5576,6 +5580,7 @@ async function autoFixCode(code) {
5576
5580
  const fixes = [];
5577
5581
  let fixed = code;
5578
5582
  const beforeQuoteFix = fixed;
5583
+ fixed = fixed.replace(/\\'(\s*[}\],])/g, "'$1");
5579
5584
  fixed = fixed.replace(/(:\s*'.+)\\'(\s*)$/gm, "$1'$2");
5580
5585
  if (fixed !== beforeQuoteFix) {
5581
5586
  fixes.push("fixed escaped closing quotes in strings");
@@ -5886,6 +5891,23 @@ ${selectImport}`
5886
5891
  }
5887
5892
  }
5888
5893
  }
5894
+ const lucideNamesMatch = fixed.match(/import\s*\{([^}]+)\}\s*from\s*["']lucide-react["']/);
5895
+ if (lucideNamesMatch) {
5896
+ const lucideNames = new Set(
5897
+ lucideNamesMatch[1].split(",").map((s) => s.trim()).filter(Boolean)
5898
+ );
5899
+ const beforeShrinkFix = fixed;
5900
+ for (const iconName of lucideNames) {
5901
+ const iconRe = new RegExp(`(<${iconName}\\s[^>]*className=")([^"]*)(")`, "g");
5902
+ fixed = fixed.replace(iconRe, (_m, pre, classes, post) => {
5903
+ if (/\bshrink-0\b/.test(classes)) return _m;
5904
+ return `${pre}${classes} shrink-0${post}`;
5905
+ });
5906
+ }
5907
+ if (fixed !== beforeShrinkFix) {
5908
+ fixes.push("added shrink-0 to icons");
5909
+ }
5910
+ }
5889
5911
  const linkWithButtonRe = /(<Link\b[^>]*>)\s*(<Button\b(?![^>]*asChild)[^>]*>)([\s\S]*?)<\/Button>\s*<\/Link>/g;
5890
5912
  const beforeLinkFix = fixed;
5891
5913
  fixed = fixed.replace(linkWithButtonRe, (_match, linkOpen, buttonOpen, inner) => {
@@ -6779,6 +6801,10 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
6779
6801
  } catch {
6780
6802
  spinner.text = "AI plan failed \u2014 extracting pages from your request...";
6781
6803
  }
6804
+ if (modCtx.config.name === "My App") {
6805
+ const nameFromPrompt = extractAppNameFromPrompt(message);
6806
+ if (nameFromPrompt) modCtx.config.name = nameFromPrompt;
6807
+ }
6782
6808
  if (pageNames.length === 0) {
6783
6809
  pageNames = extractPageNamesFromMessage(message);
6784
6810
  }
@@ -6908,6 +6934,23 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
6908
6934
  spinner.succeed(`Phase 4/4 \u2014 Generated ${allRequests.length} pages (${withCode} with full code)`);
6909
6935
  return allRequests;
6910
6936
  }
6937
+ function extractAppNameFromPrompt(prompt) {
6938
+ const patterns = [
6939
+ /(?:called|named|app\s+name)\s+["']([^"']+)["']/i,
6940
+ /(?:called|named|app\s+name)\s+(\S+)/i,
6941
+ /\b(?:build|create|make)\s+(?:a\s+)?(\S+)\s+(?:app|platform|tool|dashboard|website|saas)/i
6942
+ ];
6943
+ for (const re of patterns) {
6944
+ const m = prompt.match(re);
6945
+ if (m && m[1] && m[1].length >= 2 && m[1].length <= 30) {
6946
+ const name = m[1].replace(/[.,;:!?]$/, "");
6947
+ const skip = /* @__PURE__ */ new Set(["a", "an", "the", "my", "our", "new", "full", "complete", "simple", "modern", "beautiful", "responsive", "fast", "cool", "great", "basic", "quick", "small", "large", "custom", "nice"]);
6948
+ if (skip.has(name.toLowerCase())) continue;
6949
+ return name.charAt(0).toUpperCase() + name.slice(1);
6950
+ }
6951
+ }
6952
+ return null;
6953
+ }
6911
6954
 
6912
6955
  // src/commands/chat/modification-handler.ts
6913
6956
  import { resolve as resolve7 } from "path";
@@ -7832,19 +7875,24 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
7832
7875
  if (aiPageCode) {
7833
7876
  finalPageCode = aiPageCode;
7834
7877
  if (DEBUG2) console.log(chalk11.dim(` [pageCode] Using AI-generated pageCode (user content priority)`));
7835
- } else if (page.pageType && page.structuredContent) {
7836
- const templateFn = getTemplateForPageType(page.pageType);
7837
- if (templateFn) {
7838
- try {
7839
- const pageName = (page.name || "Page").replace(/\s+/g, "");
7840
- const opts = {
7841
- route: page.route || `/${page.id || "page"}`,
7842
- pageName
7843
- };
7844
- finalPageCode = templateFn(page.structuredContent, opts);
7845
- if (DEBUG2) console.log(chalk11.dim(` [template] Used "${page.pageType}" template (no pageCode provided)`));
7846
- } catch {
7847
- if (DEBUG2) console.log(chalk11.dim(` [template] Failed for "${page.pageType}"`));
7878
+ } else {
7879
+ const inferredType = page.pageType || inferPageType(page.route || "", page.name || "");
7880
+ if (inferredType) {
7881
+ const templateFn = getTemplateForPageType(inferredType);
7882
+ if (templateFn) {
7883
+ try {
7884
+ const pageName = (page.name || "Page").replace(/\s+/g, "");
7885
+ const opts = {
7886
+ route: page.route || `/${page.id || "page"}`,
7887
+ pageName
7888
+ };
7889
+ const content = page.structuredContent || getDefaultContent(inferredType, page.name || pageName);
7890
+ finalPageCode = templateFn(content, opts);
7891
+ if (DEBUG2)
7892
+ console.log(chalk11.dim(` [template] Used "${inferredType}" template (inferred from route/name)`));
7893
+ } catch {
7894
+ if (DEBUG2) console.log(chalk11.dim(` [template] Failed for "${inferredType}"`));
7895
+ }
7848
7896
  }
7849
7897
  }
7850
7898
  }
@@ -8216,6 +8264,65 @@ ${pagesCtx}`
8216
8264
  };
8217
8265
  }
8218
8266
  }
8267
+ function inferPageType(route, name) {
8268
+ const key = (route + " " + name).toLowerCase();
8269
+ if (/\blogin\b|\bsign.?in\b/.test(key)) return "login";
8270
+ if (/\bregister\b|\bsign.?up\b/.test(key)) return "register";
8271
+ if (/\bdashboard\b/.test(key)) return "dashboard";
8272
+ if (/\bpric(e|ing)\b/.test(key)) return "pricing";
8273
+ if (/\bfaq\b/.test(key)) return "faq";
8274
+ if (/\bcontact\b/.test(key)) return "contact";
8275
+ if (/\bblog\b/.test(key)) return "blog";
8276
+ if (/\bchangelog\b/.test(key)) return "changelog";
8277
+ if (/\babout\b/.test(key)) return "about";
8278
+ if (/\bsettings?\b/.test(key)) return "settings";
8279
+ return null;
8280
+ }
8281
+ function getDefaultContent(pageType, pageName) {
8282
+ const defaults = {
8283
+ login: {
8284
+ title: "Welcome back",
8285
+ description: "Sign in to your account to continue"
8286
+ },
8287
+ register: {
8288
+ title: "Create an account",
8289
+ description: "Get started with your free account"
8290
+ },
8291
+ dashboard: {
8292
+ title: "Dashboard",
8293
+ description: `Welcome to your ${pageName} dashboard`
8294
+ },
8295
+ pricing: {
8296
+ title: "Pricing",
8297
+ description: "Choose the plan that works for you"
8298
+ },
8299
+ faq: {
8300
+ title: "Frequently Asked Questions",
8301
+ description: "Find answers to common questions"
8302
+ },
8303
+ contact: {
8304
+ title: "Contact Us",
8305
+ description: "Get in touch with our team"
8306
+ },
8307
+ blog: {
8308
+ title: "Blog",
8309
+ description: "Latest news, updates, and insights"
8310
+ },
8311
+ changelog: {
8312
+ title: "Changelog",
8313
+ description: "What's new and improved"
8314
+ },
8315
+ about: {
8316
+ title: `About ${pageName}`,
8317
+ description: "Learn more about our mission and team"
8318
+ },
8319
+ settings: {
8320
+ title: "Settings",
8321
+ description: "Manage your account and preferences"
8322
+ }
8323
+ };
8324
+ return defaults[pageType] || { title: pageName, description: "" };
8325
+ }
8219
8326
 
8220
8327
  // src/utils/nav-snapshot.ts
8221
8328
  function takeNavSnapshot(items) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.5.7",
6
+ "version": "0.5.8",
7
7
  "description": "CLI interface for Coherent Design Method",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",