create-zudo-doc 3.1.0 → 3.3.0

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 (127) hide show
  1. package/dist/claude-md-gen.d.ts +8 -0
  2. package/dist/claude-md-gen.js +43 -26
  3. package/dist/compose.d.ts +14 -20
  4. package/dist/compose.js +15 -25
  5. package/dist/features/body-foot-util.d.ts +8 -4
  6. package/dist/features/body-foot-util.js +8 -4
  7. package/dist/features/claude-resources.d.ts +12 -0
  8. package/dist/features/claude-resources.js +13 -6
  9. package/dist/features/design-token-panel.d.ts +0 -12
  10. package/dist/features/design-token-panel.js +32 -93
  11. package/dist/features/doc-history.d.ts +18 -3
  12. package/dist/features/doc-history.js +45 -60
  13. package/dist/features/doc-tags.d.ts +9 -13
  14. package/dist/features/doc-tags.js +10 -26
  15. package/dist/features/dynamic-page-transition.d.ts +19 -30
  16. package/dist/features/dynamic-page-transition.js +21 -209
  17. package/dist/features/footer-taglist.d.ts +1 -1
  18. package/dist/features/footer-taglist.js +1 -1
  19. package/dist/features/footer.d.ts +3 -2
  20. package/dist/features/footer.js +3 -2
  21. package/dist/features/i18n.d.ts +13 -8
  22. package/dist/features/i18n.js +14 -9
  23. package/dist/features/image-enlarge.d.ts +7 -26
  24. package/dist/features/image-enlarge.js +7 -26
  25. package/dist/features/llms-txt.d.ts +3 -5
  26. package/dist/features/llms-txt.js +3 -5
  27. package/dist/features/search.d.ts +7 -3
  28. package/dist/features/search.js +7 -3
  29. package/dist/features/sidebar-resizer.d.ts +4 -8
  30. package/dist/features/sidebar-resizer.js +4 -8
  31. package/dist/features/sidebar-toggle.d.ts +7 -7
  32. package/dist/features/sidebar-toggle.js +7 -7
  33. package/dist/features/tag-governance.d.ts +14 -7
  34. package/dist/features/tag-governance.js +52 -8
  35. package/dist/features/tauri.d.ts +13 -10
  36. package/dist/features/tauri.js +16 -52
  37. package/dist/features/versioning.d.ts +12 -24
  38. package/dist/features/versioning.js +13 -39
  39. package/dist/index.js +2 -3
  40. package/dist/preset.d.ts +1 -0
  41. package/dist/preset.js +5 -0
  42. package/dist/prompts.d.ts +2 -0
  43. package/dist/prompts.js +1 -0
  44. package/dist/scaffold.d.ts +13 -6
  45. package/dist/scaffold.js +78 -59
  46. package/dist/utils.d.ts +10 -0
  47. package/dist/utils.js +14 -0
  48. package/dist/zfb-config-gen.d.ts +32 -20
  49. package/dist/zfb-config-gen.js +400 -53
  50. package/package.json +2 -2
  51. package/templates/base/pages/docs/[[...slug]].tsx +59 -0
  52. package/templates/base/pages/index.tsx +6 -41
  53. package/templates/base/scripts/setup-doc-skill.sh +261 -0
  54. package/templates/base/src/styles/global.css +15 -340
  55. package/templates/base/tsconfig.json +3 -26
  56. package/templates/features/i18n/files/pages/[locale]/docs/[[...slug]].tsx +88 -0
  57. package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +3 -1
  58. package/dist/settings-gen.d.ts +0 -2
  59. package/dist/settings-gen.js +0 -319
  60. package/templates/base/.htmlvalidate.json +0 -5
  61. package/templates/base/.zfb/doc-history-meta.json +0 -1
  62. package/templates/base/pages/_data.ts +0 -160
  63. package/templates/base/pages/lib/_body-end-islands.tsx +0 -165
  64. package/templates/base/pages/lib/_chrome.ts +0 -167
  65. package/templates/base/pages/lib/_details.tsx +0 -29
  66. package/templates/base/pages/lib/_doc-route-entries.ts +0 -10
  67. package/templates/base/pages/lib/_extract-headings.ts +0 -37
  68. package/templates/base/pages/lib/_frontmatter-preview-data.ts +0 -27
  69. package/templates/base/pages/lib/_nav-source-cache.ts +0 -100
  70. package/templates/base/pages/lib/_nav-source-docs.ts +0 -17
  71. package/templates/base/pages/lib/_preset-generator.tsx +0 -81
  72. package/templates/base/pages/lib/_route-context.ts +0 -32
  73. package/templates/base/pages/lib/_search-widget.tsx +0 -17
  74. package/templates/base/pages/lib/doc-page-props.ts +0 -30
  75. package/templates/base/pages/lib/locale-merge.ts +0 -59
  76. package/templates/base/scripts/run-b4push.sh +0 -102
  77. package/templates/base/src/components/ai-chat-modal.tsx +0 -18
  78. package/templates/base/src/components/content/code-group.tsx +0 -3
  79. package/templates/base/src/components/content/content-admonition.tsx +0 -4
  80. package/templates/base/src/components/desktop-sidebar-toggle.tsx +0 -15
  81. package/templates/base/src/components/doc-history.tsx +0 -21
  82. package/templates/base/src/components/image-enlarge.tsx +0 -24
  83. package/templates/base/src/components/preset-generator.tsx +0 -14
  84. package/templates/base/src/components/sidebar-toggle.tsx +0 -6
  85. package/templates/base/src/components/sidebar-tree.tsx +0 -6
  86. package/templates/base/src/config/color-scheme-utils.ts +0 -69
  87. package/templates/base/src/config/color-schemes.ts +0 -165
  88. package/templates/base/src/config/docs-schema.ts +0 -95
  89. package/templates/base/src/config/frontmatter-preview-defaults.ts +0 -27
  90. package/templates/base/src/config/frontmatter-preview-renderers.tsx +0 -46
  91. package/templates/base/src/config/i18n.ts +0 -239
  92. package/templates/base/src/config/settings-types.ts +0 -45
  93. package/templates/base/src/config/sidebars.ts +0 -66
  94. package/templates/base/src/config/tag-vocabulary-types.ts +0 -4
  95. package/templates/base/src/config/tag-vocabulary.ts +0 -20
  96. package/templates/base/src/config/z-index-tokens.ts +0 -128
  97. package/templates/base/src/types/docs-entry.ts +0 -28
  98. package/templates/base/src/types/heading.ts +0 -5
  99. package/templates/base/src/types/locale.ts +0 -10
  100. package/templates/base/src/utils/base.ts +0 -164
  101. package/templates/base/src/utils/docs.ts +0 -446
  102. package/templates/base/src/utils/git-info.ts +0 -70
  103. package/templates/base/src/utils/github.ts +0 -22
  104. package/templates/base/src/utils/nav-scope.ts +0 -34
  105. package/templates/base/src/utils/sidebar.ts +0 -36
  106. package/templates/base/src/utils/slug.ts +0 -10
  107. package/templates/base/src/utils/smart-break.tsx +0 -12
  108. package/templates/base/src/utils/tags.ts +0 -83
  109. package/templates/base/zfb-shim.d.ts +0 -178
  110. package/templates/features/bodyFootUtil/files/src/utils/github.ts +0 -22
  111. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +0 -42
  112. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +0 -752
  113. package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +0 -97
  114. package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +0 -735
  115. package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +0 -15
  116. package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +0 -435
  117. package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +0 -174
  118. package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +0 -30
  119. package/templates/features/docHistory/files/src/components/doc-history.tsx +0 -10
  120. package/templates/features/docHistory/files/src/types/doc-history.ts +0 -7
  121. package/templates/features/dynamicPageTransition/files/src/components/client-router-bootstrap.tsx +0 -72
  122. package/templates/features/i18n/files/pages/[locale]/index.tsx +0 -72
  123. package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +0 -11
  124. package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +0 -6
  125. package/templates/features/tauri/files/src/components/find-bar.tsx +0 -122
  126. package/templates/features/tauri/files/src/components/find-in-page-init.tsx +0 -59
  127. package/templates/features/tauri/files/src/utils/find-in-page.ts +0 -175
package/dist/scaffold.js CHANGED
@@ -1,28 +1,34 @@
1
1
  import fs from "fs-extra";
2
2
  import path from "path";
3
3
  import { fileURLToPath } from "url";
4
- import { generateSettingsFile } from "./settings-gen.js";
5
4
  import { generateZfbConfig } from "./zfb-config-gen.js";
6
5
  import { generateCLAUDEFile } from "./claude-md-gen.js";
7
6
  import { composeFeatures } from "./compose.js";
8
7
  import { featureModules } from "./features/index.js";
9
- import { capitalize, getSecondaryLang } from "./utils.js";
8
+ import { capitalize, getSecondaryLang, pmRunCommand } from "./utils.js";
10
9
  export { getSecondaryLang };
11
10
  /**
12
- * Pinned `@takazudo/zudo-doc` version used in both `generatePackageJson()`
13
- * and the `.zudo-doc.json` seed written by `scaffold()`. Hoisted as a shared
14
- * constant so the dep pin and the provenance seed can never drift.
11
+ * Pinned `@takazudo/zudo-doc` version used by `generatePackageJson()`.
12
+ * Hoisted as a shared constant (kept even though it now has a single
13
+ * call site) because `scripts/check-pin-parity.mjs` resolves this exact
14
+ * declaration below via its constant-reference regex form (see that
15
+ * script's `readScaffoldPin()`) — keep the declaration line's shape
16
+ * parseable (const name, `=`, a quoted literal) and do NOT repeat that
17
+ * exact pattern anywhere earlier in this file (a comment containing the
18
+ * literal text would false-match the same regex, since it isn't anchored
19
+ * to a real `export const` statement).
15
20
  *
16
- * Strip the caret from this string to get the bare version for provenance:
17
- * ZUDO_DOC_PIN.replace(/^\^/, "") → "1.0.0"
21
+ * `.zudo-doc.json` is NO LONGER seeded here (locked decision #2653 #6
22
+ * lazy-create on first `zudo-doc eject`; `packages/zudo-doc/src/eject/index.ts`
23
+ * already tolerates its absence and writes the file on first successful eject).
18
24
  *
19
25
  * Bumped in lockstep by scripts/release-create-zudo-doc.sh.
20
26
  */
21
- export const ZUDO_DOC_PIN = "^3.1.0";
27
+ export const ZUDO_DOC_PIN = "^3.3.0";
22
28
  /**
23
- * Files in `templates/base/**` that must never be copied into a generated
24
- * project. Each entry is matched against the path relative to `templates/base/`
25
- * (POSIX-style, forward slashes).
29
+ * Files in `templates/base/**` that must not be copied by the unconditional
30
+ * base mirror. Each entry is matched against the path relative to
31
+ * `templates/base/` (POSIX-style, forward slashes).
26
32
  *
27
33
  * W2 spec-lock Decision 5 (#1728) — `pages/api/**` is worker-only SSR
28
34
  * (uses `@takazudo/zfb-adapter-cloudflare`, `prerender = false`) and is
@@ -32,6 +38,7 @@ export const ZUDO_DOC_PIN = "^3.1.0";
32
38
  */
33
39
  const EXCLUDE_FROM_MIRROR = [
34
40
  /^pages\/api(\/|$)/,
41
+ /^scripts\/setup-doc-skill\.sh$/,
35
42
  ];
36
43
  /**
37
44
  * `fs.copy` filter for the `templates/base/` → target-dir copy. Returns
@@ -106,7 +113,7 @@ sidebar_position: 2
106
113
 
107
114
  ## Requirements
108
115
 
109
- - Node.js 18 or later
116
+ - Node.js 22 or later
110
117
  - pnpm (recommended), npm, yarn, or bun
111
118
 
112
119
  ## Create a New Project
@@ -134,7 +141,7 @@ sidebar_position: 2
134
141
 
135
142
  ## 動作要件
136
143
 
137
- - Node.js 18 以降
144
+ - Node.js 22 以降
138
145
  - pnpm(推奨)、npm、yarn、または bun
139
146
 
140
147
  ## 新しいプロジェクトを作成する
@@ -201,7 +208,7 @@ export async function scaffold(choices) {
201
208
  const templatesDir = path.join(pkgRoot, "templates");
202
209
  const baseDir = path.join(templatesDir, "base");
203
210
  const featuresDir = path.join(templatesDir, "features");
204
- // For skillSymlinker, we still need the monorepo root for the script
211
+ // Still needed for source-checkout-only assets such as Claude skills.
205
212
  const monorepoRoot = path.resolve(pkgRoot, "../..");
206
213
  await fs.ensureDir(targetDir);
207
214
  // 1. Copy base template
@@ -214,11 +221,9 @@ export async function scaffold(choices) {
214
221
  });
215
222
  // 2. Copy skill symlinker script when enabled
216
223
  if (choices.features.includes("skillSymlinker")) {
217
- const scriptSrc = path.join(monorepoRoot, "scripts/setup-doc-skill.sh");
224
+ const scriptSrc = path.join(baseDir, "scripts/setup-doc-skill.sh");
218
225
  const scriptDest = path.join(targetDir, "scripts/setup-doc-skill.sh");
219
- if (await fs.pathExists(scriptSrc)) {
220
- await fs.copy(scriptSrc, scriptDest);
221
- }
226
+ await fs.copy(scriptSrc, scriptDest);
222
227
  }
223
228
  // 2b. Copy user-facing Claude Code skills when enabled
224
229
  // Ships the curated zudo-doc-* skills (design-system, translate, version-bump)
@@ -284,21 +289,17 @@ export async function scaffold(choices) {
284
289
  await fs.outputFile(path.join(targetDir, `src/content/docs-${secondaryLang}/changelog/index.mdx`), secondaryChangelogContent);
285
290
  }
286
291
  }
287
- // 3. Generate programmatic files
288
- const settingsContent = generateSettingsFile(choices);
289
- await fs.outputFile(path.join(targetDir, "src/config/settings.ts"), settingsContent);
292
+ // 3. Generate the one config file. There is no more src/config/settings.ts —
293
+ // every user choice rides straight into zudoDoc({...}) in zfb.config.ts
294
+ // (locked decision #2653 #2 — diff-from-defaults single config).
290
295
  const zfbConfigContent = generateZfbConfig(choices);
291
296
  await fs.outputFile(path.join(targetDir, "zfb.config.ts"), zfbConfigContent);
292
297
  const pkg = generatePackageJson(choices);
293
298
  await fs.outputFile(path.join(targetDir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
294
- // Seed .zudo-doc.json provenance marker for `zudo-doc eject <component>`.
295
- // packageVersion is the bare version string (caret stripped from ZUDO_DOC_PIN)
296
- // so it records the concrete version the scaffold targets; the eject CLI
297
- // records the actually-installed version on first eject.
298
- await fs.outputFile(path.join(targetDir, ".zudo-doc.json"), JSON.stringify({
299
- packageVersion: ZUDO_DOC_PIN.replace(/^\^/, ""),
300
- ejected: {},
301
- }, null, 2) + "\n");
299
+ // .zudo-doc.json is intentionally NOT seeded (locked decision #2653 #6 —
300
+ // lazy-create on first `zudo-doc eject`). `packages/zudo-doc/src/eject/index.ts`
301
+ // already tolerates its absence (defaults to `{ packageVersion: "unknown",
302
+ // ejected: {} }`) and writes the file itself on first successful eject.
302
303
  const gitignoreLines = [
303
304
  "# Build output",
304
305
  "node_modules",
@@ -364,8 +365,10 @@ export async function scaffold(choices) {
364
365
  }
365
366
  function generatePackageJson(choices) {
366
367
  // Intentionally absent from scaffolded deps:
367
- // @takazudo/zudo-doc-md-plugins — private fixture/parity-test asset; not published,
368
- // not for app import. Zero references in generator templates/source.
368
+ // @takazudo/zudo-doc-md-plugins — the legacy JS remark/rehype pipeline it
369
+ // would have named was retired outright (packages/md-plugins/ deleted,
370
+ // #2683); its parity coverage lives in e2e/smoke-markdown-features.spec.ts.
371
+ // Zero references in generator templates/source.
369
372
  const deps = {
370
373
  // zfb engine — distributed as published npm packages (the prebuilt binary
371
374
  // ships via an optionalDependency of @takazudo/zfb-<platform>); pinned to
@@ -497,14 +500,15 @@ function generatePackageJson(choices) {
497
500
  // pins. No consumer-facing / CLI change.
498
501
  // next.76: routine toolchain bump from next.75, adopted in
499
502
  // lockstep with the root package.json pins. No consumer-facing / CLI change.
500
- // next.77 (current pin): router persistence/history fixes and runtime
501
- // island remount support, adopted in lockstep with the root package.json
502
- // pins. No scaffold API change.
503
- "@takazudo/zfb": "0.1.0-next.77",
504
- "@takazudo/zfb-runtime": "0.1.0-next.77",
503
+ // next.77: router persistence/history fixes and runtime island remount
504
+ // support, adopted in lockstep with the root package.json pins. No
505
+ // scaffold API change. next.78 (current pin): production HTML minification
506
+ // support via minifyHtml, adopted as a zudo-doc default through settings.
507
+ "@takazudo/zfb": "0.1.0-next.78",
508
+ "@takazudo/zfb-runtime": "0.1.0-next.78",
505
509
  // zfb-adapter-cloudflare — required for any route with `prerender = false`.
506
510
  // Pinned in lockstep with @takazudo/zfb.
507
- "@takazudo/zfb-adapter-cloudflare": "0.1.0-next.77",
511
+ "@takazudo/zfb-adapter-cloudflare": "0.1.0-next.78",
508
512
  // @takazudo/zudo-doc — published from this monorepo via
509
513
  // .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
510
514
  // lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
@@ -564,6 +568,26 @@ function generatePackageJson(choices) {
564
568
  // missing copy produces no `pnpm install` warning — which is why this gap
565
569
  // shipped silently and only surfaced at build time.
566
570
  diff: "^8.0.3",
571
+ // @takazudo/zdtp — SAME "unconditional at build time despite being an
572
+ // optional peer" class as `diff` above, discovered empirically while
573
+ // verifying this generator's own barebone (designTokenPanel: OFF) output
574
+ // (epic zudolab/zudo-doc#2651, #2660 self-review — a genuine package-level
575
+ // coupling, not a generator bug; flagged loudly on #2660's completion
576
+ // comment for a package-side follow-up). Since the #2658 gate-2 fix,
577
+ // `chrome/derive.tsx`'s `deriveBodyEndIslands` statically imports the REAL
578
+ // `DesignTokenPanelBootstrap` as the default for EVERY `createChrome`
579
+ // consumer (so the island auto-mounts with zero host wiring when the
580
+ // setting is on) — and that component imports `@takazudo/zdtp` at module
581
+ // scope. So every page that goes through `createChrome` — which is every
582
+ // page in this project — pulls the zdtp import into the esbuild bundle
583
+ // graph, `designTokenPanel` setting or not; only RENDERING is gated on
584
+ // the setting, not the import. Without this dep, `zfb build` fails with
585
+ // "Could not resolve '@takazudo/zdtp'" even on a fully barebone project.
586
+ // `preact ^10.29.1` (see the floor comment above) is required for the
587
+ // same reason. This is the ACCEPTED, permanent contract per #2668 — see
588
+ // the "@takazudo/zdtp dep implication" note in
589
+ // packages/zudo-doc/docs/adr/route-injection-seam.md.
590
+ "@takazudo/zdtp": "0.4.6",
567
591
  };
568
592
  const devDeps = {
569
593
  "@tailwindcss/vite": "^4.2.0",
@@ -571,7 +595,8 @@ function generatePackageJson(choices) {
571
595
  typescript: "^5.9.0",
572
596
  "@types/node": "^22.0.0",
573
597
  "@types/react": "^19.2.0", // needed for preact/compat type resolution
574
- "html-validate": "^10.0.0",
598
+ // html-validate dropped — check:html is no longer a default script
599
+ // (see the scripts block below; `.htmlvalidate.json` no longer ships).
575
600
  };
576
601
  if (choices.features.includes("search")) {
577
602
  deps["minisearch"] = "^7.2.0";
@@ -587,7 +612,7 @@ function generatePackageJson(choices) {
587
612
  // @takazudo/zudo-doc/integrations/doc-history which in turn imports
588
613
  // @takazudo/zudo-doc-history-server/git-history. Without this dep the
589
614
  // plugin host fails at init with ERR_MODULE_NOT_FOUND — W8A (#1739).
590
- deps["@takazudo/zudo-doc-history-server"] = "^3.1.0";
615
+ deps["@takazudo/zudo-doc-history-server"] = "^3.3.0";
591
616
  // tsx is no longer needed here: the relocated package plugin imports the
592
617
  // runner directly (no `tsx -e` spawn) since the package ships compiled
593
618
  // dist/ — package-first migration #2321 (#2337).
@@ -595,11 +620,6 @@ function generatePackageJson(choices) {
595
620
  // claudeResources: tsx is no longer needed. The relocated package plugin
596
621
  // (@takazudo/zudo-doc/plugins/claude-resources) imports the runner directly
597
622
  // since the package ships compiled dist/ — package-first migration #2321 (#2337).
598
- if (choices.features.includes("designTokenPanel")) {
599
- // @takazudo/zdtp requires preact >= 10.29.1 — see the preact floor comment
600
- // above (~line 382) for why the floor is set there and the coupling this creates.
601
- deps["@takazudo/zdtp"] = "0.4.5";
602
- }
603
623
  if (choices.features.includes("tagGovernance")) {
604
624
  // gray-matter is already in `deps` unconditionally (base template uses it),
605
625
  // so we only add the tooling deps specific to tags:audit / tags:suggest.
@@ -611,23 +631,19 @@ function generatePackageJson(choices) {
611
631
  devDeps["@inquirer/prompts"] = "^8.4.2";
612
632
  devDeps["tsx"] = "^4.21.0";
613
633
  }
634
+ // check:html and gen:z-index/check:z-index are DROPPED from the default
635
+ // scaffold (locked decision, epic #2651 #2660 work item 6):
636
+ // - `.htmlvalidate.json` no longer ships — html-validate becomes an
637
+ // opt-in extend step (documented in #2664).
638
+ // - z-index tokens ship unconditionally from `@takazudo/zudo-doc/theme.css`
639
+ // (13 default tiers, epic #2655) — a project only needs its own
640
+ // `src/config/z-index-tokens.ts` + codegen scripts when it overrides a
641
+ // tier, which is an eject-time decision, not a scaffold-time one.
614
642
  const scripts = {
615
643
  dev: "zfb dev",
616
644
  build: "zfb build",
617
645
  preview: "zfb preview",
618
646
  check: "zfb check",
619
- // NOTE: no `check:pages` here — the host repo's pages/ typecheck
620
- // (tsconfig.pages.json, #2018) is host-only for now. The base template's
621
- // no-op feature stubs (e.g. doc-history.tsx) are not type-clean against
622
- // the pages/lib call sites, so emitting the script would fail on a fresh
623
- // scaffold. Revisit once the template stubs carry typed props.
624
- "check:html": "html-validate \"dist/**/*.html\"",
625
- // Z-index token codegen (#2148): regenerate the GENERATED:Z_INDEX @theme
626
- // block in src/styles/global.css from src/config/z-index-tokens.ts, and a
627
- // drift check for pre-push/CI. Both ship in base — the z-index token system
628
- // is part of every scaffold. Bin provided by @takazudo/zudo-doc (S9b #2334).
629
- "gen:z-index": "gen-z-index",
630
- "check:z-index": "gen-z-index --check",
631
647
  };
632
648
  if (choices.features.includes("tagGovernance")) {
633
649
  // tags-audit bin is provided by @takazudo/zudo-doc (S9b #2334);
@@ -647,17 +663,17 @@ function generatePackageJson(choices) {
647
663
  scripts["setup:doc-skill:both"] =
648
664
  "bash scripts/setup-doc-skill.sh --target both";
649
665
  }
650
- const runCmd = choices.packageManager === "npm" || choices.packageManager === "bun" ? `${choices.packageManager} run` : choices.packageManager;
666
+ const pm = choices.packageManager;
651
667
  // claudeSkills ships the zudo-doc-version-bump skill, whose release workflow
652
668
  // calls `<pm> b4push`. Emit a minimal stub so the skill does not hit a
653
669
  // "script not found" error on freshly scaffolded projects. Consumers are
654
670
  // free to expand this into a richer pre-push pipeline later.
655
671
  if (choices.features.includes("claudeSkills")) {
656
- scripts["b4push"] = `${runCmd} check && ${runCmd} build`;
672
+ scripts["b4push"] = `${pmRunCommand(pm, "check")} && ${pmRunCommand(pm, "build")}`;
657
673
  }
658
674
  if (choices.features.includes("tauri")) {
659
675
  scripts["dev:tauri"] = "cargo tauri dev";
660
- scripts["build:tauri"] = `${runCmd} build && cargo tauri build`;
676
+ scripts["build:tauri"] = `${pmRunCommand(pm, "build")} && cargo tauri build`;
661
677
  }
662
678
  if (choices.features.includes("tauriDev")) {
663
679
  scripts["dev:tauri-dev"] = "cd src-tauri-dev && cargo tauri dev";
@@ -668,6 +684,9 @@ function generatePackageJson(choices) {
668
684
  version: "0.0.1",
669
685
  private: true,
670
686
  type: "module",
687
+ // @takazudo/zfb + @takazudo/zfb-runtime declare engines.node ">=22.0.0";
688
+ // emit the floor so `<pm> install` warns early on an unsupported Node.
689
+ engines: { node: ">=22" },
671
690
  scripts,
672
691
  dependencies: deps,
673
692
  devDependencies: devDeps,
package/dist/utils.d.ts CHANGED
@@ -37,6 +37,16 @@ export declare function initGitRepo(dir: string): GitInitResult;
37
37
  export declare function capitalize(str: string): string;
38
38
  /** Get a short uppercase label for a language code (e.g. "en" → "EN", "zh-cn" → "ZH-CN"). */
39
39
  export declare function getLangLabel(langCode: string): string;
40
+ /**
41
+ * Build the command that runs a package.json script under `pm`.
42
+ *
43
+ * npm and bun BOTH require the `run` verb — `bun build` invokes Bun's bundler,
44
+ * NOT the package.json `build` script (a real footgun), so bun must emit
45
+ * `bun run build`. pnpm and yarn accept the bare script name (`pnpm build`).
46
+ * The single source of truth for this rule across claude-md-gen.ts,
47
+ * scaffold.ts, and features/tauri.ts.
48
+ */
49
+ export declare function pmRunCommand(pm: "pnpm" | "npm" | "yarn" | "bun", script: string): string;
40
50
  /** Determine the secondary language code when i18n is enabled. */
41
51
  export declare function getSecondaryLang(defaultLang: string): string;
42
52
  /** Apply a list of regex replacements to a file (if it exists). */
package/dist/utils.js CHANGED
@@ -114,6 +114,20 @@ export function capitalize(str) {
114
114
  export function getLangLabel(langCode) {
115
115
  return langCode.toUpperCase();
116
116
  }
117
+ /**
118
+ * Build the command that runs a package.json script under `pm`.
119
+ *
120
+ * npm and bun BOTH require the `run` verb — `bun build` invokes Bun's bundler,
121
+ * NOT the package.json `build` script (a real footgun), so bun must emit
122
+ * `bun run build`. pnpm and yarn accept the bare script name (`pnpm build`).
123
+ * The single source of truth for this rule across claude-md-gen.ts,
124
+ * scaffold.ts, and features/tauri.ts.
125
+ */
126
+ export function pmRunCommand(pm, script) {
127
+ return pm === "npm" || pm === "bun"
128
+ ? `${pm} run ${script}`
129
+ : `${pm} ${script}`;
130
+ }
117
131
  /** Determine the secondary language code when i18n is enabled. */
118
132
  export function getSecondaryLang(defaultLang) {
119
133
  return defaultLang === "en" ? "ja" : "en";
@@ -1,25 +1,37 @@
1
1
  import type { UserChoices } from "./prompts.js";
2
2
  /**
3
- * Programmatically generate zfb.config.ts from user choices.
3
+ * Programmatically generate the ONE `zfb.config.ts` a scaffolded project
4
+ * ships (epic zudolab/zudo-doc#2651, minimal-scaffold Wave 6 #2660).
4
5
  *
5
- * S5b (#2329): collapsed to the thin preset-based shape that mirrors the
6
- * showcase `zfb.config.ts` after S5a. All collection wiring, plugin
7
- * descriptors, markdown features, codeHighlight, resolveMarkdownLinks, and
8
- * trailingSlash are now owned by `zudoDocPreset()` in
9
- * `@takazudo/zudo-doc/preset`. The generated config spreads the preset
10
- * result into `defineConfig` and keeps only the project-owned shell fields
11
- * (`framework`, `port`, `tailwind`, `base`).
6
+ * Replaces the former `settings-gen.ts` + `zfb-config-gen.ts` pair: there is
7
+ * no more `src/config/settings.ts` every user choice becomes a field
8
+ * passed straight into `zudoDoc({ ... })` (`@takazudo/zudo-doc/config`),
9
+ * which merges it over the package's own documented defaults and returns a
10
+ * complete `ZfbConfig`.
12
11
  *
13
- * Replaces the former astro-config-gen.ts + content-config-gen.ts pair.
14
- * In the zfb world, content-collection schemas live inside zfb.config.ts
15
- * itself there is no separate content.config.ts.
16
- *
17
- * `_choices` is intentionally unused: post-S5b the emitted config is a
18
- * CONSTANT. All feature variation is driven by `settings.*` (read at
19
- * zfb-load time inside `zudoDocPreset()`), so the generated file is byte
20
- * identical for every feature combination. The parameter is retained only
21
- * for call-site compatibility (`scaffold.ts` passes `choices`). Do NOT add
22
- * feature-gated branches here wire new feature behaviour into
23
- * `packages/zudo-doc/src/preset.ts` and the project's `settings.ts` instead.
12
+ * DIFF-FROM-DEFAULTS (locked, #2653 Decision 2): only fields whose resolved
13
+ * value differs from the matching `ZudoDocConfig` `@default` are emitted
14
+ * `siteName` is the one field always emitted. `DEFAULT_MIRROR` below is a
15
+ * hand-kept copy of `packages/zudo-doc/src/config.ts`'s `DEFAULT_SETTINGS`
16
+ * for exactly the fields this generator ever sets. It has to be a local
17
+ * mirror (not an import) because `create-zudo-doc` does not depend on
18
+ * `@takazudo/zudo-doc` at generator-build time the package is only ever a
19
+ * runtime dependency of the SCAFFOLDED project, never of the generator
20
+ * itself. Keep this mirror in sync by hand whenever `DEFAULT_SETTINGS`
21
+ * changes for one of the fields listed here.
22
+ */
23
+ export declare const DEFAULT_MIRROR: Record<string, unknown>;
24
+ /**
25
+ * Deterministic emission order for the keys of a `desired` config object:
26
+ * the keys present in `FIELD_ORDER` first (cosmetic reference order), then any
27
+ * leftover keys NOT in `FIELD_ORDER` appended in ALPHABETICAL order. The
28
+ * leftover branch exists so a key `buildDesiredConfig()` produces but nobody
29
+ * added to `FIELD_ORDER` is still emitted (deterministically) rather than
30
+ * silently dropped — matching what the `FIELD_ORDER` comment promises.
31
+ */
32
+ export declare function orderDesiredKeys(desiredKeys: readonly string[]): string[];
33
+ /**
34
+ * Generate the full `zfb.config.ts` source: `defineConfig(zudoDoc({ ... }))`
35
+ * with only the diff-from-defaults fields.
24
36
  */
25
- export declare function generateZfbConfig(_choices: UserChoices): string;
37
+ export declare function generateZfbConfig(choices: UserChoices): string;