create-zudo-doc 1.2.0 → 2.0.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/dist/api.d.ts +6 -0
- package/dist/api.js +5 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +4 -0
- package/dist/index.js +26 -1
- package/dist/scaffold.d.ts +1 -1
- package/dist/scaffold.js +10 -6
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +72 -1
- package/package.json +1 -1
- package/templates/base/pages/index.tsx +6 -4
- package/templates/base/pages/lib/_chrome.ts +166 -0
- package/templates/base/pages/lib/_doc-route-entries.ts +7 -51
- package/templates/base/pages/lib/_nav-source-docs.ts +9 -29
- package/templates/base/pages/lib/_route-context.ts +32 -0
- package/templates/base/src/config/tag-vocabulary-types.ts +4 -39
- package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +137 -22
- package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +115 -28
- package/templates/features/i18n/files/pages/[locale]/index.tsx +6 -4
- package/templates/base/pages/_mdx-components.ts +0 -106
- package/templates/base/pages/lib/_category-nav.tsx +0 -34
- package/templates/base/pages/lib/_category-tree-nav.tsx +0 -45
- package/templates/base/pages/lib/_compose-meta-title.ts +0 -25
- package/templates/base/pages/lib/_doc-body-end.tsx +0 -8
- package/templates/base/pages/lib/_doc-content-header.tsx +0 -17
- package/templates/base/pages/lib/_doc-history-area.tsx +0 -34
- package/templates/base/pages/lib/_doc-metainfo-area.tsx +0 -26
- package/templates/base/pages/lib/_doc-page-renderer.tsx +0 -31
- package/templates/base/pages/lib/_doc-page-shell.tsx +0 -29
- package/templates/base/pages/lib/_doc-pager.tsx +0 -9
- package/templates/base/pages/lib/_doc-route-paths.ts +0 -16
- package/templates/base/pages/lib/_doc-tags-area.tsx +0 -30
- package/templates/base/pages/lib/_footer-with-defaults.tsx +0 -58
- package/templates/base/pages/lib/_head-with-defaults.tsx +0 -22
- package/templates/base/pages/lib/_header-with-defaults.tsx +0 -45
- package/templates/base/pages/lib/_inline-version-switcher.tsx +0 -23
- package/templates/base/pages/lib/_math-block.tsx +0 -4
- package/templates/base/pages/lib/_nav-data-prep.ts +0 -118
- package/templates/base/pages/lib/_search-widget-script.ts +0 -2
- package/templates/base/pages/lib/_sidebar-prepaint.tsx +0 -11
- package/templates/base/pages/lib/_sidebar-with-defaults.tsx +0 -26
- package/templates/base/pages/lib/_site-tree-nav.tsx +0 -37
- package/templates/base/pages/lib/_toc-title.ts +0 -3
- package/templates/base/pages/lib/route-enumerators.ts +0 -58
- package/templates/base/src/components/tree-nav-shared.tsx +0 -71
- package/templates/base/src/utils/content-files.ts +0 -110
- package/templates/features/docTags/files/pages/lib/_tag-pages.tsx +0 -47
- package/templates/features/versioning/files/pages/lib/_versions-page.tsx +0 -33
package/dist/api.d.ts
CHANGED
|
@@ -16,5 +16,11 @@ export interface CreateOptions {
|
|
|
16
16
|
packageManager: "pnpm" | "npm" | "yarn" | "bun";
|
|
17
17
|
/** Install dependencies after scaffolding (default: false) */
|
|
18
18
|
install?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Initialize a git repository + initial commit after scaffolding
|
|
21
|
+
* (default: false). The CLI defaults this on; the programmatic API defaults
|
|
22
|
+
* it off so automation / test callers never create unexpected repos.
|
|
23
|
+
*/
|
|
24
|
+
git?: boolean;
|
|
19
25
|
}
|
|
20
26
|
export declare function createZudoDoc(options: CreateOptions): Promise<string>;
|
package/dist/api.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { scaffold } from "./scaffold.js";
|
|
3
|
-
import { installDependencies, validateProjectName } from "./utils.js";
|
|
3
|
+
import { initGitRepo, installDependencies, validateProjectName } from "./utils.js";
|
|
4
4
|
export async function createZudoDoc(options) {
|
|
5
|
-
const { install = false, ...rest } = options;
|
|
5
|
+
const { install = false, git = false, ...rest } = options;
|
|
6
6
|
const nameError = validateProjectName(rest.projectName);
|
|
7
7
|
if (nameError)
|
|
8
8
|
throw new Error(`Invalid projectName: ${nameError}`);
|
|
@@ -12,5 +12,8 @@ export async function createZudoDoc(options) {
|
|
|
12
12
|
if (install) {
|
|
13
13
|
installDependencies(targetDir, choices.packageManager);
|
|
14
14
|
}
|
|
15
|
+
if (git) {
|
|
16
|
+
initGitRepo(targetDir);
|
|
17
|
+
}
|
|
15
18
|
return targetDir;
|
|
16
19
|
}
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -67,6 +67,8 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
67
67
|
}
|
|
68
68
|
if (wasPassed("install"))
|
|
69
69
|
args.install = raw["install"] !== false;
|
|
70
|
+
if (wasPassed("git"))
|
|
71
|
+
args.git = raw["git"] !== false;
|
|
70
72
|
if (raw.yes || raw.y)
|
|
71
73
|
args.yes = true;
|
|
72
74
|
if (raw.help || raw.h)
|
|
@@ -95,6 +97,8 @@ ${featureHelp}
|
|
|
95
97
|
--preset <path> Load settings from a JSON preset file (use "-" for stdin)
|
|
96
98
|
--pm <manager> pnpm | npm | yarn | bun
|
|
97
99
|
--[no-]install Install dependencies after scaffolding
|
|
100
|
+
--[no-]git Initialize a git repository + initial commit
|
|
101
|
+
(default: on; enables doc-history metadata)
|
|
98
102
|
-y, --yes Use defaults for unspecified options, skip prompts
|
|
99
103
|
-h, --help Show this help message
|
|
100
104
|
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { FEATURES } from "./constants.js";
|
|
|
6
6
|
import { loadPreset } from "./preset.js";
|
|
7
7
|
import { runPrompts } from "./prompts.js";
|
|
8
8
|
import { scaffold } from "./scaffold.js";
|
|
9
|
-
import { installDependencies } from "./utils.js";
|
|
9
|
+
import { installDependencies, initGitRepo } from "./utils.js";
|
|
10
10
|
async function main() {
|
|
11
11
|
const args = parseArgs();
|
|
12
12
|
// Handle --help
|
|
@@ -144,6 +144,31 @@ async function main() {
|
|
|
144
144
|
s2.stop("Installation failed. Run install manually.");
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
+
// Initialize a git repository (default on; --no-git to opt out). doc-history
|
|
148
|
+
// reads `git log` for each page's Created/Updated/Author block, so a project
|
|
149
|
+
// without git renders empty history. Runs after install so the lockfile is
|
|
150
|
+
// part of the initial commit; auto-skips if the target is already inside a
|
|
151
|
+
// repo or if git is unavailable.
|
|
152
|
+
const shouldInitGit = args.git ?? true;
|
|
153
|
+
if (shouldInitGit) {
|
|
154
|
+
const s3 = p.spinner();
|
|
155
|
+
s3.start("Initializing git repository...");
|
|
156
|
+
const result = initGitRepo(targetDir);
|
|
157
|
+
switch (result.status) {
|
|
158
|
+
case "ok":
|
|
159
|
+
s3.stop("Initialized git repository with an initial commit.");
|
|
160
|
+
break;
|
|
161
|
+
case "skipped-existing-repo":
|
|
162
|
+
s3.stop("Already inside a git repository — skipped git init.");
|
|
163
|
+
break;
|
|
164
|
+
case "skipped-no-git":
|
|
165
|
+
s3.stop("git not found — skipped git init.");
|
|
166
|
+
break;
|
|
167
|
+
case "failed":
|
|
168
|
+
s3.stop("Could not initialize git — continuing without it.");
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
147
172
|
p.outro(`${pc.green("Done!")} Your project is ready at ${pc.cyan(choices.projectName)}`);
|
|
148
173
|
console.log();
|
|
149
174
|
console.log(` ${pc.bold("Next steps:")}`);
|
package/dist/scaffold.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export { getSecondaryLang };
|
|
|
11
11
|
*
|
|
12
12
|
* Bumped in lockstep by scripts/release-create-zudo-doc.sh.
|
|
13
13
|
*/
|
|
14
|
-
export declare const ZUDO_DOC_PIN = "^
|
|
14
|
+
export declare const ZUDO_DOC_PIN = "^2.0.0";
|
|
15
15
|
export declare function scaffold(choices: UserChoices): Promise<void>;
|
package/dist/scaffold.js
CHANGED
|
@@ -18,7 +18,7 @@ export { getSecondaryLang };
|
|
|
18
18
|
*
|
|
19
19
|
* Bumped in lockstep by scripts/release-create-zudo-doc.sh.
|
|
20
20
|
*/
|
|
21
|
-
export const ZUDO_DOC_PIN = "^
|
|
21
|
+
export const ZUDO_DOC_PIN = "^2.0.0";
|
|
22
22
|
/**
|
|
23
23
|
* Files in `templates/base/**` that must never be copied into a generated
|
|
24
24
|
* project. Each entry is matched against the path relative to `templates/base/`
|
|
@@ -477,13 +477,17 @@ function generatePackageJson(choices) {
|
|
|
477
477
|
// No consumer-facing / CLI breaking change.
|
|
478
478
|
// next.68: routine toolchain bump from next.67, adopted in
|
|
479
479
|
// lockstep with the root package.json pins. No consumer-facing / CLI change.
|
|
480
|
-
// next.69
|
|
480
|
+
// next.69: routine toolchain bump from next.68, adopted in
|
|
481
481
|
// lockstep with the root package.json pins. No consumer-facing / CLI change.
|
|
482
|
-
|
|
483
|
-
|
|
482
|
+
// next.70 (current pin): routine toolchain bump from next.69, re-aligned
|
|
483
|
+
// with the root package.json pins (root was bumped in b5489acf; this
|
|
484
|
+
// scaffold pin lagged at next.69 and broke check-pin-parity). No
|
|
485
|
+
// consumer-facing / CLI change.
|
|
486
|
+
"@takazudo/zfb": "0.1.0-next.70",
|
|
487
|
+
"@takazudo/zfb-runtime": "0.1.0-next.70",
|
|
484
488
|
// zfb-adapter-cloudflare — required for any route with `prerender = false`.
|
|
485
489
|
// Pinned in lockstep with @takazudo/zfb.
|
|
486
|
-
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.
|
|
490
|
+
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.70",
|
|
487
491
|
// @takazudo/zudo-doc — published from this monorepo via
|
|
488
492
|
// .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
|
|
489
493
|
// lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
|
|
@@ -566,7 +570,7 @@ function generatePackageJson(choices) {
|
|
|
566
570
|
// @takazudo/zudo-doc/integrations/doc-history which in turn imports
|
|
567
571
|
// @takazudo/zudo-doc-history-server/git-history. Without this dep the
|
|
568
572
|
// plugin host fails at init with ERR_MODULE_NOT_FOUND — W8A (#1739).
|
|
569
|
-
deps["@takazudo/zudo-doc-history-server"] = "^
|
|
573
|
+
deps["@takazudo/zudo-doc-history-server"] = "^2.0.0";
|
|
570
574
|
// tsx is no longer needed here: the relocated package plugin imports the
|
|
571
575
|
// runner directly (no `tsx -e` spawn) since the package ships compiled
|
|
572
576
|
// dist/ — package-first migration #2321 (#2337).
|
package/dist/utils.d.ts
CHANGED
|
@@ -7,6 +7,33 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function validateProjectName(name: string): string | null;
|
|
9
9
|
export declare function installDependencies(dir: string, pm: string): void;
|
|
10
|
+
export type GitInitResult = {
|
|
11
|
+
status: "ok";
|
|
12
|
+
} | {
|
|
13
|
+
status: "skipped-existing-repo";
|
|
14
|
+
} | {
|
|
15
|
+
status: "skipped-no-git";
|
|
16
|
+
} | {
|
|
17
|
+
status: "failed";
|
|
18
|
+
message: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Initialize a git repository in `dir` and create an initial commit.
|
|
22
|
+
*
|
|
23
|
+
* Why: zudo-doc's doc-history feature reads `git log` for each page's
|
|
24
|
+
* Created/Updated/Author block. A scaffolded project with no git repo renders
|
|
25
|
+
* empty history — and on older `@takazudo/zudo-doc-history-server` it crashed
|
|
26
|
+
* `pnpm dev` outright (the preBuild hook ran `git rev-parse` and threw).
|
|
27
|
+
* Initializing git here makes the feature work out of the box.
|
|
28
|
+
*
|
|
29
|
+
* Safe by construction:
|
|
30
|
+
* - `skipped-no-git` when git is not installed;
|
|
31
|
+
* - `skipped-existing-repo` when `dir` is already inside a git work tree (e.g.
|
|
32
|
+
* scaffolding into an existing monorepo) — never nest repositories;
|
|
33
|
+
* - the initial commit only falls back to a neutral identity when the user has
|
|
34
|
+
* none configured, so a normal user's commit keeps their own identity.
|
|
35
|
+
*/
|
|
36
|
+
export declare function initGitRepo(dir: string): GitInitResult;
|
|
10
37
|
export declare function capitalize(str: string): string;
|
|
11
38
|
/** Get a short uppercase label for a language code (e.g. "en" → "EN", "zh-cn" → "ZH-CN"). */
|
|
12
39
|
export declare function getLangLabel(langCode: string): string;
|
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execSync } from "child_process";
|
|
1
|
+
import { execSync, execFileSync } from "child_process";
|
|
2
2
|
import fs from "fs-extra";
|
|
3
3
|
// Project-name grammar (locked by F4 — S4 #2013):
|
|
4
4
|
// /^[a-z0-9][a-z0-9._-]*$/, max 214 chars, unscoped, used as both directory
|
|
@@ -36,6 +36,77 @@ export function installDependencies(dir, pm) {
|
|
|
36
36
|
// Use pipe to avoid garbled output when used alongside spinner
|
|
37
37
|
execSync(cmd, { cwd: dir, stdio: "pipe" });
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Initialize a git repository in `dir` and create an initial commit.
|
|
41
|
+
*
|
|
42
|
+
* Why: zudo-doc's doc-history feature reads `git log` for each page's
|
|
43
|
+
* Created/Updated/Author block. A scaffolded project with no git repo renders
|
|
44
|
+
* empty history — and on older `@takazudo/zudo-doc-history-server` it crashed
|
|
45
|
+
* `pnpm dev` outright (the preBuild hook ran `git rev-parse` and threw).
|
|
46
|
+
* Initializing git here makes the feature work out of the box.
|
|
47
|
+
*
|
|
48
|
+
* Safe by construction:
|
|
49
|
+
* - `skipped-no-git` when git is not installed;
|
|
50
|
+
* - `skipped-existing-repo` when `dir` is already inside a git work tree (e.g.
|
|
51
|
+
* scaffolding into an existing monorepo) — never nest repositories;
|
|
52
|
+
* - the initial commit only falls back to a neutral identity when the user has
|
|
53
|
+
* none configured, so a normal user's commit keeps their own identity.
|
|
54
|
+
*/
|
|
55
|
+
export function initGitRepo(dir) {
|
|
56
|
+
// Is git available at all?
|
|
57
|
+
try {
|
|
58
|
+
execFileSync("git", ["--version"], { stdio: "ignore" });
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return { status: "skipped-no-git" };
|
|
62
|
+
}
|
|
63
|
+
// Already inside a git work tree? Don't create a nested repository.
|
|
64
|
+
try {
|
|
65
|
+
const inside = execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
66
|
+
cwd: dir,
|
|
67
|
+
encoding: "utf-8",
|
|
68
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
69
|
+
}).trim();
|
|
70
|
+
if (inside === "true")
|
|
71
|
+
return { status: "skipped-existing-repo" };
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// git exits non-zero when `dir` is not inside a repo — the expected case.
|
|
75
|
+
}
|
|
76
|
+
const COMMIT_MESSAGE = "Initial commit from create-zudo-doc";
|
|
77
|
+
try {
|
|
78
|
+
execFileSync("git", ["init", "-q"], { cwd: dir, stdio: "ignore" });
|
|
79
|
+
execFileSync("git", ["add", "-A"], { cwd: dir, stdio: "ignore" });
|
|
80
|
+
try {
|
|
81
|
+
execFileSync("git", ["commit", "-q", "-m", COMMIT_MESSAGE], {
|
|
82
|
+
cwd: dir,
|
|
83
|
+
stdio: "ignore",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// No git identity configured on this machine — retry with a neutral
|
|
88
|
+
// fallback so the initial commit still succeeds. Users with a configured
|
|
89
|
+
// identity never reach this branch (their identity is used above).
|
|
90
|
+
execFileSync("git", [
|
|
91
|
+
"-c",
|
|
92
|
+
"user.name=create-zudo-doc",
|
|
93
|
+
"-c",
|
|
94
|
+
"user.email=create-zudo-doc@users.noreply.github.com",
|
|
95
|
+
"commit",
|
|
96
|
+
"-q",
|
|
97
|
+
"-m",
|
|
98
|
+
COMMIT_MESSAGE,
|
|
99
|
+
], { cwd: dir, stdio: "ignore" });
|
|
100
|
+
}
|
|
101
|
+
return { status: "ok" };
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return {
|
|
105
|
+
status: "failed",
|
|
106
|
+
message: err instanceof Error ? err.message : String(err),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
39
110
|
export function capitalize(str) {
|
|
40
111
|
return str.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
41
112
|
}
|
package/package.json
CHANGED
|
@@ -28,10 +28,12 @@ import type { JSX } from "preact";
|
|
|
28
28
|
import type { VNode } from "preact";
|
|
29
29
|
import { Island } from "@takazudo/zfb";
|
|
30
30
|
import { SiteTreeNav } from "@takazudo/zudo-doc/site-tree-nav-island";
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
import {
|
|
32
|
+
FooterWithDefaults,
|
|
33
|
+
HeaderWithDefaults,
|
|
34
|
+
HeadWithDefaults,
|
|
35
|
+
composeMetaTitle,
|
|
36
|
+
} from "./lib/_chrome";
|
|
35
37
|
import { BodyEndIslands } from "./lib/_body-end-islands";
|
|
36
38
|
|
|
37
39
|
export const frontmatter = { title: "Home" };
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
// Host chrome adapter — THE single host adapter for the page-chrome surface
|
|
4
|
+
// (epic Collapse Wiring Shells #2420; HOSTCOLLAPSE #2427 collapsed the former
|
|
5
|
+
// per-component `pages/lib/_*` chrome shells into this one module).
|
|
6
|
+
//
|
|
7
|
+
// It builds the host's REAL bindings ONCE and threads them through the public
|
|
8
|
+
// `createChrome(routeContext, hostBindings)` builder, then re-exports the wired
|
|
9
|
+
// page-chrome barrel (renderDocPage, HeaderWithDefaults, FooterWithDefaults,
|
|
10
|
+
// HeadWithDefaults, composeMetaTitle, …). Every doc route + homepage chrome
|
|
11
|
+
// import resolves here.
|
|
12
|
+
//
|
|
13
|
+
// - the reconstructed route context comes from the retained, vitest-safe
|
|
14
|
+
// `./_route-context` seam (settings + i18n + URL/nav/slug helpers +
|
|
15
|
+
// nav-source resolvers + route enumerators), fed the host content bridge
|
|
16
|
+
// (`stableDocs`) so the content read + nav enumeration stay byte-identical;
|
|
17
|
+
// - the genuinely host-bound slots (`hostBindings`): the real SearchWidget,
|
|
18
|
+
// git-history manifest, sidebars config, frontmatter renderers/builder,
|
|
19
|
+
// footer tag loader + vocabulary, body-end islands, DocHistory island, and
|
|
20
|
+
// the showcase MDX content overrides (`mdxExtras`).
|
|
21
|
+
//
|
|
22
|
+
// Island-scanner contract (load-bearing): this module MUST keep the STATIC
|
|
23
|
+
// imports of DocHistory (`@takazudo/zudo-doc/doc-history`), BodyEndIslands
|
|
24
|
+
// (`./_body-end-islands`) and PresetGeneratorFallback (`./_preset-generator`).
|
|
25
|
+
// After the collapse the only page→island import chain is
|
|
26
|
+
// `pages/docs/*.tsx → _chrome.ts → {DocHistory, BodyEndIslands, PresetGenerator}`;
|
|
27
|
+
// if any of these became a type-only or dynamic import the zfb island scanner
|
|
28
|
+
// would stop walking it and the marker/bundle would silently drop.
|
|
29
|
+
|
|
30
|
+
import type { ComponentChildren } from "preact";
|
|
31
|
+
import type { ChromeHostBindings } from "@takazudo/zudo-doc/factory-context";
|
|
32
|
+
|
|
33
|
+
import { createChrome } from "@takazudo/zudo-doc/chrome";
|
|
34
|
+
|
|
35
|
+
import { settings } from "@/config/settings";
|
|
36
|
+
import { defaultLocale } from "@/config/i18n";
|
|
37
|
+
import { tagVocabulary } from "@/config/tag-vocabulary";
|
|
38
|
+
import sidebars from "@/config/sidebars";
|
|
39
|
+
import { frontmatterRenderers } from "@/config/frontmatter-preview-renderers";
|
|
40
|
+
import { collectTags } from "@/utils/tags";
|
|
41
|
+
import { toRouteSlug } from "@/utils/slug";
|
|
42
|
+
import type { DocsEntry } from "@/types/docs-entry";
|
|
43
|
+
|
|
44
|
+
import { routeContext } from "./_route-context";
|
|
45
|
+
import { stableDocs, memoizeDerived } from "./_nav-source-cache";
|
|
46
|
+
import { mergeLocaleDocs } from "./locale-merge";
|
|
47
|
+
import { SearchWidget } from "./_search-widget";
|
|
48
|
+
import { BodyEndIslands as BodyEndIslandsSeam } from "./_body-end-islands";
|
|
49
|
+
import { buildFrontmatterPreviewEntries } from "./_frontmatter-preview-data";
|
|
50
|
+
import { DetailsWrapper } from "./_details";
|
|
51
|
+
import { PresetGeneratorFallback } from "./_preset-generator";
|
|
52
|
+
import { DocHistory } from "@takazudo/zudo-doc/doc-history";
|
|
53
|
+
import { HtmlPreviewWrapper, type HtmlPreviewWrapperProps } from "@takazudo/zudo-doc/html-preview-wrapper";
|
|
54
|
+
// SSR author + date metadata — `#doc-history-meta` is the build-time manifest
|
|
55
|
+
// alias (esbuild-inlined, no fs). Static import is load-bearing for the island
|
|
56
|
+
// scanner chain noted above.
|
|
57
|
+
import docHistoryMeta from "#doc-history-meta";
|
|
58
|
+
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Footer tag loader (host-side; moved verbatim from the former
|
|
61
|
+
// _chrome-context.ts / _footer-with-defaults.tsx). Reads collections via
|
|
62
|
+
// stableDocs / memoizeDerived and aggregates tags per locale. Threaded as
|
|
63
|
+
// hostBindings.loadTagsForLocale.
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
function loadTagsForLocale(lang: string) {
|
|
67
|
+
if (lang === defaultLocale) {
|
|
68
|
+
const baseDocs = stableDocs("docs");
|
|
69
|
+
return memoizeDerived([baseDocs], "footerTaglist;default", () => {
|
|
70
|
+
const docs: DocsEntry[] = baseDocs.filter(
|
|
71
|
+
(d) => !d.data.draft && !d.data.unlisted && !d.data.category_no_page,
|
|
72
|
+
);
|
|
73
|
+
const tagMap = collectTags(docs, (id, data) => data.slug ?? toRouteSlug(id));
|
|
74
|
+
return [...tagMap.values()].sort((a, b) => a.tag.localeCompare(b.tag, lang));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const baseDocs = stableDocs("docs");
|
|
78
|
+
const localeDocs = stableDocs(`docs-${lang}`);
|
|
79
|
+
return memoizeDerived([baseDocs, localeDocs], `footerTaglist;${lang}`, () => {
|
|
80
|
+
const result = mergeLocaleDocs({
|
|
81
|
+
baseDocs: baseDocs.filter((d) => !d.data.draft),
|
|
82
|
+
localeDocs: localeDocs.filter((d) => !d.data.draft),
|
|
83
|
+
applyDefaultLocaleOnlyFilter: true,
|
|
84
|
+
});
|
|
85
|
+
const docs: DocsEntry[] = result.docs.filter((d) => !d.data.category_no_page);
|
|
86
|
+
const tagMap = collectTags(docs, (id, data) => data.slug ?? toRouteSlug(id));
|
|
87
|
+
return [...tagMap.values()].sort((a, b) => a.tag.localeCompare(b.tag, lang));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Showcase MDX content overrides (host-bound; identical to the former
|
|
93
|
+
// pages/_mdx-components.ts `extras` block — kept in lockstep). Threaded via
|
|
94
|
+
// hostBindings.mdxExtras; the package factory merges them over its defaults.
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
/** MDX-tag stub: renders nothing (Preact null-vnode path). */
|
|
98
|
+
const MdxStub = (_props: unknown) => null;
|
|
99
|
+
|
|
100
|
+
/** SSR pass-through for `<Island when=…>` — renders children, ignores `when`. */
|
|
101
|
+
function IslandWrapper(props: {
|
|
102
|
+
when?: "load" | "idle" | "visible" | "media";
|
|
103
|
+
children?: ComponentChildren;
|
|
104
|
+
}): ComponentChildren {
|
|
105
|
+
return props.children ?? null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const HtmlPreviewWithGlobalConfig = (props: HtmlPreviewWrapperProps) =>
|
|
109
|
+
HtmlPreviewWrapper({ globalConfig: settings.htmlPreview ?? null, ...props });
|
|
110
|
+
|
|
111
|
+
const mdxExtras = {
|
|
112
|
+
HtmlPreview: HtmlPreviewWithGlobalConfig,
|
|
113
|
+
Details: DetailsWrapper,
|
|
114
|
+
SmartBreak: MdxStub,
|
|
115
|
+
Island: IslandWrapper,
|
|
116
|
+
PresetGenerator: PresetGeneratorFallback,
|
|
117
|
+
Avatar: MdxStub,
|
|
118
|
+
Button: MdxStub,
|
|
119
|
+
Card: MdxStub,
|
|
120
|
+
MyComponent: MdxStub,
|
|
121
|
+
PageLayout: MdxStub,
|
|
122
|
+
} as unknown as Record<string, (props: Record<string, unknown>) => unknown>;
|
|
123
|
+
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// The host's real bindings (the 10 ChromeHostBindings slots).
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
const hostBindings: ChromeHostBindings = {
|
|
129
|
+
SearchWidget: SearchWidget as ChromeHostBindings["SearchWidget"],
|
|
130
|
+
docHistoryMeta: docHistoryMeta as Record<string, unknown>,
|
|
131
|
+
sidebarsConfig: sidebars as unknown as Record<string, unknown>,
|
|
132
|
+
frontmatterRenderers: frontmatterRenderers as unknown as ChromeHostBindings["frontmatterRenderers"],
|
|
133
|
+
buildFrontmatterPreviewEntries:
|
|
134
|
+
buildFrontmatterPreviewEntries as unknown as ChromeHostBindings["buildFrontmatterPreviewEntries"],
|
|
135
|
+
loadTagsForLocale: loadTagsForLocale as unknown as ChromeHostBindings["loadTagsForLocale"],
|
|
136
|
+
tagVocabulary,
|
|
137
|
+
BodyEndIslands: BodyEndIslandsSeam as unknown as ChromeHostBindings["BodyEndIslands"],
|
|
138
|
+
DocHistory: DocHistory as unknown as ChromeHostBindings["DocHistory"],
|
|
139
|
+
mdxExtras: mdxExtras as ChromeHostBindings["mdxExtras"],
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Build the wired page-chrome surface ONCE from the route context + real host
|
|
144
|
+
// bindings, and re-export the barrel. Every omitted slot falls back to the
|
|
145
|
+
// package stub (byte-identical to the injected package-routes path); each REAL
|
|
146
|
+
// slot above overrides it.
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
|
|
149
|
+
const chrome = createChrome(routeContext, hostBindings);
|
|
150
|
+
|
|
151
|
+
export type { RenderDocPageOptions } from "@takazudo/zudo-doc/doc-page-renderer";
|
|
152
|
+
|
|
153
|
+
export const {
|
|
154
|
+
composeMetaTitle,
|
|
155
|
+
HeadWithDefaults,
|
|
156
|
+
HeaderWithDefaults,
|
|
157
|
+
FooterWithDefaults,
|
|
158
|
+
SidebarWithDefaults,
|
|
159
|
+
renderDocPage,
|
|
160
|
+
VersionsPageView,
|
|
161
|
+
collectTagMapForLocale,
|
|
162
|
+
TagDetailPageView,
|
|
163
|
+
TagsIndexPageView,
|
|
164
|
+
SiteTreeNavWrapper,
|
|
165
|
+
BodyEndIslands,
|
|
166
|
+
} = chrome;
|
|
@@ -1,54 +1,10 @@
|
|
|
1
|
-
// Thin
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Thin shim — the memoized doc-route-entry builder rides on the unified
|
|
2
|
+
// ChromeContext now (epic Collapse Wiring Shells #2420, FACTORIES #2424).
|
|
3
|
+
// `createRouteContext` (in _chrome-context.ts) assembles `buildDocRouteEntries`
|
|
4
|
+
// as part of the route context; this module just re-exports it so the doc-route
|
|
5
|
+
// page files keep importing it from here unchanged.
|
|
5
6
|
|
|
6
|
-
import { createDocRouteEntries } from "@takazudo/zudo-doc/doc-route-entries";
|
|
7
|
-
import type {
|
|
8
|
-
DocPageEntry,
|
|
9
|
-
DocNavNode,
|
|
10
|
-
BreadcrumbItem,
|
|
11
|
-
} from "@takazudo/zudo-doc/doc-route-entries";
|
|
12
7
|
export type { DocRouteEntry, BuildDocRouteEntriesArgs } from "@takazudo/zudo-doc/doc-route-entries";
|
|
13
|
-
import {
|
|
14
|
-
buildNavTree,
|
|
15
|
-
buildBreadcrumbs,
|
|
16
|
-
collectAutoIndexNodes,
|
|
17
|
-
type NavNode,
|
|
18
|
-
type CategoryMeta,
|
|
19
|
-
} from "@/utils/docs";
|
|
20
|
-
import { getNavSectionForSlug, getNavSubtree } from "@/utils/nav-scope";
|
|
21
|
-
import { toRouteSlug, toSlugParams } from "@/utils/slug";
|
|
22
|
-
import type { DocsEntry } from "@/types/docs-entry";
|
|
23
|
-
import type { Locale } from "@/config/i18n";
|
|
24
|
-
import { extractHeadings } from "./_extract-headings";
|
|
8
|
+
import { routeContext } from "./_route-context";
|
|
25
9
|
|
|
26
|
-
export const { buildDocRouteEntries } =
|
|
27
|
-
// The factory describes its injected nav builders with the package's own
|
|
28
|
-
// structural counterparts (DocPageEntry / DocNavNode / Map<string, unknown>)
|
|
29
|
-
// and a plain `locale: string`. The host's buildNavTree / buildBreadcrumbs
|
|
30
|
-
// are typed against the concrete project types (DocsEntry / NavNode / the
|
|
31
|
-
// Locale union / Map<string, CategoryMeta>). They are runtime-identical, so
|
|
32
|
-
// the stub adapts them with thin wrappers that cast at the injection boundary
|
|
33
|
-
// where the host owns the type knowledge.
|
|
34
|
-
buildNavTree: (docs: DocPageEntry[], locale: string, categoryMeta: Map<string, unknown>) =>
|
|
35
|
-
buildNavTree(
|
|
36
|
-
docs as unknown as DocsEntry[],
|
|
37
|
-
locale as Locale,
|
|
38
|
-
categoryMeta as Map<string, CategoryMeta>,
|
|
39
|
-
) as DocNavNode[],
|
|
40
|
-
buildBreadcrumbs: (
|
|
41
|
-
tree: DocNavNode[],
|
|
42
|
-
slug: string,
|
|
43
|
-
locale: string,
|
|
44
|
-
urlFor?: (slug: string) => string,
|
|
45
|
-
): BreadcrumbItem[] =>
|
|
46
|
-
buildBreadcrumbs(tree as NavNode[], slug, locale as Locale, urlFor),
|
|
47
|
-
collectAutoIndexNodes: (tree: DocNavNode[]) =>
|
|
48
|
-
collectAutoIndexNodes(tree as NavNode[]) as DocNavNode[],
|
|
49
|
-
getNavSectionForSlug,
|
|
50
|
-
getNavSubtree,
|
|
51
|
-
toRouteSlug,
|
|
52
|
-
toSlugParams,
|
|
53
|
-
extractHeadings,
|
|
54
|
-
});
|
|
10
|
+
export const { buildDocRouteEntries } = routeContext;
|
|
@@ -1,37 +1,17 @@
|
|
|
1
|
-
// Thin
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Thin shim — nav-source resolvers ride on the unified ChromeContext now
|
|
2
|
+
// (epic Collapse Wiring Shells #2420, FACTORIES #2424). The reconstructed
|
|
3
|
+
// `createRouteContext` (in _chrome-context.ts) builds the identity-stable
|
|
4
|
+
// nav-source API as part of the route context; this module just re-exports the
|
|
5
|
+
// bindings so the existing call sites (route files, nav wrappers, _nav-data-prep,
|
|
6
|
+
// route-enumerators) keep importing them from here unchanged.
|
|
5
7
|
|
|
6
|
-
import { createNavSourceDocs } from "@takazudo/zudo-doc/nav-source-docs";
|
|
7
8
|
export type { NavSourceDocs, NavSourceOptions } from "@takazudo/zudo-doc/nav-source-docs";
|
|
8
|
-
import {
|
|
9
|
-
import { settings } from "@/config/settings";
|
|
10
|
-
import { loadCategoryMeta, isNavVisible } from "@/utils/docs";
|
|
11
|
-
import { isDefaultLocaleOnlyPath } from "@/utils/base";
|
|
12
|
-
import { stableDocs } from "./_nav-source-cache";
|
|
9
|
+
import { routeContext } from "./_route-context";
|
|
13
10
|
|
|
14
|
-
const {
|
|
11
|
+
export const {
|
|
15
12
|
resolveNavSource,
|
|
16
13
|
resolveVersionedLocaleSource,
|
|
17
14
|
loadNavSourceDocs,
|
|
18
15
|
stableMergeCategoryMeta,
|
|
19
16
|
stableNavDocs,
|
|
20
|
-
} =
|
|
21
|
-
defaultLocale,
|
|
22
|
-
docsDir: settings.docsDir,
|
|
23
|
-
getVersions: () => settings.versions,
|
|
24
|
-
getLocaleConfig,
|
|
25
|
-
loadCategoryMeta,
|
|
26
|
-
isNavVisible,
|
|
27
|
-
isDefaultLocaleOnlyPath,
|
|
28
|
-
stableDocs,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
resolveNavSource,
|
|
33
|
-
resolveVersionedLocaleSource,
|
|
34
|
-
loadNavSourceDocs,
|
|
35
|
-
stableMergeCategoryMeta,
|
|
36
|
-
stableNavDocs,
|
|
37
|
-
};
|
|
17
|
+
} = routeContext;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Host route context — the reconstructed RouteContext (settings + i18n + URL
|
|
2
|
+
// helpers + nav/slug helpers + identity-stable nav-source resolvers + doc-route
|
|
3
|
+
// + route enumerators), built ONCE via the public `createRouteContext`
|
|
4
|
+
// (epic Collapse Wiring Shells #2420, FACTORIES #2424).
|
|
5
|
+
//
|
|
6
|
+
// Kept SEPARATE from `_chrome-context.ts` so the data shells (`_nav-source-docs`
|
|
7
|
+
// / `_doc-route-entries` / `route-enumerators`) — and the unit tests that import
|
|
8
|
+
// them — depend ONLY on this lightweight module, NOT on the chrome host bindings
|
|
9
|
+
// (which pull the build-time `#doc-history-meta` alias + island components that
|
|
10
|
+
// don't resolve under vitest).
|
|
11
|
+
//
|
|
12
|
+
// The host content bridge (`stableDocs`) is injected so the docs read + nav
|
|
13
|
+
// enumeration match the project's existing `pages/*` paths() exactly (host
|
|
14
|
+
// `bridgeDocsEntries` over the `zfb/content` snapshot), not the package default.
|
|
15
|
+
|
|
16
|
+
import { createRouteContext } from "@takazudo/zudo-doc/route-context";
|
|
17
|
+
import type { ColorScheme } from "@takazudo/zudo-doc/color-scheme-utils";
|
|
18
|
+
import { settings } from "@/config/settings";
|
|
19
|
+
import { translations } from "@/config/i18n";
|
|
20
|
+
import { tagVocabulary } from "@/config/tag-vocabulary";
|
|
21
|
+
import { colorSchemes } from "@/config/color-schemes";
|
|
22
|
+
import { stableDocs } from "./_nav-source-cache";
|
|
23
|
+
|
|
24
|
+
export const routeContext = createRouteContext(
|
|
25
|
+
{
|
|
26
|
+
settings,
|
|
27
|
+
translations,
|
|
28
|
+
tagVocabulary,
|
|
29
|
+
colorSchemes: colorSchemes as unknown as Record<string, ColorScheme>,
|
|
30
|
+
},
|
|
31
|
+
{ stableDocs },
|
|
32
|
+
);
|
|
@@ -1,39 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* free-form `string[]`. Identical to pre-vocabulary behaviour.
|
|
6
|
-
* - `"warn"` — `tags` schema stays free-form so builds pass, but the tag
|
|
7
|
-
* audit script (see Sub 2) reports unknown tags as warnings and
|
|
8
|
-
* exits non-zero under `--ci`.
|
|
9
|
-
* - `"strict"` — `tags` schema is tightened to `z.enum([...allowedIds])`, so
|
|
10
|
-
* unknown tags fail `pnpm check` / `pnpm build`.
|
|
11
|
-
*
|
|
12
|
-
* Orthogonal to `tagVocabulary` (the on/off switch for consulting the
|
|
13
|
-
* vocabulary file at runtime). See `settings-types.ts` for details.
|
|
14
|
-
*/
|
|
15
|
-
export type TagGovernanceMode = "off" | "warn" | "strict";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* A single entry in the tag vocabulary.
|
|
19
|
-
*
|
|
20
|
-
* - `id` — canonical tag id. What content files should ideally use.
|
|
21
|
-
* - `label` — optional human-readable label (falls back to `id`).
|
|
22
|
-
* - `description`— optional short description for tooling / tag index pages.
|
|
23
|
-
* - `group` — optional grouping key used by the grouped tag footer
|
|
24
|
-
* (e.g. `"type"`, `"level"`, `"topic"`).
|
|
25
|
-
* - `aliases` — alternate strings that content files may use. Alias
|
|
26
|
-
* resolution rewrites these to `id` before aggregation.
|
|
27
|
-
* - `deprecated` — `true` marks the tag as deprecated with no redirect: the
|
|
28
|
-
* canonical id is dropped from aggregation. Pass
|
|
29
|
-
* `{ redirect: "<other-id>" }` to rewrite this tag to another
|
|
30
|
-
* canonical id when it appears in content.
|
|
31
|
-
*/
|
|
32
|
-
export interface TagVocabularyEntry {
|
|
33
|
-
id: string;
|
|
34
|
-
label?: string;
|
|
35
|
-
description?: string;
|
|
36
|
-
group?: string;
|
|
37
|
-
aliases?: readonly string[];
|
|
38
|
-
deprecated?: boolean | { redirect?: string };
|
|
39
|
-
}
|
|
1
|
+
// Re-export from the shared package — canonical definitions live in
|
|
2
|
+
// @takazudo/zudo-doc/settings (epic #2321). Consumers that import from
|
|
3
|
+
// this local path continue to work unchanged.
|
|
4
|
+
export type { TagGovernanceMode, TagVocabularyEntry } from "@takazudo/zudo-doc/settings";
|