lism-cli 0.3.1 → 0.4.1

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/README.md CHANGED
@@ -9,9 +9,9 @@
9
9
  ## コマンド体系
10
10
 
11
11
  ```
12
- lism create [targetDir] [--template <name>] # examples から新規プロジェクト
13
- lism ui { init | add <names...> | list } # Lism UI コンポーネントの追加
14
- lism skill { add | check | update } # AI エージェント向け SKILL.md 配置
12
+ lism create [targetDir] [--template <name|category>] # templates から新規プロジェクト
13
+ lism ui { init | add <names...> | list } # Lism UI コンポーネントの追加
14
+ lism skill { add | check | update } # AI エージェント向け SKILL.md 配置
15
15
  ```
16
16
 
17
17
  ## 使い方
@@ -23,7 +23,10 @@ lism skill { add | check | update } # AI エージェント向け SKIL
23
23
  pnpm dlx lism-cli create
24
24
 
25
25
  # テンプレート名・出力先を指定
26
- pnpm dlx lism-cli create --template astro-minimal ./my-app
26
+ pnpm dlx lism-cli create --template minimal-astro ./my-app
27
+
28
+ # カテゴリ名を指定(stack 以下の選択を対話で続行)
29
+ pnpm dlx lism-cli create --template minimal ./my-app
27
30
  ```
28
31
 
29
32
  同じ動作は `pnpm create lism` / `npm create lism@latest` でも呼び出せます(`create-lism` パッケージ経由)。
@@ -13,16 +13,16 @@ var messages = {
13
13
  },
14
14
  // create
15
15
  "cli.create.description": {
16
- ja: "examples \u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u304B\u3089\u65B0\u898F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u751F\u6210\u3059\u308B",
17
- en: "Create a new project from an examples template"
16
+ ja: "templates \u304B\u3089\u65B0\u898F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u751F\u6210\u3059\u308B",
17
+ en: "Create a new project from a template"
18
18
  },
19
19
  "cli.create.arg.targetDir": {
20
20
  ja: "\u51FA\u529B\u5148\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA",
21
21
  en: "Target directory"
22
22
  },
23
23
  "cli.create.opt.template": {
24
- ja: "\u4F7F\u7528\u3059\u308B\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u540D\uFF08\u4F8B: astro-minimal\uFF09",
25
- en: "Template name to use (e.g. astro-minimal)"
24
+ ja: "\u4F7F\u7528\u3059\u308B\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u540D\u307E\u305F\u306F\u30AB\u30C6\u30B4\u30EA\u540D\uFF08\u4F8B: minimal-astro / minimal\uFF09",
25
+ en: "Template or category name to use (e.g. minimal-astro / minimal)"
26
26
  },
27
27
  "cli.create.opt.force": {
28
28
  ja: "\u65E2\u5B58\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u5F37\u5236\u4E0A\u66F8\u304D",
@@ -121,9 +121,33 @@ var messages = {
121
121
  ja: '\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8 "{name}" \u306F\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u5229\u7528\u53EF\u80FD: {list}',
122
122
  en: 'Template "{name}" not found. Available: {list}'
123
123
  },
124
- "create.promptSelectTemplate": {
125
- ja: "\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",
126
- en: "Select a template:"
124
+ "create.promptSelectCategory": {
125
+ ja: "\u30AB\u30C6\u30B4\u30EA\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",
126
+ en: "Select a category:"
127
+ },
128
+ "create.promptSelectVariant": {
129
+ ja: "\u30D0\u30EA\u30A2\u30F3\u30C8\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08{count}\u4EF6\uFF09:",
130
+ en: "Select a variant ({count} options):"
131
+ },
132
+ "create.promptSelectVariant.blog": {
133
+ ja: "\u6A5F\u80FD\u30EC\u30D9\u30EB\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08{count}\u4EF6\uFF09:",
134
+ en: "Select a feature level ({count} options):"
135
+ },
136
+ "create.promptSelectVariant.lp": {
137
+ ja: "\u696D\u7A2E\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08{count}\u4EF6\uFF09:",
138
+ en: "Select an industry ({count} options):"
139
+ },
140
+ "create.promptSelectVariant.web": {
141
+ ja: "\u696D\u7A2E\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08{count}\u4EF6\uFF09:",
142
+ en: "Select an industry ({count} options):"
143
+ },
144
+ "create.promptSelectStack": {
145
+ ja: "\u30B9\u30BF\u30C3\u30AF\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08{count}\u4EF6\uFF09:",
146
+ en: "Select a stack ({count} options):"
147
+ },
148
+ "create.usingStack": {
149
+ ja: "\u30B9\u30BF\u30C3\u30AF\u306F{stack}\u3092\u4F7F\u7528\u3057\u307E\u3059\uFF08{count}\u4EF6\uFF09\u3002",
150
+ en: "Using {stack} stack ({count} option)."
127
151
  },
128
152
  "create.promptTargetDir": {
129
153
  ja: "\u51FA\u529B\u5148\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA:",
@@ -141,6 +165,18 @@ var messages = {
141
165
  ja: '\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8 "{name}" \u3092\u53D6\u5F97\u4E2D\uFF08ref: {ref}\uFF09...',
142
166
  en: 'Fetching template "{name}" (ref: {ref})...'
143
167
  },
168
+ "create.templatePackageMissing": {
169
+ ja: '\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8"{name}"\u306E\u53D6\u5F97\u7D50\u679C\u306Bpackage.json\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u53D6\u5F97\u5143\u30D1\u30B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044: {path}',
170
+ en: 'Downloaded template "{name}" does not contain package.json. Check the source path: {path}'
171
+ },
172
+ "create.templateIndexMissing": {
173
+ ja: '\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8"{name}"\u306E\u53D6\u5F97\u7D50\u679C\u306Bindex.html\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u53D6\u5F97\u5143\u30D1\u30B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044: {path}',
174
+ en: 'Downloaded template "{name}" does not contain index.html. Check the source path: {path}'
175
+ },
176
+ "create.variantMissing": {
177
+ ja: 'variant "{variant}" \u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u53D6\u5F97\u5143\u30D1\u30B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044: {path}',
178
+ en: 'Variant "{variant}" directory not found. Check the source path: {path}'
179
+ },
144
180
  "create.created": {
145
181
  ja: "{dir} \u306B\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u751F\u6210\u3057\u307E\u3057\u305F\u3002",
146
182
  en: "Generated project at {dir}."
@@ -149,6 +185,18 @@ var messages = {
149
185
  ja: "\u6B21\u306E\u30B3\u30DE\u30F3\u30C9\u3067\u958B\u767A\u3092\u958B\u59CB\u3067\u304D\u307E\u3059:",
150
186
  en: "Next steps:"
151
187
  },
188
+ "create.nextStepsHtmlOpen": {
189
+ ja: " index.html\u3092\u30D6\u30E9\u30A6\u30B6\u3067\u958B\u3044\u3066\u304F\u3060\u3055\u3044",
190
+ en: " Open index.html in your browser"
191
+ },
192
+ "create.packageNameRewritten": {
193
+ ja: ' package.json\u306Ename\u3092"{name}"\u306B\u5909\u66F4\u3057\u307E\u3057\u305F\u3002',
194
+ en: ' Updated package.json name to "{name}".'
195
+ },
196
+ "create.packageNameFailed": {
197
+ ja: "package.json\u306Ename\u66F8\u304D\u63DB\u3048\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {reason}",
198
+ en: "Failed to rewrite package.json name: {reason}"
199
+ },
152
200
  "create.workspaceReplaced": {
153
201
  ja: " package.json \u306E workspace:* \u3092 ^{version} \u306B\u7F6E\u63DB\u3057\u307E\u3057\u305F\u3002",
154
202
  en: " Replaced workspace:* in package.json with ^{version}."
@@ -469,6 +517,7 @@ function interpolate(template, vars) {
469
517
 
470
518
  // src/commands/create.ts
471
519
  import fs from "fs";
520
+ import os from "os";
472
521
  import path from "path";
473
522
  import { downloadTemplate } from "giget";
474
523
  import { select, input, confirm } from "@inquirer/prompts";
@@ -498,8 +547,8 @@ var logger = {
498
547
  };
499
548
 
500
549
  // src/version.ts
501
- var LISM_CSS_VERSION = "0.16.0" ? "0.16.0" : "unknown";
502
- var CLI_VERSION = "0.3.1" ? "0.3.1" : "unknown";
550
+ var LISM_CSS_VERSION = "0.18.0" ? "0.18.0" : "unknown";
551
+ var CLI_VERSION = "0.4.1" ? "0.4.1" : "unknown";
503
552
 
504
553
  // src/constants.ts
505
554
  var SOURCE_REPO = "lism-css/lism-css";
@@ -511,19 +560,126 @@ var UI_COMPONENTS_PATH = "packages/lism-ui/src/components";
511
560
  var UI_HELPER_PATH = "packages/lism-ui/src/helper";
512
561
  var UI_REGISTRY_INDEX_PATH = "packages/lism-ui/registry-index.json";
513
562
  var SKILL_SOURCE_PATH = "skills/lism-css-guide";
514
- var EXAMPLES_PATH = "examples";
563
+ var TEMPLATES_PATH = "templates";
515
564
 
516
- // src/commands/create.ts
565
+ // ../../templates/manifest.ts
517
566
  var TEMPLATES = [
518
567
  {
519
- name: "astro-minimal",
520
- label: { ja: "Astro (\u6700\u5C0F\u69CB\u6210)", en: "Astro (minimal)" },
568
+ slug: "minimal-astro",
569
+ kind: "project",
570
+ category: "minimal",
571
+ stack: "astro",
572
+ sourcePath: "minimal/astro",
573
+ title: { ja: "Minimal Astro", en: "Minimal Astro" },
521
574
  description: { ja: "Astro \u30D9\u30FC\u30B9\u306E\u6700\u5C0F\u69CB\u6210", en: "Minimal Astro setup" }
575
+ },
576
+ {
577
+ slug: "minimal-vite",
578
+ kind: "project",
579
+ category: "minimal",
580
+ stack: "vite",
581
+ sourcePath: "minimal/vite",
582
+ title: { ja: "Minimal Vite", en: "Minimal Vite" },
583
+ description: { ja: "Vite + React \u30D9\u30FC\u30B9\u306E\u6700\u5C0F\u69CB\u6210", en: "Minimal Vite + React setup" },
584
+ previewUrl: "https://lism-minimal-vite.pages.dev/"
585
+ },
586
+ {
587
+ slug: "blog-astro-simple",
588
+ kind: "project",
589
+ category: "blog",
590
+ variant: "simple",
591
+ variantLabel: { ja: "Simple", en: "Simple" },
592
+ stack: "astro",
593
+ sourcePath: "blog/astro/simple",
594
+ title: { ja: "Blog Astro Simple", en: "Blog Astro Simple" },
595
+ description: { ja: "\u30BF\u30B0\u306E\u307F\u306E\u30B7\u30F3\u30D7\u30EB\u306A Astro \u30D6\u30ED\u30B0", en: "Simple Astro blog with tags" },
596
+ draft: true
597
+ },
598
+ {
599
+ slug: "blog-astro-full",
600
+ kind: "project",
601
+ category: "blog",
602
+ variant: "full",
603
+ variantLabel: { ja: "Full", en: "Full" },
604
+ stack: "astro",
605
+ sourcePath: "blog/astro/full",
606
+ title: { ja: "Blog Astro Full", en: "Blog Astro Full" },
607
+ description: { ja: "\u30AB\u30C6\u30B4\u30EA\u30FB\u76EE\u6B21\u3064\u304D\u306E Astro \u30D6\u30ED\u30B0", en: "Astro blog with categories and table of contents" },
608
+ draft: true
609
+ },
610
+ {
611
+ slug: "lp-astro-minimal",
612
+ kind: "single-project-variant",
613
+ category: "lp",
614
+ stack: "astro",
615
+ variant: "minimal",
616
+ variantLabel: { ja: "Minimal", en: "Minimal" },
617
+ sourcePath: "lp/astro",
618
+ title: { ja: "LP Minimal", en: "LP Minimal" },
619
+ description: { ja: "\u30DF\u30CB\u30DE\u30EB\u306A Astro \u30E9\u30F3\u30C7\u30A3\u30F3\u30B0\u30DA\u30FC\u30B8", en: "Minimal Astro landing page" },
620
+ draft: true
621
+ },
622
+ {
623
+ slug: "lp-astro-natural",
624
+ kind: "single-project-variant",
625
+ category: "lp",
626
+ stack: "astro",
627
+ variant: "natural",
628
+ variantLabel: { ja: "Natural", en: "Natural" },
629
+ sourcePath: "lp/astro",
630
+ title: { ja: "LP Natural", en: "LP Natural" },
631
+ description: { ja: "\u30CA\u30C1\u30E5\u30E9\u30EB\u306A\u96F0\u56F2\u6C17\u306E Astro \u30E9\u30F3\u30C7\u30A3\u30F3\u30B0\u30DA\u30FC\u30B8", en: "Natural-themed Astro landing page" },
632
+ draft: true
633
+ },
634
+ {
635
+ slug: "lp-astro-ryokan",
636
+ kind: "single-project-variant",
637
+ category: "lp",
638
+ stack: "astro",
639
+ variant: "ryokan",
640
+ variantLabel: { ja: "Ryokan", en: "Ryokan" },
641
+ sourcePath: "lp/astro",
642
+ title: { ja: "LP Ryokan", en: "LP Ryokan" },
643
+ description: { ja: "\u65C5\u9928\u30FB\u5BBF\u6CCA\u696D\u5411\u3051\u306E Astro \u30E9\u30F3\u30C7\u30A3\u30F3\u30B0\u30DA\u30FC\u30B8", en: "Astro landing page for ryokan / lodging" },
644
+ draft: true
645
+ }
646
+ ];
647
+
648
+ // src/commands/create.ts
649
+ var STACK_LABELS = {
650
+ astro: { ja: "Astro", en: "Astro" },
651
+ next: { ja: "Next.js", en: "Next.js" },
652
+ vite: { ja: "Vite + React", en: "Vite + React" },
653
+ html: { ja: "Static HTML", en: "Static HTML" }
654
+ };
655
+ var CATEGORIES = [
656
+ {
657
+ id: "minimal",
658
+ label: { ja: "Minimal", en: "Minimal" }
659
+ },
660
+ {
661
+ id: "blog",
662
+ label: { ja: "Blog", en: "Blog" },
663
+ variantPromptKey: "create.promptSelectVariant.blog"
664
+ },
665
+ {
666
+ id: "lp",
667
+ label: { ja: "Landing Page", en: "Landing Page" },
668
+ variantPromptKey: "create.promptSelectVariant.lp"
669
+ },
670
+ {
671
+ id: "web",
672
+ label: { ja: "Web", en: "Web" },
673
+ variantPromptKey: "create.promptSelectVariant.web"
522
674
  }
523
675
  ];
524
676
  async function runCreate({ template, targetDir, force = false }) {
525
- const tpl = await resolveTemplate(template);
526
- const outDir = path.resolve(process.cwd(), await resolveTargetDir(targetDir, tpl.name));
677
+ await runCreateWithTemplates({ template, targetDir, force }, TEMPLATES);
678
+ }
679
+ async function runCreateWithTemplates({ template, targetDir, force = false }, templates) {
680
+ const availableTemplates = templates.filter((tpl2) => !tpl2.draft);
681
+ const tpl = await resolveTemplate(template, availableTemplates);
682
+ const outDir = path.resolve(process.cwd(), await resolveTargetDir(targetDir, tpl.slug));
527
683
  if (fs.existsSync(outDir) && fs.readdirSync(outDir).length > 0 && !force) {
528
684
  const ok = await confirm({
529
685
  message: t("create.confirmOverwrite", { dir: outDir }),
@@ -535,37 +691,76 @@ async function runCreate({ template, targetDir, force = false }) {
535
691
  }
536
692
  }
537
693
  const ref = DEFAULT_TEMPLATES_REF;
538
- logger.info(t("create.fetching", { name: tpl.name, ref }));
539
- await downloadTemplate(`github:${SOURCE_REPO}/${EXAMPLES_PATH}/${tpl.name}#${ref}`, {
540
- dir: outDir,
541
- force: true,
542
- forceClean: force
543
- });
544
- rewriteWorkspaceDeps(outDir);
694
+ logger.info(t("create.fetching", { name: tpl.slug, ref }));
695
+ await downloadTemplateSource(tpl, outDir, ref, force);
696
+ ensureTemplateDownloaded(outDir, tpl);
697
+ postProcessTemplate(outDir, tpl);
545
698
  logger.success(t("create.created", { dir: outDir }));
546
- logger.heading(t("create.nextSteps"));
547
- const rel = path.relative(process.cwd(), outDir) || ".";
548
- logger.log(` cd ${rel}`);
549
- logger.log(" npm install # or pnpm install / yarn");
550
- logger.log(" npm run dev");
551
- logger.log("");
699
+ printNextSteps(outDir, tpl);
552
700
  }
553
701
  async function createCommand(targetDir, options) {
554
702
  await runCreate({ template: options.template, targetDir, force: options.force });
555
703
  }
556
- async function resolveTemplate(requested) {
704
+ async function resolveTemplate(requested, templates) {
557
705
  if (requested) {
558
- const found = TEMPLATES.find((t2) => t2.name === requested);
559
- if (!found) {
560
- throw new Error(t("create.templateNotFound", { name: requested, list: TEMPLATES.map((x) => x.name).join(", ") }));
706
+ const found = templates.find((t2) => t2.slug === requested);
707
+ if (found) return found;
708
+ const matchedCategory = CATEGORIES.find((category2) => category2.id === requested);
709
+ const categoryTemplates = matchedCategory ? templates.filter((tpl) => tpl.category === matchedCategory.id) : [];
710
+ if (matchedCategory && categoryTemplates.length > 0) {
711
+ return resolveFromCategory(matchedCategory.id, categoryTemplates);
561
712
  }
562
- return found;
713
+ throw new Error(t("create.templateNotFound", { name: requested, list: templates.map((x) => x.slug).join(", ") }));
563
714
  }
564
- const picked = await select({
565
- message: t("create.promptSelectTemplate"),
566
- choices: TEMPLATES.map((tpl) => ({ name: `${tOf(tpl.label)} \u2014 ${tOf(tpl.description)}`, value: tpl.name }))
715
+ const category = await select({
716
+ message: t("create.promptSelectCategory"),
717
+ choices: CATEGORIES.filter((category2) => templates.some((tpl) => tpl.category === category2.id)).map((category2) => ({
718
+ name: tOf(category2.label),
719
+ value: category2.id
720
+ }))
721
+ });
722
+ return resolveFromCategory(
723
+ category,
724
+ templates.filter((tpl) => tpl.category === category)
725
+ );
726
+ }
727
+ async function resolveFromCategory(category, categoryTemplates) {
728
+ const stack = await resolveStack(categoryTemplates);
729
+ const stackTemplates = categoryTemplates.filter((tpl) => tpl.stack === stack);
730
+ const variant = await resolveVariant(category, stackTemplates);
731
+ const variantTemplates = variant === void 0 ? stackTemplates : stackTemplates.filter((tpl) => tpl.variant === variant);
732
+ return variantTemplates[0];
733
+ }
734
+ async function resolveVariant(category, templates) {
735
+ const variants = uniqueDefined(templates.map((tpl) => tpl.variant));
736
+ if (variants.length <= 1) return variants[0];
737
+ const categoryDef = CATEGORIES.find((item) => item.id === category);
738
+ const messageKey = categoryDef?.variantPromptKey ?? "create.promptSelectVariant";
739
+ return select({
740
+ message: t(messageKey, { count: variants.length }),
741
+ choices: variants.map((variant) => {
742
+ const tpl = templates.find((item) => item.variant === variant);
743
+ return {
744
+ name: `${tOf(tpl.variantLabel ?? { ja: variant ?? "", en: variant ?? "" })} \u2014 ${tOf(tpl.description)}`,
745
+ value: variant
746
+ };
747
+ })
748
+ });
749
+ }
750
+ async function resolveStack(templates) {
751
+ const stacks = uniqueDefined(templates.map((tpl) => tpl.stack));
752
+ if (stacks.length === 1) {
753
+ const stack = stacks[0];
754
+ logger.info(t("create.usingStack", { stack: tOf(STACK_LABELS[stack]), count: stacks.length }));
755
+ return stack;
756
+ }
757
+ return select({
758
+ message: t("create.promptSelectStack", { count: stacks.length }),
759
+ choices: stacks.map((stack) => ({
760
+ name: tOf(STACK_LABELS[stack]),
761
+ value: stack
762
+ }))
567
763
  });
568
- return TEMPLATES.find((x) => x.name === picked);
569
764
  }
570
765
  async function resolveTargetDir(provided, templateName) {
571
766
  if (provided) return provided;
@@ -574,6 +769,139 @@ async function resolveTargetDir(provided, templateName) {
574
769
  default: `./${templateName}`
575
770
  });
576
771
  }
772
+ function ensureTemplateDownloaded(projectDir, tpl) {
773
+ if (tpl.kind === "static-html") {
774
+ const indexPath = path.join(projectDir, "index.html");
775
+ if (fs.existsSync(indexPath)) return;
776
+ throw new Error(t("create.templateIndexMissing", { name: tpl.slug, path: getTemplateSourcePath(tpl) }));
777
+ }
778
+ const pkgPath = path.join(projectDir, "package.json");
779
+ if (fs.existsSync(pkgPath)) return;
780
+ throw new Error(t("create.templatePackageMissing", { name: tpl.slug, path: getTemplateSourcePath(tpl) }));
781
+ }
782
+ async function downloadTemplateSource(tpl, outDir, ref, forceClean) {
783
+ if (tpl.kind === "base-overlay") {
784
+ await downloadTemplatePath(tpl.basePath, outDir, ref, forceClean);
785
+ const overlayDir = fs.mkdtempSync(path.join(os.tmpdir(), "lism-template-overlay-"));
786
+ try {
787
+ await downloadTemplatePath(tpl.overlayPath, overlayDir, ref, true);
788
+ mergeDirectory(overlayDir, outDir);
789
+ } finally {
790
+ fs.rmSync(overlayDir, { recursive: true, force: true });
791
+ }
792
+ return;
793
+ }
794
+ await downloadTemplatePath(tpl.sourcePath, outDir, ref, forceClean);
795
+ }
796
+ async function downloadTemplatePath(sourcePath, outDir, ref, forceClean) {
797
+ await downloadTemplate(`github:${SOURCE_REPO}/${TEMPLATES_PATH}/${sourcePath}#${ref}`, {
798
+ dir: outDir,
799
+ force: true,
800
+ forceClean
801
+ });
802
+ }
803
+ function postProcessTemplate(projectDir, tpl) {
804
+ if (tpl.kind === "static-html") return;
805
+ if (tpl.kind === "base-overlay" && tpl.rewritePackageName !== false) {
806
+ rewritePackageName(projectDir, tpl.slug);
807
+ }
808
+ if (tpl.kind === "single-project-variant") {
809
+ extractVariantPages(projectDir, tpl);
810
+ rewritePackageName(projectDir, tpl.packageName ?? tpl.slug);
811
+ }
812
+ cleanupDevArtifacts(projectDir);
813
+ rewriteWorkspaceDeps(projectDir);
814
+ }
815
+ function cleanupDevArtifacts(projectDir) {
816
+ const screenshotsDir = path.join(projectDir, "screenshots");
817
+ if (fs.existsSync(screenshotsDir)) {
818
+ fs.rmSync(screenshotsDir, { recursive: true, force: true });
819
+ }
820
+ const screenshotsConfig = path.join(projectDir, "screenshots.config.json");
821
+ if (fs.existsSync(screenshotsConfig)) {
822
+ fs.rmSync(screenshotsConfig, { force: true });
823
+ }
824
+ }
825
+ function extractVariantPages(projectDir, tpl) {
826
+ const pagesDir = path.join(projectDir, "src", "pages");
827
+ const variantDir = path.join(pagesDir, tpl.variant);
828
+ const variantIndex = path.join(variantDir, "index.astro");
829
+ const targetIndex = path.join(pagesDir, "index.astro");
830
+ if (!fs.existsSync(variantIndex)) {
831
+ throw new Error(
832
+ t("create.variantMissing", {
833
+ variant: tpl.variant,
834
+ path: `${formatTemplatePath(tpl.sourcePath)}/src/pages/${tpl.variant}/index.astro`
835
+ })
836
+ );
837
+ }
838
+ if (fs.existsSync(targetIndex)) {
839
+ fs.rmSync(targetIndex, { force: true });
840
+ }
841
+ fs.renameSync(variantIndex, targetIndex);
842
+ for (const entry of fs.readdirSync(pagesDir, { withFileTypes: true })) {
843
+ if (!entry.isDirectory()) continue;
844
+ fs.rmSync(path.join(pagesDir, entry.name), { recursive: true, force: true });
845
+ }
846
+ }
847
+ function printNextSteps(projectDir, tpl) {
848
+ logger.heading(t("create.nextSteps"));
849
+ const rel = path.relative(process.cwd(), projectDir) || ".";
850
+ logger.log(` cd ${rel}`);
851
+ if (tpl.kind === "static-html") {
852
+ logger.log(t("create.nextStepsHtmlOpen"));
853
+ logger.log("");
854
+ return;
855
+ }
856
+ logger.log(" npm install # or pnpm install / yarn");
857
+ logger.log(" npm run dev");
858
+ logger.log("");
859
+ }
860
+ function getTemplateSourcePath(tpl) {
861
+ if (tpl.kind === "base-overlay") return `${formatTemplatePath(tpl.basePath)} + ${formatTemplatePath(tpl.overlayPath)}`;
862
+ return formatTemplatePath(tpl.sourcePath);
863
+ }
864
+ function formatTemplatePath(sourcePath) {
865
+ return `${TEMPLATES_PATH}/${sourcePath}`;
866
+ }
867
+ function uniqueDefined(values) {
868
+ return [...new Set(values.filter((value) => value !== void 0))];
869
+ }
870
+ function mergeDirectory(fromDir, toDir) {
871
+ fs.mkdirSync(toDir, { recursive: true });
872
+ for (const entry of fs.readdirSync(fromDir, { withFileTypes: true })) {
873
+ const fromPath = path.join(fromDir, entry.name);
874
+ const toPath = path.join(toDir, entry.name);
875
+ if (entry.isDirectory()) {
876
+ if (fs.existsSync(toPath) && !fs.statSync(toPath).isDirectory()) {
877
+ fs.rmSync(toPath, { recursive: true, force: true });
878
+ }
879
+ mergeDirectory(fromPath, toPath);
880
+ continue;
881
+ }
882
+ if (fs.existsSync(toPath)) {
883
+ fs.rmSync(toPath, { recursive: true, force: true });
884
+ }
885
+ if (entry.isSymbolicLink()) {
886
+ fs.symlinkSync(fs.readlinkSync(fromPath), toPath);
887
+ } else {
888
+ fs.copyFileSync(fromPath, toPath);
889
+ }
890
+ }
891
+ }
892
+ function rewritePackageName(projectDir, name) {
893
+ const pkgPath = path.join(projectDir, "package.json");
894
+ if (!fs.existsSync(pkgPath)) return;
895
+ try {
896
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
897
+ if (pkg.name === name) return;
898
+ pkg.name = name;
899
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
900
+ logger.log(t("create.packageNameRewritten", { name }));
901
+ } catch (err) {
902
+ logger.warn(t("create.packageNameFailed", { reason: String(err) }));
903
+ }
904
+ }
577
905
  function rewriteWorkspaceDeps(projectDir) {
578
906
  const pkgPath = path.join(projectDir, "package.json");
579
907
  if (!fs.existsSync(pkgPath)) return;
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  preScanLang,
14
14
  setLang,
15
15
  t
16
- } from "./chunk-3PSCUHIC.js";
16
+ } from "./chunk-VMIN57OF.js";
17
17
 
18
18
  // src/createProgram.ts
19
19
  import { Command as Command3 } from "commander";
package/dist/lib.d.ts CHANGED
@@ -29,16 +29,16 @@ declare const messages: {
29
29
  readonly en: "Display language for the CLI (ja | en)";
30
30
  };
31
31
  readonly 'cli.create.description': {
32
- readonly ja: "examples テンプレートから新規プロジェクトを生成する";
33
- readonly en: "Create a new project from an examples template";
32
+ readonly ja: "templates から新規プロジェクトを生成する";
33
+ readonly en: "Create a new project from a template";
34
34
  };
35
35
  readonly 'cli.create.arg.targetDir': {
36
36
  readonly ja: "出力先ディレクトリ";
37
37
  readonly en: "Target directory";
38
38
  };
39
39
  readonly 'cli.create.opt.template': {
40
- readonly ja: "使用するテンプレート名(例: astro-minimal)";
41
- readonly en: "Template name to use (e.g. astro-minimal)";
40
+ readonly ja: "使用するテンプレート名またはカテゴリ名(例: minimal-astro / minimal)";
41
+ readonly en: "Template or category name to use (e.g. minimal-astro / minimal)";
42
42
  };
43
43
  readonly 'cli.create.opt.force': {
44
44
  readonly ja: "既存ディレクトリを強制上書き";
@@ -132,9 +132,33 @@ declare const messages: {
132
132
  readonly ja: "テンプレート \"{name}\" は見つかりません。利用可能: {list}";
133
133
  readonly en: "Template \"{name}\" not found. Available: {list}";
134
134
  };
135
- readonly 'create.promptSelectTemplate': {
136
- readonly ja: "テンプレートを選択してください:";
137
- readonly en: "Select a template:";
135
+ readonly 'create.promptSelectCategory': {
136
+ readonly ja: "カテゴリを選択してください:";
137
+ readonly en: "Select a category:";
138
+ };
139
+ readonly 'create.promptSelectVariant': {
140
+ readonly ja: "バリアントを選択してください({count}件):";
141
+ readonly en: "Select a variant ({count} options):";
142
+ };
143
+ readonly 'create.promptSelectVariant.blog': {
144
+ readonly ja: "機能レベルを選択してください({count}件):";
145
+ readonly en: "Select a feature level ({count} options):";
146
+ };
147
+ readonly 'create.promptSelectVariant.lp': {
148
+ readonly ja: "業種を選択してください({count}件):";
149
+ readonly en: "Select an industry ({count} options):";
150
+ };
151
+ readonly 'create.promptSelectVariant.web': {
152
+ readonly ja: "業種を選択してください({count}件):";
153
+ readonly en: "Select an industry ({count} options):";
154
+ };
155
+ readonly 'create.promptSelectStack': {
156
+ readonly ja: "スタックを選択してください({count}件):";
157
+ readonly en: "Select a stack ({count} options):";
158
+ };
159
+ readonly 'create.usingStack': {
160
+ readonly ja: "スタックは{stack}を使用します({count}件)。";
161
+ readonly en: "Using {stack} stack ({count} option).";
138
162
  };
139
163
  readonly 'create.promptTargetDir': {
140
164
  readonly ja: "出力先ディレクトリ:";
@@ -152,6 +176,18 @@ declare const messages: {
152
176
  readonly ja: "テンプレート \"{name}\" を取得中(ref: {ref})...";
153
177
  readonly en: "Fetching template \"{name}\" (ref: {ref})...";
154
178
  };
179
+ readonly 'create.templatePackageMissing': {
180
+ readonly ja: "テンプレート\"{name}\"の取得結果にpackage.jsonがありません。取得元パスを確認してください: {path}";
181
+ readonly en: "Downloaded template \"{name}\" does not contain package.json. Check the source path: {path}";
182
+ };
183
+ readonly 'create.templateIndexMissing': {
184
+ readonly ja: "テンプレート\"{name}\"の取得結果にindex.htmlがありません。取得元パスを確認してください: {path}";
185
+ readonly en: "Downloaded template \"{name}\" does not contain index.html. Check the source path: {path}";
186
+ };
187
+ readonly 'create.variantMissing': {
188
+ readonly ja: "variant \"{variant}\" のディレクトリが見つかりません。取得元パスを確認してください: {path}";
189
+ readonly en: "Variant \"{variant}\" directory not found. Check the source path: {path}";
190
+ };
155
191
  readonly 'create.created': {
156
192
  readonly ja: "{dir} にプロジェクトを生成しました。";
157
193
  readonly en: "Generated project at {dir}.";
@@ -160,6 +196,18 @@ declare const messages: {
160
196
  readonly ja: "次のコマンドで開発を開始できます:";
161
197
  readonly en: "Next steps:";
162
198
  };
199
+ readonly 'create.nextStepsHtmlOpen': {
200
+ readonly ja: " index.htmlをブラウザで開いてください";
201
+ readonly en: " Open index.html in your browser";
202
+ };
203
+ readonly 'create.packageNameRewritten': {
204
+ readonly ja: " package.jsonのnameを\"{name}\"に変更しました。";
205
+ readonly en: " Updated package.json name to \"{name}\".";
206
+ };
207
+ readonly 'create.packageNameFailed': {
208
+ readonly ja: "package.jsonのname書き換えに失敗しました: {reason}";
209
+ readonly en: "Failed to rewrite package.json name: {reason}";
210
+ };
163
211
  readonly 'create.workspaceReplaced': {
164
212
  readonly ja: " package.json の workspace:* を ^{version} に置換しました。";
165
213
  readonly en: " Replaced workspace:* in package.json with ^{version}.";
package/dist/lib.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  setLang,
4
4
  t,
5
5
  tOf
6
- } from "./chunk-3PSCUHIC.js";
6
+ } from "./chunk-VMIN57OF.js";
7
7
  export {
8
8
  runCreate,
9
9
  setLang,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lism-cli",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "CLI for scaffolding projects and adding UI components for Lism CSS / Lism UI.",
5
5
  "author": {
6
6
  "name": "ddryo",