create-zudo-doc 3.3.0 → 4.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.
- package/README.md +3 -2
- package/dist/api.d.ts +2 -0
- package/dist/api.js +9 -1
- package/dist/claude-md-gen.js +3 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +11 -1
- package/dist/constants.d.ts +6 -0
- package/dist/constants.js +123 -1
- package/dist/features/claude-resources.d.ts +2 -5
- package/dist/features/claude-resources.js +2 -5
- package/dist/features/doc-history.d.ts +4 -3
- package/dist/features/doc-history.js +8 -4
- package/dist/features/index.js +2 -0
- package/dist/features/tag-governance.d.ts +3 -15
- package/dist/features/tag-governance.js +24 -40
- package/dist/features/theme-pack-switcher.d.ts +11 -0
- package/dist/features/theme-pack-switcher.js +13 -0
- package/dist/index.js +3 -0
- package/dist/preset.d.ts +2 -0
- package/dist/preset.js +12 -1
- package/dist/prompts.d.ts +2 -0
- package/dist/prompts.js +22 -1
- package/dist/scaffold.d.ts +1 -1
- package/dist/scaffold.js +36 -36
- package/dist/zfb-config-gen.js +24 -14
- package/package.json +1 -1
- package/templates/base/pages/docs/[[...slug]].tsx +11 -6
- package/templates/features/i18n/files/pages/[locale]/docs/[[...slug]].tsx +8 -4
- package/templates/features/tagGovernance/files/scripts/tags-audit.ts +0 -131
- package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +0 -430
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ Each feature has a `--[no-]<flag>` form. Passing `--feature` enables it; `--no-f
|
|
|
72
72
|
| `--[no-]search` | Pagefind full-text search | on |
|
|
73
73
|
| `--[no-]sidebar-filter` | Real-time sidebar filter | on |
|
|
74
74
|
| `--[no-]image-enlarge` | Click-to-enlarge for oversized images | on |
|
|
75
|
-
| `--[no-]tag-governance` | Vocabulary-aware tag audit + suggest scripts |
|
|
75
|
+
| `--[no-]tag-governance` | Vocabulary-aware tag audit + suggest scripts | off |
|
|
76
76
|
| `--[no-]claude-resources` | Auto-generate Claude Code docs (`CLAUDE.md`, `llms.txt`) | off |
|
|
77
77
|
| `--[no-]claude-skills` | Ship zudo-doc Claude Code skills (design-system, translate, version-bump) | off |
|
|
78
78
|
| `--[no-]design-token-panel` | Interactive panel for tweaking spacing, font, color tokens | off |
|
|
@@ -86,7 +86,8 @@ Each feature has a `--[no-]<flag>` form. Passing `--feature` enables it; `--no-f
|
|
|
86
86
|
| `--[no-]tauri` | Tauri desktop app — Mode 1 offline reader | off |
|
|
87
87
|
| `--[no-]tauri-dev` | Tauri dev wrapper — Mode 2 configurable dev wrapper | off |
|
|
88
88
|
| `--[no-]footer-nav-group` | Navigation links in the footer | off |
|
|
89
|
-
| `--[no-]
|
|
89
|
+
| `--[no-]dynamic-page-transition` | SPA-style page transition with history handling | on |
|
|
90
|
+
| `--[no-]footer-copyright` | Copyright notice in the footer | on |
|
|
90
91
|
| `--[no-]footer-taglist` | Grouped tag index in the footer (requires tag-governance) | off |
|
|
91
92
|
| `--[no-]changelog` | Changelog page | off |
|
|
92
93
|
|
package/dist/api.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface CreateOptions {
|
|
|
9
9
|
darkScheme?: string;
|
|
10
10
|
respectPrefersColorScheme?: boolean;
|
|
11
11
|
defaultMode?: "light" | "dark";
|
|
12
|
+
/** Theme pack slug (ADR #2818 Decision 7), validated against THEME_PACKS. Default: "default". */
|
|
13
|
+
themePack?: string;
|
|
12
14
|
features: string[];
|
|
13
15
|
/** GitHub repository URL — drives the header GitHub link and body-foot
|
|
14
16
|
* "View source on GitHub" link. Empty = disabled. */
|
package/dist/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { SINGLE_SCHEMES } from "./constants.js";
|
|
2
|
+
import { SINGLE_SCHEMES, THEME_PACKS } from "./constants.js";
|
|
3
3
|
import { scaffold } from "./scaffold.js";
|
|
4
4
|
import { initGitRepo, installDependencies, validateProjectName } from "./utils.js";
|
|
5
5
|
export async function createZudoDoc(options) {
|
|
@@ -22,6 +22,14 @@ export async function createZudoDoc(options) {
|
|
|
22
22
|
throw new Error(`Unknown ${label} "${value}"`);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
// Validate the theme pack slug like the CLI (cli.ts) and preset (preset.ts)
|
|
26
|
+
// paths do (ADR #2818 Decision 7 / #2823 codex-review follow-up) — an
|
|
27
|
+
// unvalidated slug here would be written verbatim into zfb.config.ts and
|
|
28
|
+
// only fail when the generated site's build reaches plugin setup.
|
|
29
|
+
if (rest.themePack && !THEME_PACKS.some((t) => t.slug === rest.themePack)) {
|
|
30
|
+
const catalog = THEME_PACKS.map((t) => t.slug).join(", ");
|
|
31
|
+
throw new Error(`Unknown theme pack "${rest.themePack}". Available: ${catalog}`);
|
|
32
|
+
}
|
|
25
33
|
const choices = { ...rest, defaultLang: rest.defaultLang ?? "en" };
|
|
26
34
|
await scaffold(choices);
|
|
27
35
|
const targetDir = path.resolve(process.cwd(), choices.projectName);
|
package/dist/claude-md-gen.js
CHANGED
|
@@ -21,7 +21,7 @@ export function generateCLAUDEFile(choices) {
|
|
|
21
21
|
lines.push(`- **MDX** — content format, authored under \`src/content/\``);
|
|
22
22
|
lines.push(`- **Tailwind CSS v4** — via \`@tailwindcss/vite\``);
|
|
23
23
|
lines.push(`- **Preact** — for interactive islands only (with compat mode for React API)`);
|
|
24
|
-
lines.push(`- **
|
|
24
|
+
lines.push(`- **Shiki** — package-owned code highlighting with the configured light/dark theme pair`);
|
|
25
25
|
lines.push(`- **@takazudo/zudo-doc** — the package that owns everything: layout, chrome, islands, default \`@theme\` design tokens, and (via \`packageOwnedRoutes\`, on by default) the doc routes themselves`);
|
|
26
26
|
lines.push(``);
|
|
27
27
|
// Commands
|
|
@@ -45,6 +45,7 @@ export function generateCLAUDEFile(choices) {
|
|
|
45
45
|
lines.push(` [locale]/docs/[[...slug]].tsx # same, for non-default locales`);
|
|
46
46
|
}
|
|
47
47
|
lines.push(`src/`);
|
|
48
|
+
lines.push(`├── chrome-bindings.tsx # optional typed primary chrome / named header / MDX bindings`);
|
|
48
49
|
lines.push(`├── content/`);
|
|
49
50
|
lines.push(`│ └── docs/ # MDX content (this project's showcase docs)`);
|
|
50
51
|
if (choices.features.includes("i18n")) {
|
|
@@ -55,7 +56,7 @@ export function generateCLAUDEFile(choices) {
|
|
|
55
56
|
lines.push(` └── global.css # @import chain + a token-override slot — that's it`);
|
|
56
57
|
lines.push("```");
|
|
57
58
|
lines.push(``);
|
|
58
|
-
lines.push(`Everything else — layout, header, sidebar, footer, doc chrome, islands, and the default design tokens — lives in \`node_modules/@takazudo/zudo-doc\`.
|
|
59
|
+
lines.push(`Everything else — layout, header, sidebar, footer, doc chrome, islands, and the default design tokens — lives in \`node_modules/@takazudo/zudo-doc\`. For supported markup replacement, create \`src/chrome-bindings.tsx\` with \`defineChromeBindings\`, set \`chromeBindingsModule\`, and use the primary \`Header\` / \`Footer\` / \`Sidebar\` / \`Toc\` / \`Breadcrumb\` / \`DocPager\` slots or the named \`headerRightComponents\` registry. The generated default, locale, and doc-history route shapes already consume the same binding object; do not fork a route stub for presentational customization. \`npx zudo-doc eject <component>\` only copies source: heed its primary, nested-chrome, or content-layer remediation before expecting the copy to render. Settings you didn't set explicitly in \`zfb.config.ts\` use the package's documented defaults — hover \`zudoDoc\`'s \`ZudoDocConfig\` argument in your editor to see every field and its \`@default\`.`);
|
|
59
60
|
lines.push(``);
|
|
60
61
|
// Content conventions
|
|
61
62
|
lines.push(`## Content Conventions`);
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface CliArgs {
|
|
|
7
7
|
darkScheme?: string;
|
|
8
8
|
defaultMode?: "light" | "dark";
|
|
9
9
|
respectSystemPreference?: boolean;
|
|
10
|
+
/** Theme pack slug (ADR #2818 Decision 7). Validated against THEME_PACKS. */
|
|
11
|
+
themePack?: string;
|
|
10
12
|
i18n?: boolean;
|
|
11
13
|
search?: boolean;
|
|
12
14
|
sidebarFilter?: boolean;
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import minimist from "minimist";
|
|
2
2
|
import pc from "picocolors";
|
|
3
|
-
import { FEATURES, SINGLE_SCHEMES, SUPPORTED_LANGS } from "./constants.js";
|
|
3
|
+
import { FEATURES, SINGLE_SCHEMES, SUPPORTED_LANGS, THEME_PACKS } from "./constants.js";
|
|
4
4
|
import { validateProjectName } from "./utils.js";
|
|
5
5
|
export function parseArgs(argv = process.argv.slice(2)) {
|
|
6
6
|
const raw = minimist(argv, {
|
|
@@ -12,6 +12,7 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
12
12
|
"light-scheme",
|
|
13
13
|
"dark-scheme",
|
|
14
14
|
"default-mode",
|
|
15
|
+
"theme-pack",
|
|
15
16
|
"github-url",
|
|
16
17
|
"preset",
|
|
17
18
|
"pm",
|
|
@@ -49,6 +50,8 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
49
50
|
args.darkScheme = raw["dark-scheme"];
|
|
50
51
|
if (raw["default-mode"])
|
|
51
52
|
args.defaultMode = raw["default-mode"];
|
|
53
|
+
if (raw["theme-pack"])
|
|
54
|
+
args.themePack = raw["theme-pack"];
|
|
52
55
|
if (raw.preset)
|
|
53
56
|
args.preset = raw.preset;
|
|
54
57
|
if (raw.pm)
|
|
@@ -77,6 +80,7 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
77
80
|
}
|
|
78
81
|
export function printHelp() {
|
|
79
82
|
const langList = SUPPORTED_LANGS.map((l) => l.value).join(", ");
|
|
83
|
+
const themePackList = THEME_PACKS.map((t) => t.slug).join(", ");
|
|
80
84
|
const featureHelp = FEATURES.map((f) => ` --[no-]${f.cliFlag.padEnd(22)} ${f.hint}`).join("\n");
|
|
81
85
|
console.log(`
|
|
82
86
|
${pc.bold("Usage:")} create-zudo-doc [project-name] [options]
|
|
@@ -92,6 +96,8 @@ ${pc.bold("Options:")}
|
|
|
92
96
|
--default-mode <mode> light | dark (light-dark mode)
|
|
93
97
|
--[no-]respect-system-preference
|
|
94
98
|
Respect OS color scheme preference
|
|
99
|
+
--theme-pack <slug> Theme pack (${themePackList})
|
|
100
|
+
Default: default
|
|
95
101
|
${featureHelp}
|
|
96
102
|
--github-url <url> GitHub repository URL (drives header link + source link)
|
|
97
103
|
--preset <path> Load settings from a JSON preset file (use "-" for stdin)
|
|
@@ -135,6 +141,10 @@ export function validateArgs(args) {
|
|
|
135
141
|
if (args.defaultMode && !["light", "dark"].includes(args.defaultMode)) {
|
|
136
142
|
return `Invalid default-mode "${args.defaultMode}". Must be "light" or "dark"`;
|
|
137
143
|
}
|
|
144
|
+
if (args.themePack && !THEME_PACKS.some((t) => t.slug === args.themePack)) {
|
|
145
|
+
const catalog = THEME_PACKS.map((t) => t.slug).join(", ");
|
|
146
|
+
return `Unknown theme pack "${args.themePack}". Available: ${catalog}`;
|
|
147
|
+
}
|
|
138
148
|
if (args.pm && !["pnpm", "npm", "yarn", "bun"].includes(args.pm)) {
|
|
139
149
|
return `Invalid package manager "${args.pm}". Must be pnpm, npm, yarn, or bun`;
|
|
140
150
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -11,6 +11,12 @@ export interface SupportedLang {
|
|
|
11
11
|
label: string;
|
|
12
12
|
}
|
|
13
13
|
export declare const SUPPORTED_LANGS: SupportedLang[];
|
|
14
|
+
export interface ThemePackOption {
|
|
15
|
+
slug: string;
|
|
16
|
+
label: string;
|
|
17
|
+
hint: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const THEME_PACKS: ThemePackOption[];
|
|
14
20
|
export interface Feature {
|
|
15
21
|
value: string;
|
|
16
22
|
label: string;
|
package/dist/constants.js
CHANGED
|
@@ -18,6 +18,121 @@ export const SUPPORTED_LANGS = [
|
|
|
18
18
|
{ value: "de", label: "German" },
|
|
19
19
|
{ value: "pt", label: "Portuguese" },
|
|
20
20
|
];
|
|
21
|
+
// Hand-kept mirror of the bundled theme-pack registry
|
|
22
|
+
// (packages/zudo-doc/src/theme-packs/<slug>/meta.json — theme pack ADR
|
|
23
|
+
// #2818, census landed by #2819, full catalog synced by the Finalize epic's
|
|
24
|
+
// catalog-sync sub-issue #2855). Same convention as DEFAULT_MIRROR in
|
|
25
|
+
// zfb-config-gen.ts: create-zudo-doc cannot import @takazudo/zudo-doc at
|
|
26
|
+
// generator-build time, so the CLI/prompt catalog is a local copy. Order
|
|
27
|
+
// mirrors the package's own default enablement order (resolveEnabledPacks):
|
|
28
|
+
// "default" first, then the rest alphabetically by slug.
|
|
29
|
+
export const THEME_PACKS = [
|
|
30
|
+
{
|
|
31
|
+
slug: "default",
|
|
32
|
+
label: "Default",
|
|
33
|
+
hint: "Stock zudo-doc look — no extra stylesheet loaded",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
slug: "beacon",
|
|
37
|
+
label: "Beacon",
|
|
38
|
+
hint: "WCAG-AAA high contrast — 7:1+ ink, 3px focus rings, always-underlined links",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
slug: "broadsheet",
|
|
42
|
+
label: "Broadsheet",
|
|
43
|
+
hint: "Newspaper editorial — Playfair masthead, Oxford ink rules, a red drop cap",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
slug: "brutalist",
|
|
47
|
+
label: "Brutalist",
|
|
48
|
+
hint: "Raw concrete web — stark black on white, 4px slab borders, hazard-orange tape",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
slug: "drift",
|
|
52
|
+
label: "Drift",
|
|
53
|
+
hint: "Floaty slate-blue comfort dark for long reading, relaxed Plex type",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
slug: "fjord",
|
|
57
|
+
label: "Fjord",
|
|
58
|
+
hint: "Polar-night blue under a faint aurora — frost-cyan accents, icy borders",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
slug: "foundry",
|
|
62
|
+
label: "Foundry",
|
|
63
|
+
hint: "GitHub-neutral baseline — white paper, Primer-blue accents",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
slug: "futura-editorial",
|
|
67
|
+
label: "Futura Editorial",
|
|
68
|
+
hint: "Geometric Futura headings over Noto Sans body, one restrained red accent",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
slug: "hearth",
|
|
72
|
+
label: "Hearth",
|
|
73
|
+
hint: "Warm cream & brick-red fireside docs — Fraunces headings, ember-glow dark mode",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
slug: "hollow",
|
|
77
|
+
label: "Hollow",
|
|
78
|
+
hint: "Dark violet space — neon pink headings, violet links, a quiet starfield",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
slug: "ledger",
|
|
82
|
+
label: "Ledger",
|
|
83
|
+
hint: "Cream academic serif in the Tufte tradition — warm paper, oxblood links",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
slug: "manuscript",
|
|
87
|
+
label: "Manuscript",
|
|
88
|
+
hint: "A quiet Garamond book page — warm paper, soft ink, sepia rubrication",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
slug: "matcha",
|
|
92
|
+
label: "Matcha",
|
|
93
|
+
hint: "Green tea ceremony — deep matcha on warm cream, mincho headings, zen whitespace",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
slug: "nocturne",
|
|
97
|
+
label: "Nocturne",
|
|
98
|
+
hint: "Purple midnight — velvet aubergine depths, lavender links, muted gold hairlines",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
slug: "observatory",
|
|
102
|
+
label: "Observatory",
|
|
103
|
+
hint: "Night-sky atlas — star-field depth, nebula violet and comet gold over navy",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
slug: "onyx",
|
|
107
|
+
label: "Onyx",
|
|
108
|
+
hint: "Luxury noir — jet black, champagne serif headings, a single gold hairline accent",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
slug: "phosphor",
|
|
112
|
+
label: "Phosphor",
|
|
113
|
+
hint: "Green CRT terminal — phosphor glow, scanlines, inverse-video nav",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
slug: "solar",
|
|
117
|
+
label: "Solar",
|
|
118
|
+
hint: "Solarized precision — low-eyestrain paper tones, blue/cyan/orange accents",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
slug: "sumi",
|
|
122
|
+
label: "Sumi",
|
|
123
|
+
hint: "Sumi-e ink on washi — bold mincho brush headings, one vermillion hanko seal accent",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
slug: "swissgrid",
|
|
127
|
+
label: "Swissgrid",
|
|
128
|
+
hint: "International Typographic Style — grid discipline, one hot Swiss-red accent",
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
slug: "washi",
|
|
132
|
+
label: "Washi",
|
|
133
|
+
hint: "Warm washi paper, sumi ink, and ai-iro indigo seals for calm documentation",
|
|
134
|
+
},
|
|
135
|
+
];
|
|
21
136
|
export const FEATURES = [
|
|
22
137
|
{
|
|
23
138
|
value: "i18n",
|
|
@@ -61,6 +176,13 @@ export const FEATURES = [
|
|
|
61
176
|
default: false,
|
|
62
177
|
cliFlag: "design-token-panel",
|
|
63
178
|
},
|
|
179
|
+
{
|
|
180
|
+
value: "themePackSwitcher",
|
|
181
|
+
label: "Theme pack switcher",
|
|
182
|
+
hint: "Bottom-right flyout to switch between installed theme packs",
|
|
183
|
+
default: false,
|
|
184
|
+
cliFlag: "theme-pack-switcher",
|
|
185
|
+
},
|
|
64
186
|
{
|
|
65
187
|
value: "sidebarResizer",
|
|
66
188
|
label: "Sidebar resizer",
|
|
@@ -149,7 +271,7 @@ export const FEATURES = [
|
|
|
149
271
|
value: "footerCopyright",
|
|
150
272
|
label: "Footer copyright",
|
|
151
273
|
hint: "Copyright notice in the footer",
|
|
152
|
-
default:
|
|
274
|
+
default: true,
|
|
153
275
|
cliFlag: "footer-copyright",
|
|
154
276
|
},
|
|
155
277
|
{
|
|
@@ -4,11 +4,8 @@ import type { FeatureModule } from "../compose.js";
|
|
|
4
4
|
*
|
|
5
5
|
* Fully plugin-owned (`@takazudo/zudo-doc/plugins/claude-resources`,
|
|
6
6
|
* `zudoDocPreset()` wires it whenever `settings.claudeResources` is
|
|
7
|
-
* truthy).
|
|
8
|
-
*
|
|
9
|
-
* duplicate implementation nothing imported — deleted in the minimal-scaffold
|
|
10
|
-
* cutover (epic zudolab/zudo-doc#2651, Wave 6 #2660). This feature's touch
|
|
11
|
-
* points are now just: `claudeResources` + `defaultLocaleOnlyPrefixes` fields
|
|
7
|
+
* truthy). Generation is package-owned. This feature's touch points are now
|
|
8
|
+
* just: `claudeResources` + `defaultLocaleOnlyPrefixes` fields
|
|
12
9
|
* (`zfb-config-gen.ts`).
|
|
13
10
|
*/
|
|
14
11
|
export declare const claudeResourcesFeature: FeatureModule;
|
|
@@ -3,11 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Fully plugin-owned (`@takazudo/zudo-doc/plugins/claude-resources`,
|
|
5
5
|
* `zudoDocPreset()` wires it whenever `settings.claudeResources` is
|
|
6
|
-
* truthy).
|
|
7
|
-
*
|
|
8
|
-
* duplicate implementation nothing imported — deleted in the minimal-scaffold
|
|
9
|
-
* cutover (epic zudolab/zudo-doc#2651, Wave 6 #2660). This feature's touch
|
|
10
|
-
* points are now just: `claudeResources` + `defaultLocaleOnlyPrefixes` fields
|
|
6
|
+
* truthy). Generation is package-owned. This feature's touch points are now
|
|
7
|
+
* just: `claudeResources` + `defaultLocaleOnlyPrefixes` fields
|
|
11
8
|
* (`zfb-config-gen.ts`).
|
|
12
9
|
*/
|
|
13
10
|
export const claudeResourcesFeature = () => ({
|
|
@@ -12,13 +12,14 @@ import type { FeatureModule } from "../compose.js";
|
|
|
12
12
|
*
|
|
13
13
|
* What's left to wire: the self-contained doc-route stub(s)
|
|
14
14
|
* (`pages/docs/[[...slug]].tsx`, and its i18n locale sibling when i18n is
|
|
15
|
-
* also selected)
|
|
15
|
+
* also selected) always thread the host's `chromeBindings`. Unlike
|
|
16
16
|
* `DesignTokenPanelBootstrap` (auto-defaulted at the chrome-derive seam,
|
|
17
17
|
* #2658 gate-2 fix), `DocHistory`'s derive-level default is a deliberate
|
|
18
18
|
* no-op stub (see `routes/_chrome.tsx`'s comment on why — its own island
|
|
19
19
|
* needs the REAL host binding to hydrate). So when docHistory is selected,
|
|
20
20
|
* this feature patches the stub(s) to statically import the real
|
|
21
|
-
* `DocHistory` component and
|
|
22
|
-
*
|
|
21
|
+
* `DocHistory` component and merge it over those bindings — preserving every
|
|
22
|
+
* configured host slot while maintaining the same #2480 scanner-reachability
|
|
23
|
+
* chain `routes/_chrome.tsx` uses for the package's own routes.
|
|
23
24
|
*/
|
|
24
25
|
export declare const docHistoryFeature: FeatureModule;
|
|
@@ -13,14 +13,15 @@ import path from "path";
|
|
|
13
13
|
*
|
|
14
14
|
* What's left to wire: the self-contained doc-route stub(s)
|
|
15
15
|
* (`pages/docs/[[...slug]].tsx`, and its i18n locale sibling when i18n is
|
|
16
|
-
* also selected)
|
|
16
|
+
* also selected) always thread the host's `chromeBindings`. Unlike
|
|
17
17
|
* `DesignTokenPanelBootstrap` (auto-defaulted at the chrome-derive seam,
|
|
18
18
|
* #2658 gate-2 fix), `DocHistory`'s derive-level default is a deliberate
|
|
19
19
|
* no-op stub (see `routes/_chrome.tsx`'s comment on why — its own island
|
|
20
20
|
* needs the REAL host binding to hydrate). So when docHistory is selected,
|
|
21
21
|
* this feature patches the stub(s) to statically import the real
|
|
22
|
-
* `DocHistory` component and
|
|
23
|
-
*
|
|
22
|
+
* `DocHistory` component and merge it over those bindings — preserving every
|
|
23
|
+
* configured host slot while maintaining the same #2480 scanner-reachability
|
|
24
|
+
* chain `routes/_chrome.tsx` uses for the package's own routes.
|
|
24
25
|
*/
|
|
25
26
|
export const docHistoryFeature = () => ({
|
|
26
27
|
name: "docHistory",
|
|
@@ -45,7 +46,10 @@ export const docHistoryFeature = () => ({
|
|
|
45
46
|
content = content.replace(`import { createChrome } from "@takazudo/zudo-doc/chrome";`, `import { createChrome } from "@takazudo/zudo-doc/chrome";
|
|
46
47
|
${importMarker}
|
|
47
48
|
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";`);
|
|
48
|
-
content = content.replace(`const { renderDocPage } = createChrome(routeCtx);`, `const { renderDocPage } = createChrome(routeCtx,
|
|
49
|
+
content = content.replace(`const { renderDocPage } = createChrome(routeCtx, chromeBindings);`, `const { renderDocPage } = createChrome(routeCtx, {
|
|
50
|
+
...chromeBindings,
|
|
51
|
+
...defineChromeBindings({ DocHistory }),
|
|
52
|
+
});`);
|
|
49
53
|
await fs.writeFile(stubPath, content);
|
|
50
54
|
}
|
|
51
55
|
},
|
package/dist/features/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { docHistoryFeature } from "./doc-history.js";
|
|
|
14
14
|
import { llmsTxtFeature } from "./llms-txt.js";
|
|
15
15
|
import { claudeResourcesFeature } from "./claude-resources.js";
|
|
16
16
|
import { designTokenPanelFeature } from "./design-token-panel.js";
|
|
17
|
+
import { themePackSwitcherFeature } from "./theme-pack-switcher.js";
|
|
17
18
|
import { i18nFeature } from "./i18n.js";
|
|
18
19
|
import { versioningFeature } from "./versioning.js";
|
|
19
20
|
import { tauriFeature } from "./tauri.js";
|
|
@@ -35,6 +36,7 @@ export const featureModules = {
|
|
|
35
36
|
// sidebarFilter — built into sidebar-tree.tsx, stays in base
|
|
36
37
|
claudeResources: claudeResourcesFeature,
|
|
37
38
|
designTokenPanel: designTokenPanelFeature,
|
|
39
|
+
themePackSwitcher: themePackSwitcherFeature,
|
|
38
40
|
sidebarResizer: sidebarResizerFeature,
|
|
39
41
|
sidebarToggle: sidebarToggleFeature,
|
|
40
42
|
versioning: versioningFeature,
|
|
@@ -2,20 +2,8 @@ import type { FeatureModule } from "../compose.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Tag governance feature.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `zfb-config-gen.ts` writes straight into `zfb.config.ts`.
|
|
9
|
-
*
|
|
10
|
-
* One genuine remaining coupling (minimal-scaffold cutover, epic
|
|
11
|
-
* zudolab/zudo-doc#2651): `@takazudo/zudo-doc`'s `tags-audit` bin
|
|
12
|
-
* (`packages/zudo-doc/bin/tags-audit-runner.ts`) still dynamically
|
|
13
|
-
* `import()`s `src/config/settings.ts` and `src/config/tag-vocabulary.ts`
|
|
14
|
-
* BY PATH — a legacy contract that predates the single-`zfb.config.ts`
|
|
15
|
-
* model and hasn't been updated for it (out of this generator's scope; a
|
|
16
|
-
* package-level follow-up could remove it). So `tagGovernance` is the one
|
|
17
|
-
* feature that still needs a tiny `src/config/` pair — this postProcess
|
|
18
|
-
* writes both, sourced from the SAME `choices` the main `zfb.config.ts`
|
|
19
|
-
* generation reads, so the two can't drift.
|
|
5
|
+
* Writes one project-owned tag vocabulary module. Its named vocabulary export
|
|
6
|
+
* feeds zfb while its default TagCliConfig export feeds both package-owned
|
|
7
|
+
* bins through an explicit `--config` package-script argument.
|
|
20
8
|
*/
|
|
21
9
|
export declare const tagGovernanceFeature: FeatureModule;
|
|
@@ -4,21 +4,9 @@ import { getSecondaryLang } from "../utils.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Tag governance feature.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `zfb-config-gen.ts` writes straight into `zfb.config.ts`.
|
|
11
|
-
*
|
|
12
|
-
* One genuine remaining coupling (minimal-scaffold cutover, epic
|
|
13
|
-
* zudolab/zudo-doc#2651): `@takazudo/zudo-doc`'s `tags-audit` bin
|
|
14
|
-
* (`packages/zudo-doc/bin/tags-audit-runner.ts`) still dynamically
|
|
15
|
-
* `import()`s `src/config/settings.ts` and `src/config/tag-vocabulary.ts`
|
|
16
|
-
* BY PATH — a legacy contract that predates the single-`zfb.config.ts`
|
|
17
|
-
* model and hasn't been updated for it (out of this generator's scope; a
|
|
18
|
-
* package-level follow-up could remove it). So `tagGovernance` is the one
|
|
19
|
-
* feature that still needs a tiny `src/config/` pair — this postProcess
|
|
20
|
-
* writes both, sourced from the SAME `choices` the main `zfb.config.ts`
|
|
21
|
-
* generation reads, so the two can't drift.
|
|
7
|
+
* Writes one project-owned tag vocabulary module. Its named vocabulary export
|
|
8
|
+
* feeds zfb while its default TagCliConfig export feeds both package-owned
|
|
9
|
+
* bins through an explicit `--config` package-script argument.
|
|
22
10
|
*/
|
|
23
11
|
export const tagGovernanceFeature = (choices) => ({
|
|
24
12
|
name: "tagGovernance",
|
|
@@ -26,34 +14,30 @@ export const tagGovernanceFeature = (choices) => ({
|
|
|
26
14
|
postProcess: async (targetDir) => {
|
|
27
15
|
const vocabPath = path.join(targetDir, "src/config/tag-vocabulary.ts");
|
|
28
16
|
if (!(await fs.pathExists(vocabPath))) {
|
|
29
|
-
|
|
17
|
+
const contentDirs = choices.features.includes("i18n")
|
|
18
|
+
? `[
|
|
19
|
+
"src/content/docs",
|
|
20
|
+
"src/content/docs-${getSecondaryLang(choices.defaultLang)}",
|
|
21
|
+
]`
|
|
22
|
+
: `["src/content/docs"]`;
|
|
23
|
+
await fs.outputFile(vocabPath, `import type { TagCliConfig } from "@takazudo/zudo-doc/tags-audit";
|
|
24
|
+
import type { TagVocabularyEntry } from "@takazudo/zudo-doc/settings";
|
|
30
25
|
|
|
31
26
|
// Starter (empty) tag vocabulary — add an entry per tag you use in doc
|
|
32
|
-
// frontmatter so \`pnpm tags:audit\` can validate it.
|
|
33
|
-
// zfb.config.ts
|
|
34
|
-
// scripts/tags-suggest.ts — this file is the single source of truth.
|
|
27
|
+
// frontmatter so \`pnpm tags:audit\` can validate it. This named export is
|
|
28
|
+
// also consumed by zfb.config.ts as tagVocabularyEntries.
|
|
35
29
|
export const tagVocabulary: TagVocabularyEntry[] = [];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// full note). Keep these four fields in sync with the matching zudoDoc({...})
|
|
48
|
-
// fields in zfb.config.ts — both are generated from the same choices at
|
|
49
|
-
// scaffold time, so a fresh scaffold never drifts; hand-edit both if you
|
|
50
|
-
// change either one later.
|
|
51
|
-
export const settings = {
|
|
52
|
-
docsDir: "src/content/docs",
|
|
53
|
-
tagGovernance: "warn" as const,
|
|
54
|
-
tagVocabulary: true,
|
|
55
|
-
locales: ${locales},
|
|
56
|
-
};
|
|
30
|
+
|
|
31
|
+
// Package scripts pass this module to the package-owned audit/suggest bins.
|
|
32
|
+
// Paths are resolved from the project root.
|
|
33
|
+
const tagCliConfig = {
|
|
34
|
+
contentDirs: ${contentDirs},
|
|
35
|
+
vocabulary: tagVocabulary,
|
|
36
|
+
governance: "warn",
|
|
37
|
+
vocabularyActive: true,
|
|
38
|
+
} satisfies TagCliConfig;
|
|
39
|
+
|
|
40
|
+
export default tagCliConfig;
|
|
57
41
|
`);
|
|
58
42
|
}
|
|
59
43
|
},
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* themePackSwitcher feature (theme pack ADR #2818).
|
|
4
|
+
*
|
|
5
|
+
* Purely a `zudoDoc({ themePackSwitcher: true })` field (see
|
|
6
|
+
* `zfb-config-gen.ts`) — the bottom-right switcher flyout and its browse-all
|
|
7
|
+
* dialog are PACKAGE-INJECTED (`@takazudo/zudo-doc`'s theme-pack-provider /
|
|
8
|
+
* theme-pack-sync + the flyout/dialog islands), gated on
|
|
9
|
+
* `settings.themePackSwitcher`. There is nothing to copy or postProcess.
|
|
10
|
+
*/
|
|
11
|
+
export declare const themePackSwitcherFeature: FeatureModule;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* themePackSwitcher feature (theme pack ADR #2818).
|
|
3
|
+
*
|
|
4
|
+
* Purely a `zudoDoc({ themePackSwitcher: true })` field (see
|
|
5
|
+
* `zfb-config-gen.ts`) — the bottom-right switcher flyout and its browse-all
|
|
6
|
+
* dialog are PACKAGE-INJECTED (`@takazudo/zudo-doc`'s theme-pack-provider /
|
|
7
|
+
* theme-pack-sync + the flyout/dialog islands), gated on
|
|
8
|
+
* `settings.themePackSwitcher`. There is nothing to copy or postProcess.
|
|
9
|
+
*/
|
|
10
|
+
export const themePackSwitcherFeature = () => ({
|
|
11
|
+
name: "themePackSwitcher",
|
|
12
|
+
injections: [],
|
|
13
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -55,6 +55,8 @@ async function main() {
|
|
|
55
55
|
if (args.respectSystemPreference !== undefined) {
|
|
56
56
|
prefilled.respectPrefersColorScheme = args.respectSystemPreference;
|
|
57
57
|
}
|
|
58
|
+
if (args.themePack)
|
|
59
|
+
prefilled.themePack = args.themePack;
|
|
58
60
|
if (args.pm)
|
|
59
61
|
prefilled.packageManager = args.pm;
|
|
60
62
|
if (args.githubUrl !== undefined)
|
|
@@ -91,6 +93,7 @@ async function main() {
|
|
|
91
93
|
else {
|
|
92
94
|
prefilled.singleScheme ??= "Default Dark";
|
|
93
95
|
}
|
|
96
|
+
prefilled.themePack ??= "default";
|
|
94
97
|
prefilled.packageManager ??= "pnpm";
|
|
95
98
|
prefilled.githubUrl ??= "";
|
|
96
99
|
// For features: set defaults for any not explicitly specified
|
package/dist/preset.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface PresetJson {
|
|
|
35
35
|
darkScheme?: string;
|
|
36
36
|
defaultMode?: "light" | "dark";
|
|
37
37
|
respectPrefersColorScheme?: boolean;
|
|
38
|
+
/** Theme pack slug (ADR #2818 Decision 7), validated against THEME_PACKS. */
|
|
39
|
+
themePack?: string;
|
|
38
40
|
features?: string[];
|
|
39
41
|
githubUrl?: string;
|
|
40
42
|
cjkFriendly?: boolean;
|
package/dist/preset.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
-
import { FEATURES, SINGLE_SCHEMES, SUPPORTED_LANGS } from "./constants.js";
|
|
2
|
+
import { FEATURES, SINGLE_SCHEMES, SUPPORTED_LANGS, THEME_PACKS } from "./constants.js";
|
|
3
3
|
import { validateProjectName } from "./utils.js";
|
|
4
4
|
const VALID_HEADER_RIGHT_COMPONENTS = new Set([
|
|
5
5
|
"theme-toggle",
|
|
@@ -30,6 +30,7 @@ export function loadPreset(pathOrStdin) {
|
|
|
30
30
|
const VALID_LANGS = new Set(SUPPORTED_LANGS.map((l) => l.value));
|
|
31
31
|
const VALID_SCHEMES = new Set(SINGLE_SCHEMES);
|
|
32
32
|
const VALID_PMS = new Set(["pnpm", "npm", "yarn", "bun"]);
|
|
33
|
+
const VALID_THEME_PACKS = new Set(THEME_PACKS.map((t) => t.slug));
|
|
33
34
|
export function validatePreset(json) {
|
|
34
35
|
if (json === null || typeof json !== "object" || Array.isArray(json)) {
|
|
35
36
|
return "Preset must be a JSON object";
|
|
@@ -66,6 +67,14 @@ export function validatePreset(json) {
|
|
|
66
67
|
if (p.defaultMode && !["light", "dark"].includes(p.defaultMode)) {
|
|
67
68
|
return `Invalid defaultMode "${p.defaultMode}" in preset`;
|
|
68
69
|
}
|
|
70
|
+
if (p.themePack !== undefined) {
|
|
71
|
+
if (typeof p.themePack !== "string") {
|
|
72
|
+
return `"themePack" must be a string in preset`;
|
|
73
|
+
}
|
|
74
|
+
if (!VALID_THEME_PACKS.has(p.themePack)) {
|
|
75
|
+
return `Unknown theme pack "${p.themePack}" in preset. Available: ${[...VALID_THEME_PACKS].join(", ")}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
69
78
|
if (p.packageManager && !VALID_PMS.has(p.packageManager)) {
|
|
70
79
|
return `Invalid packageManager "${p.packageManager}" in preset`;
|
|
71
80
|
}
|
|
@@ -174,6 +183,8 @@ export function presetToChoices(json) {
|
|
|
174
183
|
if (json.respectPrefersColorScheme !== undefined) {
|
|
175
184
|
choices.respectPrefersColorScheme = json.respectPrefersColorScheme;
|
|
176
185
|
}
|
|
186
|
+
if (json.themePack)
|
|
187
|
+
choices.themePack = json.themePack;
|
|
177
188
|
if (json.packageManager)
|
|
178
189
|
choices.packageManager = json.packageManager;
|
|
179
190
|
if (json.githubUrl !== undefined)
|
package/dist/prompts.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface UserChoices {
|
|
|
8
8
|
darkScheme?: string;
|
|
9
9
|
respectPrefersColorScheme?: boolean;
|
|
10
10
|
defaultMode?: "light" | "dark";
|
|
11
|
+
themePack?: string;
|
|
11
12
|
features: string[];
|
|
12
13
|
explicitlyDisabledFeatures?: string[];
|
|
13
14
|
githubUrl?: string;
|
|
@@ -26,6 +27,7 @@ export interface PartialChoices {
|
|
|
26
27
|
darkScheme?: string;
|
|
27
28
|
respectPrefersColorScheme?: boolean;
|
|
28
29
|
defaultMode?: "light" | "dark";
|
|
30
|
+
themePack?: string;
|
|
29
31
|
features?: Partial<Record<string, boolean>>;
|
|
30
32
|
explicitlyDisabledFeatures?: string[];
|
|
31
33
|
githubUrl?: string;
|