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.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/bin/create-zudo-doc.js +2 -0
- package/dist/api.d.ts +20 -0
- package/dist/api.js +13 -0
- package/dist/claude-md-gen.d.ts +2 -0
- package/dist/claude-md-gen.js +113 -0
- package/dist/cli.d.ts +39 -0
- package/dist/cli.js +157 -0
- package/dist/compose.d.ts +95 -0
- package/dist/compose.js +206 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.js +224 -0
- package/dist/features/body-foot-util.d.ts +10 -0
- package/dist/features/body-foot-util.js +12 -0
- package/dist/features/claude-resources.d.ts +2 -0
- package/dist/features/claude-resources.js +6 -0
- package/dist/features/design-token-panel.d.ts +14 -0
- package/dist/features/design-token-panel.js +27 -0
- package/dist/features/doc-history.d.ts +9 -0
- package/dist/features/doc-history.js +11 -0
- package/dist/features/doc-tags.d.ts +19 -0
- package/dist/features/doc-tags.js +33 -0
- package/dist/features/footer-taglist.d.ts +14 -0
- package/dist/features/footer-taglist.js +17 -0
- package/dist/features/footer.d.ts +8 -0
- package/dist/features/footer.js +10 -0
- package/dist/features/i18n.d.ts +22 -0
- package/dist/features/i18n.js +41 -0
- package/dist/features/image-enlarge.d.ts +11 -0
- package/dist/features/image-enlarge.js +13 -0
- package/dist/features/index.d.ts +15 -0
- package/dist/features/index.js +53 -0
- package/dist/features/llms-txt.d.ts +11 -0
- package/dist/features/llms-txt.js +13 -0
- package/dist/features/search.d.ts +9 -0
- package/dist/features/search.js +11 -0
- package/dist/features/sidebar-resizer.d.ts +14 -0
- package/dist/features/sidebar-resizer.js +16 -0
- package/dist/features/sidebar-toggle.d.ts +13 -0
- package/dist/features/sidebar-toggle.js +15 -0
- package/dist/features/tag-governance.d.ts +14 -0
- package/dist/features/tag-governance.js +16 -0
- package/dist/features/tauri-dev.d.ts +2 -0
- package/dist/features/tauri-dev.js +25 -0
- package/dist/features/tauri.d.ts +11 -0
- package/dist/features/tauri.js +52 -0
- package/dist/features/versioning.d.ts +27 -0
- package/dist/features/versioning.js +43 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +150 -0
- package/dist/preset.d.ts +37 -0
- package/dist/preset.js +156 -0
- package/dist/prompts.d.ts +32 -0
- package/dist/prompts.js +248 -0
- package/dist/scaffold.d.ts +4 -0
- package/dist/scaffold.js +344 -0
- package/dist/settings-gen.d.ts +2 -0
- package/dist/settings-gen.js +237 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +34 -0
- package/dist/zfb-config-gen.d.ts +19 -0
- package/dist/zfb-config-gen.js +222 -0
- package/package.json +65 -0
- package/templates/base/.htmlvalidate.json +5 -0
- package/templates/base/.zfb/doc-history-meta.json +1 -0
- package/templates/base/pages/404.tsx +55 -0
- package/templates/base/pages/_data.ts +179 -0
- package/templates/base/pages/_mdx-components.ts +249 -0
- package/templates/base/pages/docs/[...slug].tsx +448 -0
- package/templates/base/pages/index.tsx +158 -0
- package/templates/base/pages/lib/_body-end-islands.tsx +201 -0
- package/templates/base/pages/lib/_category-nav.tsx +148 -0
- package/templates/base/pages/lib/_category-tree-nav.tsx +104 -0
- package/templates/base/pages/lib/_compose-meta-title.ts +29 -0
- package/templates/base/pages/lib/_details.tsx +30 -0
- package/templates/base/pages/lib/_doc-history-area.tsx +178 -0
- package/templates/base/pages/lib/_doc-metainfo-area.tsx +100 -0
- package/templates/base/pages/lib/_doc-tags-area.tsx +89 -0
- package/templates/base/pages/lib/_extract-headings.ts +81 -0
- package/templates/base/pages/lib/_footer-with-defaults.tsx +234 -0
- package/templates/base/pages/lib/_frontmatter-preview-data.ts +53 -0
- package/templates/base/pages/lib/_head-with-defaults.tsx +113 -0
- package/templates/base/pages/lib/_header-with-defaults.tsx +386 -0
- package/templates/base/pages/lib/_inline-version-switcher.tsx +84 -0
- package/templates/base/pages/lib/_math-block.tsx +63 -0
- package/templates/base/pages/lib/_nav-source-docs.ts +68 -0
- package/templates/base/pages/lib/_preset-generator.tsx +81 -0
- package/templates/base/pages/lib/_search-widget-script.ts +388 -0
- package/templates/base/pages/lib/_search-widget.tsx +196 -0
- package/templates/base/pages/lib/_sidebar-with-defaults.tsx +176 -0
- package/templates/base/pages/lib/_site-tree-nav.tsx +128 -0
- package/templates/base/pages/lib/locale-merge.ts +58 -0
- package/templates/base/pages/lib/route-enumerators.ts +302 -0
- package/templates/base/pages/sitemap.xml.tsx +51 -0
- package/templates/base/plugins/connect-adapter.mjs +144 -0
- package/templates/base/plugins/copy-public-plugin.mjs +50 -0
- package/templates/base/plugins/search-index-plugin.mjs +54 -0
- package/templates/base/scripts/run-b4push.sh +102 -0
- package/templates/base/src/components/ai-chat-modal.tsx +15 -0
- package/templates/base/src/components/client-router-bootstrap.tsx +14 -0
- package/templates/base/src/components/content/component-map.ts +25 -0
- package/templates/base/src/components/content/content-blockquote.tsx +16 -0
- package/templates/base/src/components/content/content-code.tsx +117 -0
- package/templates/base/src/components/content/content-link.tsx +83 -0
- package/templates/base/src/components/content/content-ol.tsx +19 -0
- package/templates/base/src/components/content/content-paragraph.tsx +10 -0
- package/templates/base/src/components/content/content-strong.tsx +16 -0
- package/templates/base/src/components/content/content-table.tsx +18 -0
- package/templates/base/src/components/content/content-ul.tsx +18 -0
- package/templates/base/src/components/content/heading-h2.tsx +26 -0
- package/templates/base/src/components/content/heading-h3.tsx +26 -0
- package/templates/base/src/components/content/heading-h4.tsx +26 -0
- package/templates/base/src/components/design-token-panel-bootstrap.tsx +15 -0
- package/templates/base/src/components/desktop-sidebar-toggle.tsx +15 -0
- package/templates/base/src/components/doc-history.tsx +18 -0
- package/templates/base/src/components/html-preview/highlighted-code.tsx +74 -0
- package/templates/base/src/components/html-preview/html-preview.tsx +108 -0
- package/templates/base/src/components/html-preview/preflight.ts +112 -0
- package/templates/base/src/components/html-preview/preview-base.tsx +159 -0
- package/templates/base/src/components/image-enlarge.tsx +19 -0
- package/templates/base/src/components/mobile-toc.tsx +94 -0
- package/templates/base/src/components/preset-generator.tsx +14 -0
- package/templates/base/src/components/sidebar-toggle.tsx +98 -0
- package/templates/base/src/components/sidebar-tree.tsx +543 -0
- package/templates/base/src/components/site-tree-nav.tsx +233 -0
- package/templates/base/src/components/theme-toggle.tsx +93 -0
- package/templates/base/src/components/toc.tsx +63 -0
- package/templates/base/src/components/tree-nav-shared.tsx +71 -0
- package/templates/base/src/config/color-scheme-utils.ts +182 -0
- package/templates/base/src/config/color-schemes.ts +128 -0
- package/templates/base/src/config/frontmatter-preview-defaults.ts +24 -0
- package/templates/base/src/config/frontmatter-preview-renderers.tsx +46 -0
- package/templates/base/src/config/i18n.ts +225 -0
- package/templates/base/src/config/settings-types.ts +162 -0
- package/templates/base/src/config/sidebars.ts +66 -0
- package/templates/base/src/config/tag-vocabulary-types.ts +39 -0
- package/templates/base/src/config/tag-vocabulary.ts +20 -0
- package/templates/base/src/hooks/use-active-heading.ts +133 -0
- package/templates/base/src/plugins/docs-source-map.ts +103 -0
- package/templates/base/src/plugins/hast-utils.ts +10 -0
- package/templates/base/src/plugins/rehype-code-title.ts +50 -0
- package/templates/base/src/plugins/rehype-heading-links.ts +53 -0
- package/templates/base/src/plugins/rehype-image-enlarge.ts +113 -0
- package/templates/base/src/plugins/rehype-mermaid.ts +41 -0
- package/templates/base/src/plugins/rehype-strip-md-extension.ts +58 -0
- package/templates/base/src/plugins/remark-admonitions.ts +99 -0
- package/templates/base/src/plugins/remark-resolve-markdown-links.ts +127 -0
- package/templates/base/src/plugins/url-utils.ts +4 -0
- package/templates/base/src/styles/global.css +1066 -0
- package/templates/base/src/types/docs-entry.ts +39 -0
- package/templates/base/src/types/heading.ts +5 -0
- package/templates/base/src/types/locale.ts +10 -0
- package/templates/base/src/utils/base.ts +139 -0
- package/templates/base/src/utils/content-files.ts +106 -0
- package/templates/base/src/utils/dedent.ts +24 -0
- package/templates/base/src/utils/docs.ts +335 -0
- package/templates/base/src/utils/git-info.ts +70 -0
- package/templates/base/src/utils/github.ts +19 -0
- package/templates/base/src/utils/header-right-items.ts +38 -0
- package/templates/base/src/utils/nav-scope.ts +63 -0
- package/templates/base/src/utils/sidebar.ts +104 -0
- package/templates/base/src/utils/slug.ts +10 -0
- package/templates/base/src/utils/smart-break.tsx +126 -0
- package/templates/base/src/utils/tags.ts +126 -0
- package/templates/base/tsconfig.json +36 -0
- package/templates/features/bodyFootUtil/files/src/utils/github.ts +19 -0
- package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +137 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +34 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +376 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +93 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +586 -0
- package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +15 -0
- package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +99 -0
- package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +177 -0
- package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +50 -0
- package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +99 -0
- package/templates/features/docHistory/files/src/components/doc-history.tsx +598 -0
- package/templates/features/docHistory/files/src/types/doc-history.ts +23 -0
- package/templates/features/docHistory/files/src/utils/doc-history.ts +180 -0
- package/templates/features/docTags/files/pages/[locale]/docs/tags/[tag].tsx +116 -0
- package/templates/features/docTags/files/pages/[locale]/docs/tags/index.tsx +99 -0
- package/templates/features/docTags/files/pages/docs/tags/[tag].tsx +101 -0
- package/templates/features/docTags/files/pages/docs/tags/index.tsx +86 -0
- package/templates/features/i18n/files/pages/[locale]/docs/[...slug].tsx +467 -0
- package/templates/features/i18n/files/pages/[locale]/index.tsx +213 -0
- package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +248 -0
- package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +74 -0
- package/templates/features/sidebarResizer/files/src/scripts/sidebar-resizer.ts +185 -0
- package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +126 -0
- package/templates/features/tagGovernance/files/scripts/tags-audit.ts +576 -0
- package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +428 -0
- package/templates/features/tauri/files/src/components/find-bar.tsx +122 -0
- package/templates/features/tauri/files/src/components/find-in-page-init.tsx +53 -0
- package/templates/features/tauri/files/src/utils/find-in-page.ts +175 -0
- package/templates/features/tauri/files/src-tauri/Cargo.toml +14 -0
- package/templates/features/tauri/files/src-tauri/build.rs +3 -0
- package/templates/features/tauri/files/src-tauri/capabilities/default.json +11 -0
- package/templates/features/tauri/files/src-tauri/src/main.rs +250 -0
- package/templates/features/tauri/files/src-tauri/tauri.conf.json +25 -0
- package/templates/features/tauriDev/files/src-tauri-dev/Cargo.toml +15 -0
- package/templates/features/tauriDev/files/src-tauri-dev/build.rs +3 -0
- package/templates/features/tauriDev/files/src-tauri-dev/capabilities/default.json +7 -0
- package/templates/features/tauriDev/files/src-tauri-dev/frontend/index.html +187 -0
- package/templates/features/tauriDev/files/src-tauri-dev/icons/icon.png +0 -0
- package/templates/features/tauriDev/files/src-tauri-dev/src/main.rs +995 -0
- package/templates/features/tauriDev/files/src-tauri-dev/tauri.conf.json +22 -0
- package/templates/features/tauriDev/files/src-tauri-dev/test-launch.sh +65 -0
- package/templates/features/versioning/files/pages/[locale]/docs/versions.tsx +100 -0
- package/templates/features/versioning/files/pages/docs/versions.tsx +78 -0
- package/templates/features/versioning/files/pages/v/[version]/docs/[...slug].tsx +451 -0
- package/templates/features/versioning/files/pages/v/[version]/ja/docs/[...slug].tsx +490 -0
package/dist/compose.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Anchor patterns
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
/**
|
|
7
|
+
* Regex that matches any line containing an @slot anchor comment.
|
|
8
|
+
*
|
|
9
|
+
* Matches all anchor forms used across the template files:
|
|
10
|
+
* - `// @slot:…` — TypeScript/JS line comment (module scope)
|
|
11
|
+
* - `/* @slot:… *\/` — block comment
|
|
12
|
+
* - `{/* @slot:… *\/}` — JSX expression comment (body region in .tsx)
|
|
13
|
+
* - `<!-- @slot:… -->` — HTML comment (legacy .astro body region)
|
|
14
|
+
* - `# @slot:…` — shell / YAML comment
|
|
15
|
+
*/
|
|
16
|
+
const ANCHOR_LINE_RE = /^[ \t]*(?:\{\/\*|\/\/|\/\*|<!--|#)\s*@slot:[^\n]*(?:\*\/\}|\*\/|-->)?[ \t]*\r?\n?$/gm;
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Core functions
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/**
|
|
21
|
+
* Apply a list of injections to files in the target directory.
|
|
22
|
+
*
|
|
23
|
+
* Injections are grouped by target file and applied in array order.
|
|
24
|
+
* For "before"/"after" modes the content is inserted relative to the anchor
|
|
25
|
+
* line. For "replace" mode, the content replaces everything between the
|
|
26
|
+
* `:start` and `:end` anchors (exclusive — the anchor lines themselves are
|
|
27
|
+
* also removed).
|
|
28
|
+
*/
|
|
29
|
+
export async function applyInjections(targetDir, injections) {
|
|
30
|
+
// Group injections by target file
|
|
31
|
+
const byFile = new Map();
|
|
32
|
+
for (const inj of injections) {
|
|
33
|
+
const list = byFile.get(inj.file) ?? [];
|
|
34
|
+
list.push(inj);
|
|
35
|
+
byFile.set(inj.file, list);
|
|
36
|
+
}
|
|
37
|
+
for (const [relPath, fileInjections] of byFile) {
|
|
38
|
+
const filePath = path.join(targetDir, relPath);
|
|
39
|
+
if (!(await fs.pathExists(filePath)))
|
|
40
|
+
continue;
|
|
41
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
42
|
+
for (const inj of fileInjections) {
|
|
43
|
+
const mode = inj.position ?? "before";
|
|
44
|
+
if (mode === "replace") {
|
|
45
|
+
// Range-based replacement: find :start and :end anchors
|
|
46
|
+
const startAnchor = inj.anchor; // must end with :start
|
|
47
|
+
const endAnchor = inj.anchor.replace(/:start\b/, ":end");
|
|
48
|
+
const startIdx = content.indexOf(startAnchor);
|
|
49
|
+
const endIdx = content.indexOf(endAnchor);
|
|
50
|
+
if (startIdx === -1 || endIdx === -1)
|
|
51
|
+
continue;
|
|
52
|
+
// Find the full lines containing the anchors
|
|
53
|
+
const startLineBegin = content.lastIndexOf("\n", startIdx) + 1;
|
|
54
|
+
const endLineEnd = content.indexOf("\n", endIdx);
|
|
55
|
+
const actualEnd = endLineEnd === -1 ? content.length : endLineEnd + 1;
|
|
56
|
+
content =
|
|
57
|
+
content.slice(0, startLineBegin) +
|
|
58
|
+
inj.content +
|
|
59
|
+
(inj.content.endsWith("\n") ? "" : "\n") +
|
|
60
|
+
content.slice(actualEnd);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// before / after: find the anchor line and insert relative to it
|
|
64
|
+
const anchorIdx = content.indexOf(inj.anchor);
|
|
65
|
+
if (anchorIdx === -1)
|
|
66
|
+
continue;
|
|
67
|
+
const lineStart = content.lastIndexOf("\n", anchorIdx) + 1;
|
|
68
|
+
const lineEnd = content.indexOf("\n", anchorIdx);
|
|
69
|
+
const actualLineEnd = lineEnd === -1 ? content.length : lineEnd + 1;
|
|
70
|
+
if (mode === "before") {
|
|
71
|
+
content =
|
|
72
|
+
content.slice(0, lineStart) +
|
|
73
|
+
inj.content +
|
|
74
|
+
(inj.content.endsWith("\n") ? "" : "\n") +
|
|
75
|
+
content.slice(lineStart);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// after
|
|
79
|
+
content =
|
|
80
|
+
content.slice(0, actualLineEnd) +
|
|
81
|
+
inj.content +
|
|
82
|
+
(inj.content.endsWith("\n") ? "" : "\n") +
|
|
83
|
+
content.slice(actualLineEnd);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
await fs.writeFile(filePath, content);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Remove all remaining `@slot:` anchor lines from files in the target
|
|
92
|
+
* directory. Call this after all injections have been applied so that
|
|
93
|
+
* unused anchors don't appear in the generated project.
|
|
94
|
+
*/
|
|
95
|
+
export async function cleanAnchors(targetDir, files) {
|
|
96
|
+
for (const relPath of files) {
|
|
97
|
+
const filePath = path.join(targetDir, relPath);
|
|
98
|
+
if (!(await fs.pathExists(filePath)))
|
|
99
|
+
continue;
|
|
100
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
101
|
+
let cleaned = content.replace(ANCHOR_LINE_RE, "");
|
|
102
|
+
// Collapse runs of 3+ consecutive newlines down to 2 (one blank line)
|
|
103
|
+
cleaned = cleaned.replace(/\n{3,}/g, "\n\n");
|
|
104
|
+
if (cleaned !== content) {
|
|
105
|
+
await fs.writeFile(filePath, cleaned);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Copy a feature's files into the target directory.
|
|
111
|
+
* `featureFilesDir` is the absolute path to the feature's `files/` directory.
|
|
112
|
+
* Each file inside mirrors the project directory structure.
|
|
113
|
+
*/
|
|
114
|
+
export async function copyFeatureFiles(featureFilesDir, targetDir) {
|
|
115
|
+
if (!(await fs.pathExists(featureFilesDir)))
|
|
116
|
+
return;
|
|
117
|
+
await fs.copy(featureFilesDir, targetDir, { overwrite: true });
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Resolve which features are selected based on UserChoices.
|
|
121
|
+
* Handles special cases like the footer pseudo-feature.
|
|
122
|
+
*/
|
|
123
|
+
export function resolveSelectedFeatures(choices, featureModules) {
|
|
124
|
+
const selected = [];
|
|
125
|
+
for (const [name, moduleFn] of Object.entries(featureModules)) {
|
|
126
|
+
// Special case: footer is activated by footerNavGroup, footerCopyright,
|
|
127
|
+
// or footerTaglist (the taglist renders inside the same footer grid).
|
|
128
|
+
if (name === "footer") {
|
|
129
|
+
if (choices.features.includes("footerNavGroup") ||
|
|
130
|
+
choices.features.includes("footerCopyright") ||
|
|
131
|
+
choices.features.includes("footerTaglist")) {
|
|
132
|
+
selected.push(moduleFn(choices));
|
|
133
|
+
}
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (choices.features.includes(name)) {
|
|
137
|
+
selected.push(moduleFn(choices));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return selected;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Validate that all feature dependencies are satisfied.
|
|
144
|
+
* Throws if a selected feature depends on one that isn't selected.
|
|
145
|
+
*/
|
|
146
|
+
export function validateDependencies(features, allSelectedNames) {
|
|
147
|
+
for (const feature of features) {
|
|
148
|
+
if (!feature.dependencies)
|
|
149
|
+
continue;
|
|
150
|
+
for (const dep of feature.dependencies) {
|
|
151
|
+
if (!allSelectedNames.has(dep)) {
|
|
152
|
+
throw new Error(`Feature "${feature.name}" requires "${dep}" but it is not selected.`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Files that may contain injection anchors and need cleaning.
|
|
158
|
+
*
|
|
159
|
+
* W7A (#1736): the two `.astro` entries were dropped — those files no
|
|
160
|
+
* longer exist in generated projects after the post-cutover .tsx
|
|
161
|
+
* migration. The only surviving anchor target is `global.css`, where
|
|
162
|
+
* `design-token-panel.ts` injects `@import "@takazudo/zdtp/styles.css";`
|
|
163
|
+
* at `@slot:global-css:feature-styles`. The sibling
|
|
164
|
+
* `@slot:global-css:theme-tokens` anchor in the same file is consumed
|
|
165
|
+
* by the color-scheme palette generator and must remain. The .tsx
|
|
166
|
+
* anchor form is still supported in `ANCHOR_LINE_RE` for forward
|
|
167
|
+
* compatibility, but no current feature uses it.
|
|
168
|
+
*/
|
|
169
|
+
export const ANCHOR_FILES = ["src/styles/global.css"];
|
|
170
|
+
/**
|
|
171
|
+
* Main composition entry point. Orchestrates the full feature composition
|
|
172
|
+
* pipeline for a generated project.
|
|
173
|
+
*
|
|
174
|
+
* 1. Resolve selected features
|
|
175
|
+
* 2. Validate dependencies
|
|
176
|
+
* 3. Copy feature files
|
|
177
|
+
* 4. Apply all injections
|
|
178
|
+
* 5. Run post-processing hooks
|
|
179
|
+
* 6. Clean up unused anchors
|
|
180
|
+
*/
|
|
181
|
+
export async function composeFeatures(targetDir, choices, featureModules, featuresDir) {
|
|
182
|
+
// 1. Resolve
|
|
183
|
+
const features = resolveSelectedFeatures(choices, featureModules);
|
|
184
|
+
const selectedNames = new Set(features.map((f) => f.name));
|
|
185
|
+
// 2. Validate
|
|
186
|
+
validateDependencies(features, selectedNames);
|
|
187
|
+
// 3. Copy feature files
|
|
188
|
+
for (const feature of features) {
|
|
189
|
+
const filesDir = path.join(featuresDir, feature.name, "files");
|
|
190
|
+
await copyFeatureFiles(filesDir, targetDir);
|
|
191
|
+
}
|
|
192
|
+
// 4. Collect and apply all injections
|
|
193
|
+
const allInjections = [];
|
|
194
|
+
for (const feature of features) {
|
|
195
|
+
allInjections.push(...feature.injections);
|
|
196
|
+
}
|
|
197
|
+
await applyInjections(targetDir, allInjections);
|
|
198
|
+
// 5. Post-processing
|
|
199
|
+
for (const feature of features) {
|
|
200
|
+
if (feature.postProcess) {
|
|
201
|
+
await feature.postProcess(targetDir, choices);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// 6. Clean up unused anchors
|
|
205
|
+
await cleanAnchors(targetDir, ANCHOR_FILES);
|
|
206
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface LightDarkPairing {
|
|
2
|
+
light: string;
|
|
3
|
+
dark: string;
|
|
4
|
+
label: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const LIGHT_DARK_PAIRINGS: LightDarkPairing[];
|
|
7
|
+
export declare const SINGLE_SCHEMES: string[];
|
|
8
|
+
export interface SupportedLang {
|
|
9
|
+
value: string;
|
|
10
|
+
label: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const SUPPORTED_LANGS: SupportedLang[];
|
|
13
|
+
export interface Feature {
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
hint: string;
|
|
17
|
+
default: boolean;
|
|
18
|
+
cliFlag: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const FEATURES: Feature[];
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
export const LIGHT_DARK_PAIRINGS = [
|
|
2
|
+
{ light: "Default Light", dark: "Default Dark", label: "Default" },
|
|
3
|
+
{ light: "GitHub Light", dark: "GitHub Dark", label: "GitHub" },
|
|
4
|
+
{ light: "Catppuccin Latte", dark: "Catppuccin Mocha", label: "Catppuccin" },
|
|
5
|
+
{ light: "Solarized Light", dark: "Solarized Dark", label: "Solarized" },
|
|
6
|
+
{ light: "Rose Pine Dawn", dark: "Rose Pine", label: "Rosé Pine" },
|
|
7
|
+
{ light: "Atom One Light", dark: "Atom One Dark", label: "Atom One" },
|
|
8
|
+
{ light: "Everforest Light", dark: "Everforest Dark", label: "Everforest" },
|
|
9
|
+
{ light: "Gruvbox Light", dark: "Gruvbox Dark", label: "Gruvbox" },
|
|
10
|
+
{ light: "Ayu Light", dark: "Ayu Dark", label: "Ayu" },
|
|
11
|
+
];
|
|
12
|
+
// All available single schemes (dark ones most popular first)
|
|
13
|
+
export const SINGLE_SCHEMES = [
|
|
14
|
+
"Default Dark",
|
|
15
|
+
"Dracula",
|
|
16
|
+
"Catppuccin Mocha",
|
|
17
|
+
"GitHub Dark",
|
|
18
|
+
"Nord",
|
|
19
|
+
"TokyoNight",
|
|
20
|
+
"Gruvbox Dark",
|
|
21
|
+
"Atom One Dark",
|
|
22
|
+
"Rose Pine",
|
|
23
|
+
"Solarized Dark",
|
|
24
|
+
"Material Ocean",
|
|
25
|
+
"Monokai Pro",
|
|
26
|
+
"Everforest Dark",
|
|
27
|
+
"Kanagawa Wave",
|
|
28
|
+
"Night Owl",
|
|
29
|
+
"Ayu Dark",
|
|
30
|
+
"VS Code Dark+",
|
|
31
|
+
"Doom One",
|
|
32
|
+
"Challenger Deep",
|
|
33
|
+
"Catppuccin Frappe",
|
|
34
|
+
"Catppuccin Macchiato",
|
|
35
|
+
"Gruvbox Dark Hard",
|
|
36
|
+
"Rose Pine Moon",
|
|
37
|
+
"GitHub Dark Dimmed",
|
|
38
|
+
"Ayu Mirage",
|
|
39
|
+
"Material Darker",
|
|
40
|
+
"Material Dark",
|
|
41
|
+
"Monokai Remastered",
|
|
42
|
+
"Monokai Vivid",
|
|
43
|
+
"Monokai Soda",
|
|
44
|
+
"Solarized Dark Higher Contrast",
|
|
45
|
+
"Gruvbox Material Dark",
|
|
46
|
+
"Kanagawa Dragon",
|
|
47
|
+
// Light schemes
|
|
48
|
+
"Default Light",
|
|
49
|
+
"GitHub Light",
|
|
50
|
+
"Catppuccin Latte",
|
|
51
|
+
"Solarized Light",
|
|
52
|
+
"Rose Pine Dawn",
|
|
53
|
+
"Atom One Light",
|
|
54
|
+
"Everforest Light",
|
|
55
|
+
"Gruvbox Light",
|
|
56
|
+
"Ayu Light",
|
|
57
|
+
];
|
|
58
|
+
export const SUPPORTED_LANGS = [
|
|
59
|
+
{ value: "en", label: "English" },
|
|
60
|
+
{ value: "ja", label: "Japanese" },
|
|
61
|
+
{ value: "zh-cn", label: "Chinese (Simplified)" },
|
|
62
|
+
{ value: "zh-tw", label: "Chinese (Traditional)" },
|
|
63
|
+
{ value: "ko", label: "Korean" },
|
|
64
|
+
{ value: "es", label: "Spanish" },
|
|
65
|
+
{ value: "fr", label: "French" },
|
|
66
|
+
{ value: "de", label: "German" },
|
|
67
|
+
{ value: "pt", label: "Portuguese" },
|
|
68
|
+
];
|
|
69
|
+
export const FEATURES = [
|
|
70
|
+
{
|
|
71
|
+
value: "i18n",
|
|
72
|
+
label: "i18n (multi-language)",
|
|
73
|
+
hint: "Add a secondary language",
|
|
74
|
+
default: false,
|
|
75
|
+
cliFlag: "i18n",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
value: "search",
|
|
79
|
+
label: "Pagefind search",
|
|
80
|
+
hint: "Full-text search",
|
|
81
|
+
default: true,
|
|
82
|
+
cliFlag: "search",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
value: "sidebarFilter",
|
|
86
|
+
label: "Sidebar filter",
|
|
87
|
+
hint: "Real-time sidebar filtering",
|
|
88
|
+
default: true,
|
|
89
|
+
cliFlag: "sidebar-filter",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
value: "claudeResources",
|
|
93
|
+
label: "Claude Resources",
|
|
94
|
+
hint: "Auto-generate Claude Code docs",
|
|
95
|
+
default: false,
|
|
96
|
+
cliFlag: "claude-resources",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
value: "claudeSkills",
|
|
100
|
+
label: "Claude skills (user-facing)",
|
|
101
|
+
hint: "Ship zudo-doc-* Claude Code skills (design-system, translate, version-bump)",
|
|
102
|
+
default: false,
|
|
103
|
+
cliFlag: "claude-skills",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
value: "designTokenPanel",
|
|
107
|
+
label: "Design Token Panel",
|
|
108
|
+
hint: "Interactive tabbed panel for tweaking spacing, font, size, and color tokens",
|
|
109
|
+
default: false,
|
|
110
|
+
cliFlag: "design-token-panel",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
value: "sidebarResizer",
|
|
114
|
+
label: "Sidebar resizer",
|
|
115
|
+
hint: "Draggable sidebar width",
|
|
116
|
+
default: false,
|
|
117
|
+
cliFlag: "sidebar-resizer",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
value: "sidebarToggle",
|
|
121
|
+
label: "Sidebar toggle",
|
|
122
|
+
hint: "Show/hide desktop sidebar",
|
|
123
|
+
default: false,
|
|
124
|
+
cliFlag: "sidebar-toggle",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
value: "versioning",
|
|
128
|
+
label: "Versioning",
|
|
129
|
+
hint: "Multi-version documentation support",
|
|
130
|
+
default: false,
|
|
131
|
+
cliFlag: "versioning",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
value: "docHistory",
|
|
135
|
+
label: "Document history",
|
|
136
|
+
hint: "Show document edit history",
|
|
137
|
+
default: false,
|
|
138
|
+
cliFlag: "doc-history",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
value: "bodyFootUtil",
|
|
142
|
+
label: "Body foot util area",
|
|
143
|
+
hint: "Right-aligned strip below each doc: doc history trigger + View source on GitHub link",
|
|
144
|
+
default: false,
|
|
145
|
+
cliFlag: "body-foot-util",
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
value: "llmsTxt",
|
|
149
|
+
label: "llms.txt",
|
|
150
|
+
hint: "Generate llms.txt for LLM consumption",
|
|
151
|
+
default: false,
|
|
152
|
+
cliFlag: "llms-txt",
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
value: "skillSymlinker",
|
|
156
|
+
label: "Skill symlinker",
|
|
157
|
+
hint: "Symlink documentation skills",
|
|
158
|
+
default: false,
|
|
159
|
+
cliFlag: "skill-symlinker",
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
value: "tauri",
|
|
163
|
+
label: "Tauri desktop app",
|
|
164
|
+
hint: "macOS desktop wrapper with in-page search",
|
|
165
|
+
default: false,
|
|
166
|
+
cliFlag: "tauri",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
value: "tauriDev",
|
|
170
|
+
label: "Tauri dev wrapper (Mode 2)",
|
|
171
|
+
hint: "Configurable desktop dev wrapper for any project",
|
|
172
|
+
default: false,
|
|
173
|
+
cliFlag: "tauri-dev",
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
value: "footerNavGroup",
|
|
177
|
+
label: "Footer nav group",
|
|
178
|
+
hint: "Navigation links in the footer",
|
|
179
|
+
default: false,
|
|
180
|
+
cliFlag: "footer-nav-group",
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
value: "imageEnlarge",
|
|
184
|
+
label: "Image enlarge",
|
|
185
|
+
hint: "Click-to-enlarge for oversized markdown images",
|
|
186
|
+
default: true,
|
|
187
|
+
cliFlag: "image-enlarge",
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
value: "footerCopyright",
|
|
191
|
+
label: "Footer copyright",
|
|
192
|
+
hint: "Copyright notice in the footer",
|
|
193
|
+
default: false,
|
|
194
|
+
cliFlag: "footer-copyright",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
value: "changelog",
|
|
198
|
+
label: "Changelog",
|
|
199
|
+
hint: "Changelog page",
|
|
200
|
+
default: false,
|
|
201
|
+
cliFlag: "changelog",
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
value: "tagGovernance",
|
|
205
|
+
label: "Tag governance",
|
|
206
|
+
hint: "Vocabulary-aware tag audit + suggest scripts",
|
|
207
|
+
default: true,
|
|
208
|
+
cliFlag: "tag-governance",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
value: "docTags",
|
|
212
|
+
label: "Doc tags pages",
|
|
213
|
+
hint: "Per-tag and tag-index browsing routes (docs/tags/...)",
|
|
214
|
+
default: false,
|
|
215
|
+
cliFlag: "doc-tags",
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
value: "footerTaglist",
|
|
219
|
+
label: "Footer taglist",
|
|
220
|
+
hint: "Grouped tag index in the footer (requires tagGovernance)",
|
|
221
|
+
default: false,
|
|
222
|
+
cliFlag: "footer-taglist",
|
|
223
|
+
},
|
|
224
|
+
];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* body-foot-util feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, the body-foot-util area is hosted by
|
|
6
|
+
* `pages/lib/_doc-history-area.tsx` which wraps `BodyFootUtilArea`
|
|
7
|
+
* unconditionally. The component itself runtime-gates on
|
|
8
|
+
* `settings.bodyFootUtilArea`, so there is nothing to inject.
|
|
9
|
+
*/
|
|
10
|
+
export declare const bodyFootUtilFeature: FeatureModule;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* body-foot-util feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, the body-foot-util area is hosted by
|
|
5
|
+
* `pages/lib/_doc-history-area.tsx` which wraps `BodyFootUtilArea`
|
|
6
|
+
* unconditionally. The component itself runtime-gates on
|
|
7
|
+
* `settings.bodyFootUtilArea`, so there is nothing to inject.
|
|
8
|
+
*/
|
|
9
|
+
export const bodyFootUtilFeature = () => ({
|
|
10
|
+
name: "bodyFootUtil",
|
|
11
|
+
injections: [],
|
|
12
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Design-token-panel (zdtp) feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): keeps the single surviving inject() — the zdtp CSS @import
|
|
6
|
+
* at `@slot:global-css:feature-styles`. The two dead .astro injections
|
|
7
|
+
* (doc-layout bootstrap import + header trigger button) are dropped:
|
|
8
|
+
* the bootstrap is loaded by `pages/lib/design-token-panel-bootstrap`-side
|
|
9
|
+
* effect when the feature is enabled, and the header trigger is now
|
|
10
|
+
* rendered by `pages/lib/_header-with-defaults.tsx` from the
|
|
11
|
+
* `settings.headerRightItems` entry `{ type: "trigger", trigger:
|
|
12
|
+
* "design-token-panel" }`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const designTokenPanelFeature: FeatureModule;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design-token-panel (zdtp) feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): keeps the single surviving inject() — the zdtp CSS @import
|
|
5
|
+
* at `@slot:global-css:feature-styles`. The two dead .astro injections
|
|
6
|
+
* (doc-layout bootstrap import + header trigger button) are dropped:
|
|
7
|
+
* the bootstrap is loaded by `pages/lib/design-token-panel-bootstrap`-side
|
|
8
|
+
* effect when the feature is enabled, and the header trigger is now
|
|
9
|
+
* rendered by `pages/lib/_header-with-defaults.tsx` from the
|
|
10
|
+
* `settings.headerRightItems` entry `{ type: "trigger", trigger:
|
|
11
|
+
* "design-token-panel" }`.
|
|
12
|
+
*/
|
|
13
|
+
export const designTokenPanelFeature = () => ({
|
|
14
|
+
name: "designTokenPanel",
|
|
15
|
+
injections: [
|
|
16
|
+
{
|
|
17
|
+
// Panel chrome CSS — imported here so the rules land in the main page
|
|
18
|
+
// CSS bundle (not a deferred chunk), ensuring the panel renders
|
|
19
|
+
// correctly on first click. Vite library mode strips the source CSS
|
|
20
|
+
// import from the emitted JS, so this CSS-side import is the required
|
|
21
|
+
// pull point. See @takazudo/zdtp PORTABLE-CONTRACT.md §7.
|
|
22
|
+
file: "src/styles/global.css",
|
|
23
|
+
anchor: "/* @slot:global-css:feature-styles */",
|
|
24
|
+
content: `@import "@takazudo/zdtp/styles.css";`,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Doc-history feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, `pages/lib/_doc-history-area.tsx` is mounted
|
|
6
|
+
* unconditionally and self-gates on `settings.docHistory`. The plugin entry
|
|
7
|
+
* is wired by `zfb-config-gen.ts`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const docHistoryFeature: FeatureModule;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doc-history feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, `pages/lib/_doc-history-area.tsx` is mounted
|
|
5
|
+
* unconditionally and self-gates on `settings.docHistory`. The plugin entry
|
|
6
|
+
* is wired by `zfb-config-gen.ts`.
|
|
7
|
+
*/
|
|
8
|
+
export const docHistoryFeature = () => ({
|
|
9
|
+
name: "docHistory",
|
|
10
|
+
injections: [],
|
|
11
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* docTags feature (W7C — #1738).
|
|
4
|
+
*
|
|
5
|
+
* Settings gate: `settings.docTags === true`.
|
|
6
|
+
*
|
|
7
|
+
* Ships feature-conditional pages from
|
|
8
|
+
* `templates/features/docTags/files/pages/`:
|
|
9
|
+
*
|
|
10
|
+
* docs/tags/[tag].tsx
|
|
11
|
+
* docs/tags/index.tsx
|
|
12
|
+
* [locale]/docs/tags/[tag].tsx — only when i18n ALSO selected
|
|
13
|
+
* [locale]/docs/tags/index.tsx — only when i18n ALSO selected
|
|
14
|
+
*
|
|
15
|
+
* `copyFeatureFiles` (compose.ts) auto-emits every file under
|
|
16
|
+
* `files/`; postProcess removes the `[locale]/**` subset when i18n
|
|
17
|
+
* is NOT selected. See W2 spec-lock §Cross-feature interaction.
|
|
18
|
+
*/
|
|
19
|
+
export declare const docTagsFeature: FeatureModule;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* docTags feature (W7C — #1738).
|
|
5
|
+
*
|
|
6
|
+
* Settings gate: `settings.docTags === true`.
|
|
7
|
+
*
|
|
8
|
+
* Ships feature-conditional pages from
|
|
9
|
+
* `templates/features/docTags/files/pages/`:
|
|
10
|
+
*
|
|
11
|
+
* docs/tags/[tag].tsx
|
|
12
|
+
* docs/tags/index.tsx
|
|
13
|
+
* [locale]/docs/tags/[tag].tsx — only when i18n ALSO selected
|
|
14
|
+
* [locale]/docs/tags/index.tsx — only when i18n ALSO selected
|
|
15
|
+
*
|
|
16
|
+
* `copyFeatureFiles` (compose.ts) auto-emits every file under
|
|
17
|
+
* `files/`; postProcess removes the `[locale]/**` subset when i18n
|
|
18
|
+
* is NOT selected. See W2 spec-lock §Cross-feature interaction.
|
|
19
|
+
*/
|
|
20
|
+
export const docTagsFeature = (choices) => ({
|
|
21
|
+
name: "docTags",
|
|
22
|
+
injections: [],
|
|
23
|
+
postProcess: async (targetDir) => {
|
|
24
|
+
if (!choices.features.includes("i18n")) {
|
|
25
|
+
// i18n is OFF — strip the locale-scoped tag pages that were
|
|
26
|
+
// copied unconditionally by copyFeatureFiles.
|
|
27
|
+
const localeTagsDir = path.join(targetDir, "pages", "[locale]", "docs", "tags");
|
|
28
|
+
if (await fs.pathExists(localeTagsDir)) {
|
|
29
|
+
await fs.remove(localeTagsDir);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Footer taglist feature.
|
|
4
|
+
*
|
|
5
|
+
* Purely a settings toggle: `settings-gen.ts` emits
|
|
6
|
+
* `footer.taglist = { enabled: true, groupBy: "group" }` when selected,
|
|
7
|
+
* and the existing `footer.astro` (part of the footer pseudo-feature) reads
|
|
8
|
+
* `settings.footer.taglist` to decide whether to render the column(s).
|
|
9
|
+
*
|
|
10
|
+
* `footer.astro` is only installed by the footer pseudo-feature, so
|
|
11
|
+
* `resolveSelectedFeatures` treats `footerTaglist` as one of the triggers
|
|
12
|
+
* for that feature.
|
|
13
|
+
*/
|
|
14
|
+
export declare const footerTaglistFeature: FeatureModule;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Footer taglist feature.
|
|
3
|
+
*
|
|
4
|
+
* Purely a settings toggle: `settings-gen.ts` emits
|
|
5
|
+
* `footer.taglist = { enabled: true, groupBy: "group" }` when selected,
|
|
6
|
+
* and the existing `footer.astro` (part of the footer pseudo-feature) reads
|
|
7
|
+
* `settings.footer.taglist` to decide whether to render the column(s).
|
|
8
|
+
*
|
|
9
|
+
* `footer.astro` is only installed by the footer pseudo-feature, so
|
|
10
|
+
* `resolveSelectedFeatures` treats `footerTaglist` as one of the triggers
|
|
11
|
+
* for that feature.
|
|
12
|
+
*/
|
|
13
|
+
export const footerTaglistFeature = () => ({
|
|
14
|
+
name: "footerTaglist",
|
|
15
|
+
injections: [],
|
|
16
|
+
dependencies: ["tagGovernance"],
|
|
17
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Footer pseudo-feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, `pages/lib/_footer-with-defaults.tsx` mounts
|
|
6
|
+
* the footer unconditionally — no doc-layout injection is required.
|
|
7
|
+
*/
|
|
8
|
+
export declare const footerFeature: FeatureModule;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Footer pseudo-feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, `pages/lib/_footer-with-defaults.tsx` mounts
|
|
5
|
+
* the footer unconditionally — no doc-layout injection is required.
|
|
6
|
+
*/
|
|
7
|
+
export const footerFeature = () => ({
|
|
8
|
+
name: "footer",
|
|
9
|
+
injections: [],
|
|
10
|
+
});
|