create-zudo-doc 0.1.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 (212) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/bin/create-zudo-doc.js +2 -0
  4. package/dist/api.d.ts +20 -0
  5. package/dist/api.js +13 -0
  6. package/dist/claude-md-gen.d.ts +2 -0
  7. package/dist/claude-md-gen.js +113 -0
  8. package/dist/cli.d.ts +39 -0
  9. package/dist/cli.js +157 -0
  10. package/dist/compose.d.ts +95 -0
  11. package/dist/compose.js +206 -0
  12. package/dist/constants.d.ts +20 -0
  13. package/dist/constants.js +224 -0
  14. package/dist/features/body-foot-util.d.ts +10 -0
  15. package/dist/features/body-foot-util.js +12 -0
  16. package/dist/features/claude-resources.d.ts +2 -0
  17. package/dist/features/claude-resources.js +6 -0
  18. package/dist/features/design-token-panel.d.ts +14 -0
  19. package/dist/features/design-token-panel.js +27 -0
  20. package/dist/features/doc-history.d.ts +9 -0
  21. package/dist/features/doc-history.js +11 -0
  22. package/dist/features/doc-tags.d.ts +19 -0
  23. package/dist/features/doc-tags.js +33 -0
  24. package/dist/features/footer-taglist.d.ts +14 -0
  25. package/dist/features/footer-taglist.js +17 -0
  26. package/dist/features/footer.d.ts +8 -0
  27. package/dist/features/footer.js +10 -0
  28. package/dist/features/i18n.d.ts +22 -0
  29. package/dist/features/i18n.js +41 -0
  30. package/dist/features/image-enlarge.d.ts +11 -0
  31. package/dist/features/image-enlarge.js +13 -0
  32. package/dist/features/index.d.ts +15 -0
  33. package/dist/features/index.js +53 -0
  34. package/dist/features/llms-txt.d.ts +11 -0
  35. package/dist/features/llms-txt.js +13 -0
  36. package/dist/features/search.d.ts +9 -0
  37. package/dist/features/search.js +11 -0
  38. package/dist/features/sidebar-resizer.d.ts +14 -0
  39. package/dist/features/sidebar-resizer.js +16 -0
  40. package/dist/features/sidebar-toggle.d.ts +13 -0
  41. package/dist/features/sidebar-toggle.js +15 -0
  42. package/dist/features/tag-governance.d.ts +14 -0
  43. package/dist/features/tag-governance.js +16 -0
  44. package/dist/features/tauri-dev.d.ts +2 -0
  45. package/dist/features/tauri-dev.js +25 -0
  46. package/dist/features/tauri.d.ts +11 -0
  47. package/dist/features/tauri.js +52 -0
  48. package/dist/features/versioning.d.ts +27 -0
  49. package/dist/features/versioning.js +43 -0
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +150 -0
  52. package/dist/preset.d.ts +37 -0
  53. package/dist/preset.js +156 -0
  54. package/dist/prompts.d.ts +32 -0
  55. package/dist/prompts.js +248 -0
  56. package/dist/scaffold.d.ts +4 -0
  57. package/dist/scaffold.js +344 -0
  58. package/dist/settings-gen.d.ts +2 -0
  59. package/dist/settings-gen.js +237 -0
  60. package/dist/utils.d.ts +8 -0
  61. package/dist/utils.js +34 -0
  62. package/dist/zfb-config-gen.d.ts +19 -0
  63. package/dist/zfb-config-gen.js +222 -0
  64. package/package.json +65 -0
  65. package/templates/base/.htmlvalidate.json +5 -0
  66. package/templates/base/.zfb/doc-history-meta.json +1 -0
  67. package/templates/base/pages/404.tsx +55 -0
  68. package/templates/base/pages/_data.ts +179 -0
  69. package/templates/base/pages/_mdx-components.ts +249 -0
  70. package/templates/base/pages/docs/[...slug].tsx +448 -0
  71. package/templates/base/pages/index.tsx +158 -0
  72. package/templates/base/pages/lib/_body-end-islands.tsx +201 -0
  73. package/templates/base/pages/lib/_category-nav.tsx +148 -0
  74. package/templates/base/pages/lib/_category-tree-nav.tsx +104 -0
  75. package/templates/base/pages/lib/_compose-meta-title.ts +29 -0
  76. package/templates/base/pages/lib/_details.tsx +30 -0
  77. package/templates/base/pages/lib/_doc-history-area.tsx +178 -0
  78. package/templates/base/pages/lib/_doc-metainfo-area.tsx +100 -0
  79. package/templates/base/pages/lib/_doc-tags-area.tsx +89 -0
  80. package/templates/base/pages/lib/_extract-headings.ts +81 -0
  81. package/templates/base/pages/lib/_footer-with-defaults.tsx +234 -0
  82. package/templates/base/pages/lib/_frontmatter-preview-data.ts +53 -0
  83. package/templates/base/pages/lib/_head-with-defaults.tsx +113 -0
  84. package/templates/base/pages/lib/_header-with-defaults.tsx +386 -0
  85. package/templates/base/pages/lib/_inline-version-switcher.tsx +84 -0
  86. package/templates/base/pages/lib/_math-block.tsx +63 -0
  87. package/templates/base/pages/lib/_nav-source-docs.ts +68 -0
  88. package/templates/base/pages/lib/_preset-generator.tsx +81 -0
  89. package/templates/base/pages/lib/_search-widget-script.ts +388 -0
  90. package/templates/base/pages/lib/_search-widget.tsx +196 -0
  91. package/templates/base/pages/lib/_sidebar-with-defaults.tsx +176 -0
  92. package/templates/base/pages/lib/_site-tree-nav.tsx +128 -0
  93. package/templates/base/pages/lib/locale-merge.ts +58 -0
  94. package/templates/base/pages/lib/route-enumerators.ts +302 -0
  95. package/templates/base/pages/sitemap.xml.tsx +51 -0
  96. package/templates/base/plugins/connect-adapter.mjs +144 -0
  97. package/templates/base/plugins/copy-public-plugin.mjs +50 -0
  98. package/templates/base/plugins/search-index-plugin.mjs +54 -0
  99. package/templates/base/scripts/run-b4push.sh +102 -0
  100. package/templates/base/src/components/ai-chat-modal.tsx +15 -0
  101. package/templates/base/src/components/client-router-bootstrap.tsx +14 -0
  102. package/templates/base/src/components/content/component-map.ts +25 -0
  103. package/templates/base/src/components/content/content-blockquote.tsx +16 -0
  104. package/templates/base/src/components/content/content-code.tsx +117 -0
  105. package/templates/base/src/components/content/content-link.tsx +83 -0
  106. package/templates/base/src/components/content/content-ol.tsx +19 -0
  107. package/templates/base/src/components/content/content-paragraph.tsx +10 -0
  108. package/templates/base/src/components/content/content-strong.tsx +16 -0
  109. package/templates/base/src/components/content/content-table.tsx +18 -0
  110. package/templates/base/src/components/content/content-ul.tsx +18 -0
  111. package/templates/base/src/components/content/heading-h2.tsx +26 -0
  112. package/templates/base/src/components/content/heading-h3.tsx +26 -0
  113. package/templates/base/src/components/content/heading-h4.tsx +26 -0
  114. package/templates/base/src/components/design-token-panel-bootstrap.tsx +15 -0
  115. package/templates/base/src/components/desktop-sidebar-toggle.tsx +15 -0
  116. package/templates/base/src/components/doc-history.tsx +18 -0
  117. package/templates/base/src/components/html-preview/highlighted-code.tsx +74 -0
  118. package/templates/base/src/components/html-preview/html-preview.tsx +108 -0
  119. package/templates/base/src/components/html-preview/preflight.ts +112 -0
  120. package/templates/base/src/components/html-preview/preview-base.tsx +159 -0
  121. package/templates/base/src/components/image-enlarge.tsx +19 -0
  122. package/templates/base/src/components/mobile-toc.tsx +94 -0
  123. package/templates/base/src/components/preset-generator.tsx +14 -0
  124. package/templates/base/src/components/sidebar-toggle.tsx +98 -0
  125. package/templates/base/src/components/sidebar-tree.tsx +543 -0
  126. package/templates/base/src/components/site-tree-nav.tsx +233 -0
  127. package/templates/base/src/components/theme-toggle.tsx +93 -0
  128. package/templates/base/src/components/toc.tsx +63 -0
  129. package/templates/base/src/components/tree-nav-shared.tsx +71 -0
  130. package/templates/base/src/config/color-scheme-utils.ts +182 -0
  131. package/templates/base/src/config/color-schemes.ts +128 -0
  132. package/templates/base/src/config/frontmatter-preview-defaults.ts +24 -0
  133. package/templates/base/src/config/frontmatter-preview-renderers.tsx +46 -0
  134. package/templates/base/src/config/i18n.ts +225 -0
  135. package/templates/base/src/config/settings-types.ts +162 -0
  136. package/templates/base/src/config/sidebars.ts +66 -0
  137. package/templates/base/src/config/tag-vocabulary-types.ts +39 -0
  138. package/templates/base/src/config/tag-vocabulary.ts +20 -0
  139. package/templates/base/src/hooks/use-active-heading.ts +133 -0
  140. package/templates/base/src/plugins/docs-source-map.ts +103 -0
  141. package/templates/base/src/plugins/hast-utils.ts +10 -0
  142. package/templates/base/src/plugins/rehype-code-title.ts +50 -0
  143. package/templates/base/src/plugins/rehype-heading-links.ts +53 -0
  144. package/templates/base/src/plugins/rehype-image-enlarge.ts +113 -0
  145. package/templates/base/src/plugins/rehype-mermaid.ts +41 -0
  146. package/templates/base/src/plugins/rehype-strip-md-extension.ts +58 -0
  147. package/templates/base/src/plugins/remark-admonitions.ts +99 -0
  148. package/templates/base/src/plugins/remark-resolve-markdown-links.ts +127 -0
  149. package/templates/base/src/plugins/url-utils.ts +4 -0
  150. package/templates/base/src/styles/global.css +1066 -0
  151. package/templates/base/src/types/docs-entry.ts +39 -0
  152. package/templates/base/src/types/heading.ts +5 -0
  153. package/templates/base/src/types/locale.ts +10 -0
  154. package/templates/base/src/utils/base.ts +139 -0
  155. package/templates/base/src/utils/content-files.ts +106 -0
  156. package/templates/base/src/utils/dedent.ts +24 -0
  157. package/templates/base/src/utils/docs.ts +335 -0
  158. package/templates/base/src/utils/git-info.ts +70 -0
  159. package/templates/base/src/utils/github.ts +19 -0
  160. package/templates/base/src/utils/header-right-items.ts +38 -0
  161. package/templates/base/src/utils/nav-scope.ts +63 -0
  162. package/templates/base/src/utils/sidebar.ts +104 -0
  163. package/templates/base/src/utils/slug.ts +10 -0
  164. package/templates/base/src/utils/smart-break.tsx +126 -0
  165. package/templates/base/src/utils/tags.ts +126 -0
  166. package/templates/base/tsconfig.json +36 -0
  167. package/templates/features/bodyFootUtil/files/src/utils/github.ts +19 -0
  168. package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +137 -0
  169. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +34 -0
  170. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +376 -0
  171. package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +93 -0
  172. package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +586 -0
  173. package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +15 -0
  174. package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +99 -0
  175. package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +177 -0
  176. package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +50 -0
  177. package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +99 -0
  178. package/templates/features/docHistory/files/src/components/doc-history.tsx +598 -0
  179. package/templates/features/docHistory/files/src/types/doc-history.ts +23 -0
  180. package/templates/features/docHistory/files/src/utils/doc-history.ts +180 -0
  181. package/templates/features/docTags/files/pages/[locale]/docs/tags/[tag].tsx +116 -0
  182. package/templates/features/docTags/files/pages/[locale]/docs/tags/index.tsx +99 -0
  183. package/templates/features/docTags/files/pages/docs/tags/[tag].tsx +101 -0
  184. package/templates/features/docTags/files/pages/docs/tags/index.tsx +86 -0
  185. package/templates/features/i18n/files/pages/[locale]/docs/[...slug].tsx +467 -0
  186. package/templates/features/i18n/files/pages/[locale]/index.tsx +213 -0
  187. package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +248 -0
  188. package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +74 -0
  189. package/templates/features/sidebarResizer/files/src/scripts/sidebar-resizer.ts +185 -0
  190. package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +126 -0
  191. package/templates/features/tagGovernance/files/scripts/tags-audit.ts +576 -0
  192. package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +428 -0
  193. package/templates/features/tauri/files/src/components/find-bar.tsx +122 -0
  194. package/templates/features/tauri/files/src/components/find-in-page-init.tsx +53 -0
  195. package/templates/features/tauri/files/src/utils/find-in-page.ts +175 -0
  196. package/templates/features/tauri/files/src-tauri/Cargo.toml +14 -0
  197. package/templates/features/tauri/files/src-tauri/build.rs +3 -0
  198. package/templates/features/tauri/files/src-tauri/capabilities/default.json +11 -0
  199. package/templates/features/tauri/files/src-tauri/src/main.rs +250 -0
  200. package/templates/features/tauri/files/src-tauri/tauri.conf.json +25 -0
  201. package/templates/features/tauriDev/files/src-tauri-dev/Cargo.toml +15 -0
  202. package/templates/features/tauriDev/files/src-tauri-dev/build.rs +3 -0
  203. package/templates/features/tauriDev/files/src-tauri-dev/capabilities/default.json +7 -0
  204. package/templates/features/tauriDev/files/src-tauri-dev/frontend/index.html +187 -0
  205. package/templates/features/tauriDev/files/src-tauri-dev/icons/icon.png +0 -0
  206. package/templates/features/tauriDev/files/src-tauri-dev/src/main.rs +995 -0
  207. package/templates/features/tauriDev/files/src-tauri-dev/tauri.conf.json +22 -0
  208. package/templates/features/tauriDev/files/src-tauri-dev/test-launch.sh +65 -0
  209. package/templates/features/versioning/files/pages/[locale]/docs/versions.tsx +100 -0
  210. package/templates/features/versioning/files/pages/docs/versions.tsx +78 -0
  211. package/templates/features/versioning/files/pages/v/[version]/docs/[...slug].tsx +451 -0
  212. package/templates/features/versioning/files/pages/v/[version]/ja/docs/[...slug].tsx +490 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Takeshi Takatsudo
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.
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # create-zudo-doc
2
+
3
+ Scaffold a new [zudo-doc](https://zudo-doc.takazudomodular.com) documentation site in seconds. Generates a ready-to-run project powered by [zfb](https://github.com/zudolab/zudo-doc), MDX, Tailwind CSS v4, and Preact — with optional features (search, i18n, sidebar, doc history, design token panel, and more).
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # pnpm
9
+ pnpm create zudo-doc
10
+
11
+ # npm
12
+ npm create zudo-doc@latest
13
+
14
+ # yarn
15
+ yarn create zudo-doc
16
+
17
+ # bun
18
+ bunx create-zudo-doc
19
+ ```
20
+
21
+ Running without arguments starts the **interactive mode**: the CLI prompts for project name, language, color scheme, and which optional features to enable, then scaffolds the project and optionally installs dependencies.
22
+
23
+ ## Non-Interactive Usage
24
+
25
+ Pass `--yes` to accept all defaults and skip prompts, or provide flags to pre-answer specific questions:
26
+
27
+ ```bash
28
+ # All defaults, no prompts
29
+ pnpm create zudo-doc my-docs --yes
30
+
31
+ # Fully specified, non-interactive
32
+ pnpm create zudo-doc my-docs \
33
+ --lang ja \
34
+ --scheme Dracula \
35
+ --no-i18n \
36
+ --search \
37
+ --pm pnpm \
38
+ --install
39
+ ```
40
+
41
+ ## Options
42
+
43
+ ### Project basics
44
+
45
+ | Flag | Description | Default |
46
+ |------|-------------|---------|
47
+ | `[project-name]` | Project name (positional arg or `--name`) | prompted |
48
+ | `--lang <code>` | Default language: `en`, `ja`, `zh-cn`, `zh-tw`, `ko`, `es`, `fr`, `de`, `pt` | `en` |
49
+ | `--pm <manager>` | Package manager: `pnpm`, `npm`, `yarn`, `bun` | detected |
50
+ | `--[no-]install` | Install dependencies after scaffolding | prompted |
51
+ | `-y, --yes` | Use defaults for all unspecified options, skip prompts | — |
52
+ | `-h, --help` | Show help | — |
53
+
54
+ ### Color scheme
55
+
56
+ | Flag | Description |
57
+ |------|-------------|
58
+ | `--color-scheme-mode <mode>` | `single` (one fixed scheme) or `light-dark` (OS-aware) |
59
+ | `--scheme <name>` | Color scheme name when using `single` mode |
60
+ | `--light-scheme <name>` | Light scheme when using `light-dark` mode |
61
+ | `--dark-scheme <name>` | Dark scheme when using `light-dark` mode |
62
+ | `--default-mode <mode>` | `light` or `dark` — initial mode in `light-dark` |
63
+ | `--[no-]respect-system-preference` | Follow OS color scheme preference |
64
+
65
+ ### Features
66
+
67
+ Each feature has a `--[no-]<flag>` form. Passing `--feature` enables it; `--no-feature` disables it; omitting the flag triggers the interactive prompt (or uses the default when `--yes` is set).
68
+
69
+ | Flag | Description | Default |
70
+ |------|-------------|---------|
71
+ | `--[no-]i18n` | Multi-language support (adds a secondary locale) | off |
72
+ | `--[no-]search` | Pagefind full-text search | on |
73
+ | `--[no-]sidebar-filter` | Real-time sidebar filter | on |
74
+ | `--[no-]image-enlarge` | Click-to-enlarge for oversized images | on |
75
+ | `--[no-]tag-governance` | Vocabulary-aware tag audit + suggest scripts | on |
76
+ | `--[no-]claude-resources` | Auto-generate Claude Code docs (`CLAUDE.md`, `llms.txt`) | off |
77
+ | `--[no-]claude-skills` | Ship zudo-doc Claude Code skills (design-system, translate, version-bump) | off |
78
+ | `--[no-]design-token-panel` | Interactive panel for tweaking spacing, font, color tokens | off |
79
+ | `--[no-]sidebar-resizer` | Draggable sidebar width handle | off |
80
+ | `--[no-]sidebar-toggle` | Show/hide desktop sidebar button | off |
81
+ | `--[no-]versioning` | Multi-version documentation support | off |
82
+ | `--[no-]doc-history` | Show per-page document edit history | off |
83
+ | `--[no-]body-foot-util` | Right-aligned strip below each doc (history trigger + GitHub source link) | off |
84
+ | `--[no-]llms-txt` | Generate `llms.txt` for LLM consumption | off |
85
+ | `--[no-]skill-symlinker` | Symlink documentation skills into `.claude/` | off |
86
+ | `--[no-]tauri` | Tauri desktop app — Mode 1 offline reader | off |
87
+ | `--[no-]tauri-dev` | Tauri dev wrapper — Mode 2 configurable dev wrapper | off |
88
+ | `--[no-]footer-nav-group` | Navigation links in the footer | off |
89
+ | `--[no-]footer-copyright` | Copyright notice in the footer | off |
90
+ | `--[no-]footer-taglist` | Grouped tag index in the footer (requires tag-governance) | off |
91
+ | `--[no-]changelog` | Changelog page | off |
92
+
93
+ ### Advanced
94
+
95
+ | Flag | Description |
96
+ |------|-------------|
97
+ | `--github-url <url>` | GitHub repository URL — drives header link and "View source" links |
98
+ | `--preset <path>` | Load all settings from a JSON file (use `-` for stdin) |
99
+
100
+ ## Examples
101
+
102
+ ```bash
103
+ # Japanese docs site with search and sidebar, using pnpm
104
+ pnpm create zudo-doc my-docs \
105
+ --lang ja \
106
+ --search \
107
+ --sidebar-filter \
108
+ --pm pnpm \
109
+ --install \
110
+ --yes
111
+
112
+ # Light/dark color scheme with Catppuccin pairings
113
+ pnpm create zudo-doc my-docs \
114
+ --color-scheme-mode light-dark \
115
+ --light-scheme "Catppuccin Latte" \
116
+ --dark-scheme "Catppuccin Mocha" \
117
+ --default-mode dark \
118
+ --yes
119
+
120
+ # Fully featured site from a preset file
121
+ pnpm create zudo-doc my-docs --preset ./my-preset.json --install
122
+ ```
123
+
124
+ ## Programmatic API
125
+
126
+ ```ts
127
+ import { createZudoDoc } from "create-zudo-doc";
128
+
129
+ await createZudoDoc({
130
+ projectName: "my-docs",
131
+ defaultLang: "en",
132
+ colorSchemeMode: "single",
133
+ singleScheme: "Dracula",
134
+ features: ["search", "sidebarFilter", "tagGovernance"],
135
+ packageManager: "pnpm",
136
+ install: true,
137
+ });
138
+ ```
139
+
140
+ ## Documentation
141
+
142
+ Full documentation at [zudo-doc.takazudomodular.com](https://zudo-doc.takazudomodular.com).
143
+
144
+ ## License
145
+
146
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../dist/index.js";
package/dist/api.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ export type { UserChoices } from "./prompts.js";
2
+ export interface CreateOptions {
3
+ projectName: string;
4
+ /** Default language code (default: "en") */
5
+ defaultLang?: string;
6
+ colorSchemeMode: "single" | "light-dark";
7
+ singleScheme?: string;
8
+ lightScheme?: string;
9
+ darkScheme?: string;
10
+ respectPrefersColorScheme?: boolean;
11
+ defaultMode?: "light" | "dark";
12
+ features: string[];
13
+ /** GitHub repository URL — drives the header GitHub link and body-foot
14
+ * "View source on GitHub" link. Empty = disabled. */
15
+ githubUrl?: string;
16
+ packageManager: "pnpm" | "npm" | "yarn" | "bun";
17
+ /** Install dependencies after scaffolding (default: false) */
18
+ install?: boolean;
19
+ }
20
+ export declare function createZudoDoc(options: CreateOptions): Promise<string>;
package/dist/api.js ADDED
@@ -0,0 +1,13 @@
1
+ import path from "path";
2
+ import { scaffold } from "./scaffold.js";
3
+ import { installDependencies } from "./utils.js";
4
+ export async function createZudoDoc(options) {
5
+ const { install = false, ...rest } = options;
6
+ const choices = { ...rest, defaultLang: rest.defaultLang ?? "en" };
7
+ await scaffold(choices);
8
+ const targetDir = path.resolve(process.cwd(), choices.projectName);
9
+ if (install) {
10
+ installDependencies(targetDir, choices.packageManager);
11
+ }
12
+ return targetDir;
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { UserChoices } from "./prompts.js";
2
+ export declare function generateCLAUDEFile(choices: UserChoices): string;
@@ -0,0 +1,113 @@
1
+ import { capitalize } from "./utils.js";
2
+ function runCmd(pm, script) {
3
+ if (pm === "npm")
4
+ return `npm run ${script}`;
5
+ return `${pm} ${script}`;
6
+ }
7
+ export function generateCLAUDEFile(choices) {
8
+ const siteName = capitalize(choices.projectName.replace(/-/g, " "));
9
+ const lines = [];
10
+ lines.push(`# ${siteName}`);
11
+ lines.push(``);
12
+ lines.push(`Documentation site built with [zudo-doc](https://github.com/zudolab/zudo-doc) — a zfb-based documentation framework with MDX, Tailwind CSS v4, and Preact islands.`);
13
+ lines.push(``);
14
+ // Tech stack
15
+ lines.push(`## Tech Stack`);
16
+ lines.push(``);
17
+ lines.push(`- **zfb** — documentation build framework`);
18
+ lines.push(`- **MDX** — content format`);
19
+ lines.push(`- **Tailwind CSS v4** — via \`@tailwindcss/vite\``);
20
+ lines.push(`- **Preact** — for interactive islands only (with compat mode for React API)`);
21
+ lines.push(`- **syntect** — built-in code highlighting, run by zfb's Rust pipeline at build time (single fixed theme: \`base16-ocean-dark\`)`);
22
+ lines.push(``);
23
+ // Commands
24
+ lines.push(`## Commands`);
25
+ lines.push(``);
26
+ const pm = choices.packageManager;
27
+ lines.push(`- \`${runCmd(pm, "dev")}\` — zfb dev server (port 4321)`);
28
+ lines.push(`- \`${runCmd(pm, "build")}\` — static HTML export to \`dist/\``);
29
+ lines.push(`- \`${runCmd(pm, "check")}\` — TypeScript type checking`);
30
+ lines.push(``);
31
+ // Key directories
32
+ lines.push(`## Key Directories`);
33
+ lines.push(``);
34
+ lines.push("```");
35
+ lines.push(`src/`);
36
+ lines.push(`├── components/ # JSX + Preact components`);
37
+ lines.push(`│ └── admonitions/ # Note, Tip, Info, Warning, Danger`);
38
+ lines.push(`├── config/ # Settings, color schemes`);
39
+ lines.push(`├── content/`);
40
+ lines.push(`│ └── docs/ # MDX content`);
41
+ if (choices.features.includes("i18n")) {
42
+ const secondaryLang = choices.defaultLang === "ja" ? "en" : "ja";
43
+ lines.push(`│ └── docs-${secondaryLang}/ # ${secondaryLang === "ja" ? "Japanese" : "English"} MDX content (mirrors docs/)`);
44
+ }
45
+ lines.push(`├── layouts/ # JSX layouts`);
46
+ lines.push(`├── pages/ # File-based routing`);
47
+ lines.push(`└── styles/`);
48
+ lines.push(` └── global.css # Design tokens & Tailwind config`);
49
+ lines.push("```");
50
+ lines.push(``);
51
+ // Content conventions
52
+ lines.push(`## Content Conventions`);
53
+ lines.push(``);
54
+ lines.push(`### Frontmatter`);
55
+ lines.push(``);
56
+ lines.push(`- Required: \`title\` (string)`);
57
+ lines.push(`- Optional: \`description\`, \`sidebar_position\` (number), \`category\``);
58
+ lines.push(`- Sidebar order is driven by \`sidebar_position\``);
59
+ lines.push(``);
60
+ lines.push(`### Admonitions`);
61
+ lines.push(``);
62
+ lines.push(`Available in all MDX files without imports: \`<Note>\`, \`<Tip>\`, \`<Info>\`, \`<Warning>\`, \`<Danger>\``);
63
+ lines.push(`Each accepts an optional \`title\` prop.`);
64
+ lines.push(``);
65
+ lines.push(`### Headings`);
66
+ lines.push(``);
67
+ lines.push(`Do NOT use h1 (\`#\`) in doc content — the page title from frontmatter is rendered as h1. Start content headings from h2 (\`##\`).`);
68
+ lines.push(``);
69
+ // Components
70
+ lines.push(`## Components`);
71
+ lines.push(``);
72
+ lines.push(`- Default to **server-rendered JSX components** (\`.tsx\`) — zero JS, server-rendered`);
73
+ lines.push(`- Use **Preact islands** (\`client:load\`) only when client-side interactivity is needed`);
74
+ lines.push(``);
75
+ // i18n section
76
+ if (choices.features.includes("i18n")) {
77
+ const secondaryLang = choices.defaultLang === "ja" ? "en" : "ja";
78
+ const defaultLabel = choices.defaultLang === "ja" ? "Japanese" : "English";
79
+ const secondaryLabel = secondaryLang === "ja" ? "Japanese" : "English";
80
+ lines.push(`## i18n`);
81
+ lines.push(``);
82
+ lines.push(`- ${defaultLabel} (default): \`/docs/...\` — content in \`src/content/docs/\``);
83
+ lines.push(`- ${secondaryLabel}: \`/${secondaryLang}/docs/...\` — content in \`src/content/docs-${secondaryLang}/\``);
84
+ lines.push(`- ${secondaryLabel} docs should mirror the ${defaultLabel} directory structure`);
85
+ lines.push(``);
86
+ }
87
+ // Enabled features
88
+ const featureDescriptions = {
89
+ search: "Full-text search via Pagefind",
90
+ sidebarFilter: "Real-time sidebar filtering",
91
+ designTokenPanel: "Interactive tabbed panel for tweaking spacing, font, size, and color tokens",
92
+ sidebarResizer: "Draggable sidebar width",
93
+ sidebarToggle: "Show/hide desktop sidebar",
94
+ versioning: "Multi-version documentation support",
95
+ docHistory: "Document edit history",
96
+ llmsTxt: "Generates llms.txt for LLM consumption",
97
+ claudeResources: "Auto-generated docs for Claude Code resources",
98
+ changelog: "Changelog page at `/docs/changelog`",
99
+ };
100
+ const enabledFeatures = choices.features.filter((f) => featureDescriptions[f] !== undefined &&
101
+ f !== "footerNavGroup" &&
102
+ f !== "footerCopyright" &&
103
+ f !== "skillSymlinker");
104
+ if (enabledFeatures.length > 0) {
105
+ lines.push(`## Enabled Features`);
106
+ lines.push(``);
107
+ for (const f of enabledFeatures) {
108
+ lines.push(`- **${f}** — ${featureDescriptions[f]}`);
109
+ }
110
+ lines.push(``);
111
+ }
112
+ return lines.join("\n");
113
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ export interface CliArgs {
2
+ name?: string;
3
+ lang?: string;
4
+ colorSchemeMode?: "single" | "light-dark";
5
+ scheme?: string;
6
+ lightScheme?: string;
7
+ darkScheme?: string;
8
+ defaultMode?: "light" | "dark";
9
+ respectSystemPreference?: boolean;
10
+ i18n?: boolean;
11
+ search?: boolean;
12
+ sidebarFilter?: boolean;
13
+ designTokenPanel?: boolean;
14
+ sidebarResizer?: boolean;
15
+ sidebarToggle?: boolean;
16
+ versioning?: boolean;
17
+ claudeResources?: boolean;
18
+ claudeSkills?: boolean;
19
+ docHistory?: boolean;
20
+ llmsTxt?: boolean;
21
+ skillSymlinker?: boolean;
22
+ tauri?: boolean;
23
+ tauriDev?: boolean;
24
+ footerNavGroup?: boolean;
25
+ footerCopyright?: boolean;
26
+ changelog?: boolean;
27
+ tagGovernance?: boolean;
28
+ footerTaglist?: boolean;
29
+ bodyFootUtil?: boolean;
30
+ githubUrl?: string;
31
+ preset?: string;
32
+ pm?: "pnpm" | "npm" | "yarn" | "bun";
33
+ install?: boolean;
34
+ yes?: boolean;
35
+ help?: boolean;
36
+ }
37
+ export declare function parseArgs(argv?: string[]): CliArgs;
38
+ export declare function printHelp(): void;
39
+ export declare function validateArgs(args: CliArgs): string | null;
package/dist/cli.js ADDED
@@ -0,0 +1,157 @@
1
+ import minimist from "minimist";
2
+ import pc from "picocolors";
3
+ import { FEATURES, SINGLE_SCHEMES, SUPPORTED_LANGS } from "./constants.js";
4
+ export function parseArgs(argv = process.argv.slice(2)) {
5
+ const raw = minimist(argv, {
6
+ string: [
7
+ "name",
8
+ "lang",
9
+ "color-scheme-mode",
10
+ "scheme",
11
+ "light-scheme",
12
+ "dark-scheme",
13
+ "default-mode",
14
+ "github-url",
15
+ "preset",
16
+ "pm",
17
+ ],
18
+ // Do NOT declare booleans here — minimist would default them to false,
19
+ // making it impossible to distinguish "not passed" from "--no-flag".
20
+ // Instead we detect explicit usage by checking whether the original argv
21
+ // contains the flag (or its --no- variant).
22
+ alias: {
23
+ h: "help",
24
+ y: "yes",
25
+ },
26
+ });
27
+ /** Check if a boolean flag was explicitly passed in argv. */
28
+ function wasPassed(flag) {
29
+ return argv.some((a) => a === `--${flag}` || a === `--no-${flag}`);
30
+ }
31
+ const args = {};
32
+ // Project name: first positional arg or --name
33
+ if (raw.name) {
34
+ args.name = raw.name;
35
+ }
36
+ else if (raw._.length > 0 && typeof raw._[0] === "string") {
37
+ args.name = raw._[0];
38
+ }
39
+ if (raw.lang)
40
+ args.lang = raw.lang;
41
+ if (raw["color-scheme-mode"])
42
+ args.colorSchemeMode = raw["color-scheme-mode"];
43
+ if (raw.scheme)
44
+ args.scheme = raw.scheme;
45
+ if (raw["light-scheme"])
46
+ args.lightScheme = raw["light-scheme"];
47
+ if (raw["dark-scheme"])
48
+ args.darkScheme = raw["dark-scheme"];
49
+ if (raw["default-mode"])
50
+ args.defaultMode = raw["default-mode"];
51
+ if (raw.preset)
52
+ args.preset = raw.preset;
53
+ if (raw.pm)
54
+ args.pm = raw.pm;
55
+ if (typeof raw["github-url"] === "string")
56
+ args.githubUrl = raw["github-url"];
57
+ // Boolean flags — only set if explicitly passed in argv
58
+ if (wasPassed("respect-system-preference")) {
59
+ args.respectSystemPreference = raw["respect-system-preference"] !== false;
60
+ }
61
+ // Feature flags — driven by FEATURES constant
62
+ for (const f of FEATURES) {
63
+ if (wasPassed(f.cliFlag)) {
64
+ args[f.value] = raw[f.cliFlag] !== false;
65
+ }
66
+ }
67
+ if (wasPassed("install"))
68
+ args.install = raw["install"] !== false;
69
+ if (raw.yes || raw.y)
70
+ args.yes = true;
71
+ if (raw.help || raw.h)
72
+ args.help = true;
73
+ return args;
74
+ }
75
+ export function printHelp() {
76
+ const langList = SUPPORTED_LANGS.map((l) => l.value).join(", ");
77
+ const featureHelp = FEATURES.map((f) => ` --[no-]${f.cliFlag.padEnd(22)} ${f.hint}`).join("\n");
78
+ console.log(`
79
+ ${pc.bold("Usage:")} create-zudo-doc [project-name] [options]
80
+
81
+ ${pc.bold("Options:")}
82
+ --name <name> Project name (or first positional arg)
83
+ --lang <code> Default language (${langList})
84
+ Default: en
85
+ --color-scheme-mode <mode> single | light-dark
86
+ --scheme <name> Color scheme (single mode)
87
+ --light-scheme <name> Light scheme (light-dark mode)
88
+ --dark-scheme <name> Dark scheme (light-dark mode)
89
+ --default-mode <mode> light | dark (light-dark mode)
90
+ --[no-]respect-system-preference
91
+ Respect OS color scheme preference
92
+ ${featureHelp}
93
+ --github-url <url> GitHub repository URL (drives header link + source link)
94
+ --preset <path> Load settings from a JSON preset file (use "-" for stdin)
95
+ --pm <manager> pnpm | npm | yarn | bun
96
+ --[no-]install Install dependencies after scaffolding
97
+ -y, --yes Use defaults for unspecified options, skip prompts
98
+ -h, --help Show this help message
99
+
100
+ ${pc.bold("Examples:")}
101
+ ${pc.dim("# Interactive mode (default)")}
102
+ create-zudo-doc
103
+
104
+ ${pc.dim("# Non-interactive with defaults")}
105
+ create-zudo-doc my-docs --yes
106
+
107
+ ${pc.dim("# Fully specified")}
108
+ create-zudo-doc my-docs --lang ja --scheme Dracula --no-i18n --pm pnpm --install
109
+
110
+ ${pc.dim("# Light/dark mode with custom schemes")}
111
+ create-zudo-doc my-docs --color-scheme-mode light-dark \\
112
+ --light-scheme "GitHub Light" --dark-scheme "GitHub Dark" \\
113
+ --default-mode dark --yes
114
+ `);
115
+ }
116
+ export function validateArgs(args) {
117
+ if (args.lang) {
118
+ const validLangs = SUPPORTED_LANGS.map((l) => l.value);
119
+ if (!validLangs.includes(args.lang)) {
120
+ return `Invalid language "${args.lang}". Supported: ${validLangs.join(", ")}`;
121
+ }
122
+ }
123
+ if (args.colorSchemeMode && !["single", "light-dark"].includes(args.colorSchemeMode)) {
124
+ return `Invalid color-scheme-mode "${args.colorSchemeMode}". Must be "single" or "light-dark"`;
125
+ }
126
+ if (args.scheme && !SINGLE_SCHEMES.includes(args.scheme)) {
127
+ return `Unknown color scheme "${args.scheme}"`;
128
+ }
129
+ if (args.lightScheme && !SINGLE_SCHEMES.includes(args.lightScheme)) {
130
+ return `Unknown light scheme "${args.lightScheme}"`;
131
+ }
132
+ if (args.darkScheme && !SINGLE_SCHEMES.includes(args.darkScheme)) {
133
+ return `Unknown dark scheme "${args.darkScheme}"`;
134
+ }
135
+ if (args.defaultMode && !["light", "dark"].includes(args.defaultMode)) {
136
+ return `Invalid default-mode "${args.defaultMode}". Must be "light" or "dark"`;
137
+ }
138
+ if (args.pm && !["pnpm", "npm", "yarn", "bun"].includes(args.pm)) {
139
+ return `Invalid package manager "${args.pm}". Must be pnpm, npm, yarn, or bun`;
140
+ }
141
+ // Validate scheme combinations
142
+ if (args.colorSchemeMode === "single" && (args.lightScheme || args.darkScheme)) {
143
+ return `--light-scheme and --dark-scheme are only valid with --color-scheme-mode light-dark`;
144
+ }
145
+ if (args.colorSchemeMode === "light-dark" && args.scheme) {
146
+ return `--scheme is only valid with --color-scheme-mode single`;
147
+ }
148
+ if (args.name) {
149
+ if (/^[./]|\.\./.test(args.name)) {
150
+ return "Project name must not contain path traversal characters";
151
+ }
152
+ if (/[<>:"|?*\\]/.test(args.name)) {
153
+ return "Project name contains invalid characters";
154
+ }
155
+ }
156
+ return null;
157
+ }
@@ -0,0 +1,95 @@
1
+ import type { UserChoices } from "./prompts.js";
2
+ /** A single injection into a shared file at an anchor point. */
3
+ export interface Injection {
4
+ /** Target file path relative to project root */
5
+ file: string;
6
+ /** Anchor comment string to locate in the target file */
7
+ anchor: string;
8
+ /** Content to insert */
9
+ content: string;
10
+ /**
11
+ * Where to insert relative to the anchor line.
12
+ * - "before": insert content on the line before the anchor (default)
13
+ * - "after": insert content on the line after the anchor
14
+ * - "replace": replace the range between `anchor` (start) and the
15
+ * corresponding `:end` anchor. The anchor must end with `:start`
16
+ * and a sibling anchor ending with `:end` must exist.
17
+ */
18
+ position?: "before" | "after" | "replace";
19
+ }
20
+ /** Definition of a single feature's contribution to the generated project. */
21
+ export interface FeatureDefinition {
22
+ /** Feature key (matches constants.ts value or internal name) */
23
+ name: string;
24
+ /** Injection instructions for shared/base files */
25
+ injections: Injection[];
26
+ /** Other feature names this feature depends on (optional) */
27
+ dependencies?: string[];
28
+ /**
29
+ * Post-processing hook for complex transformations that cannot be expressed
30
+ * as simple file copies or anchor injections (e.g. i18n page patching).
31
+ */
32
+ postProcess?: (targetDir: string, choices: UserChoices) => Promise<void>;
33
+ }
34
+ /**
35
+ * A function that returns a FeatureDefinition based on user choices.
36
+ * This allows injections to be conditional on other choices.
37
+ */
38
+ export type FeatureModule = (choices: UserChoices) => FeatureDefinition;
39
+ /**
40
+ * Apply a list of injections to files in the target directory.
41
+ *
42
+ * Injections are grouped by target file and applied in array order.
43
+ * For "before"/"after" modes the content is inserted relative to the anchor
44
+ * line. For "replace" mode, the content replaces everything between the
45
+ * `:start` and `:end` anchors (exclusive — the anchor lines themselves are
46
+ * also removed).
47
+ */
48
+ export declare function applyInjections(targetDir: string, injections: Injection[]): Promise<void>;
49
+ /**
50
+ * Remove all remaining `@slot:` anchor lines from files in the target
51
+ * directory. Call this after all injections have been applied so that
52
+ * unused anchors don't appear in the generated project.
53
+ */
54
+ export declare function cleanAnchors(targetDir: string, files: string[]): Promise<void>;
55
+ /**
56
+ * Copy a feature's files into the target directory.
57
+ * `featureFilesDir` is the absolute path to the feature's `files/` directory.
58
+ * Each file inside mirrors the project directory structure.
59
+ */
60
+ export declare function copyFeatureFiles(featureFilesDir: string, targetDir: string): Promise<void>;
61
+ /**
62
+ * Resolve which features are selected based on UserChoices.
63
+ * Handles special cases like the footer pseudo-feature.
64
+ */
65
+ export declare function resolveSelectedFeatures(choices: UserChoices, featureModules: Record<string, FeatureModule>): FeatureDefinition[];
66
+ /**
67
+ * Validate that all feature dependencies are satisfied.
68
+ * Throws if a selected feature depends on one that isn't selected.
69
+ */
70
+ export declare function validateDependencies(features: FeatureDefinition[], allSelectedNames: Set<string>): void;
71
+ /** Files that may contain injection anchors and need cleaning.
72
+ *
73
+ * W7A (#1736): the two `.astro` entries were dropped — those files no
74
+ * longer exist in generated projects after the post-cutover .tsx
75
+ * migration. The only surviving anchor target is `global.css`, where
76
+ * `design-token-panel.ts` injects `@import "@takazudo/zdtp/styles.css";`
77
+ * at `@slot:global-css:feature-styles`. The sibling
78
+ * `@slot:global-css:theme-tokens` anchor in the same file is consumed
79
+ * by the color-scheme palette generator and must remain. The .tsx
80
+ * anchor form is still supported in `ANCHOR_LINE_RE` for forward
81
+ * compatibility, but no current feature uses it.
82
+ */
83
+ export declare const ANCHOR_FILES: string[];
84
+ /**
85
+ * Main composition entry point. Orchestrates the full feature composition
86
+ * pipeline for a generated project.
87
+ *
88
+ * 1. Resolve selected features
89
+ * 2. Validate dependencies
90
+ * 3. Copy feature files
91
+ * 4. Apply all injections
92
+ * 5. Run post-processing hooks
93
+ * 6. Clean up unused anchors
94
+ */
95
+ export declare function composeFeatures(targetDir: string, choices: UserChoices, featureModules: Record<string, FeatureModule>, featuresDir: string): Promise<void>;