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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* i18n feature — gates the locale-prefixed page set.
|
|
4
|
+
*
|
|
5
|
+
* Page templates are shipped under `templates/features/i18n/files/pages/`
|
|
6
|
+
* and copied by `composeFeatures → copyFeatureFiles` whenever `i18n` is in
|
|
7
|
+
* the selected feature set.
|
|
8
|
+
*
|
|
9
|
+
* No injections: header / language-switcher wiring was retired with the
|
|
10
|
+
* Astro cutover (#1736 / W7A) — `pages/lib/_header-with-defaults.tsx` now
|
|
11
|
+
* gates `LanguageSwitcher` on `Object.keys(settings.locales).length > 0`.
|
|
12
|
+
* The pages are locale-agnostic — they iterate `settings.locales` at build
|
|
13
|
+
* time, so no postProcess regex patching is required for non-default
|
|
14
|
+
* languages.
|
|
15
|
+
*
|
|
16
|
+
* Loud-failure check: per spec-lock Decision 8 (#1737), abort scaffolding
|
|
17
|
+
* if the feature template dir is missing or empty. Without this guard,
|
|
18
|
+
* `copyFeatureFiles` silently no-ops on a missing dir (l-lessons line 790)
|
|
19
|
+
* and the user receives a half-scaffolded project with `i18n` enabled in
|
|
20
|
+
* settings but no `[locale]/**` pages.
|
|
21
|
+
*/
|
|
22
|
+
export declare const i18nFeature: FeatureModule;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
/**
|
|
5
|
+
* i18n feature — gates the locale-prefixed page set.
|
|
6
|
+
*
|
|
7
|
+
* Page templates are shipped under `templates/features/i18n/files/pages/`
|
|
8
|
+
* and copied by `composeFeatures → copyFeatureFiles` whenever `i18n` is in
|
|
9
|
+
* the selected feature set.
|
|
10
|
+
*
|
|
11
|
+
* No injections: header / language-switcher wiring was retired with the
|
|
12
|
+
* Astro cutover (#1736 / W7A) — `pages/lib/_header-with-defaults.tsx` now
|
|
13
|
+
* gates `LanguageSwitcher` on `Object.keys(settings.locales).length > 0`.
|
|
14
|
+
* The pages are locale-agnostic — they iterate `settings.locales` at build
|
|
15
|
+
* time, so no postProcess regex patching is required for non-default
|
|
16
|
+
* languages.
|
|
17
|
+
*
|
|
18
|
+
* Loud-failure check: per spec-lock Decision 8 (#1737), abort scaffolding
|
|
19
|
+
* if the feature template dir is missing or empty. Without this guard,
|
|
20
|
+
* `copyFeatureFiles` silently no-ops on a missing dir (l-lessons line 790)
|
|
21
|
+
* and the user receives a half-scaffolded project with `i18n` enabled in
|
|
22
|
+
* settings but no `[locale]/**` pages.
|
|
23
|
+
*/
|
|
24
|
+
export const i18nFeature = (_choices) => {
|
|
25
|
+
const featuresRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", // up from features/ to src/
|
|
26
|
+
"..", // up from src/ to package root
|
|
27
|
+
"templates/features");
|
|
28
|
+
const pagesDir = path.join(featuresRoot, "i18n/files/pages");
|
|
29
|
+
// Check existence + directory-ness before readdir so a stray file at this
|
|
30
|
+
// path produces the same loud error rather than an opaque ENOTDIR.
|
|
31
|
+
const stat = fs.existsSync(pagesDir) ? fs.statSync(pagesDir) : null;
|
|
32
|
+
if (!stat || !stat.isDirectory() || fs.readdirSync(pagesDir).length === 0) {
|
|
33
|
+
throw new Error(`i18n feature template dir is missing or empty: ${pagesDir}\n` +
|
|
34
|
+
`Expected to find [locale]/index.tsx and [locale]/docs/[...slug].tsx.\n` +
|
|
35
|
+
`This is a generator bug — please file an issue.`);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
name: "i18n",
|
|
39
|
+
injections: [],
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Image-enlarge feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, the image-enlarge island is mounted by the
|
|
6
|
+
* pages/lib body-end wrapper (always present; runtime-gated via the
|
|
7
|
+
* always-loaded stub-or-real ImageEnlarge component). Image-enlarge CSS
|
|
8
|
+
* lives unconditionally in `templates/base/src/styles/global.css` — the
|
|
9
|
+
* selectors only activate when the runtime mounts the .zd-enlarge-btn.
|
|
10
|
+
*/
|
|
11
|
+
export declare const imageEnlargeFeature: FeatureModule;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-enlarge feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, the image-enlarge island is mounted by the
|
|
5
|
+
* pages/lib body-end wrapper (always present; runtime-gated via the
|
|
6
|
+
* always-loaded stub-or-real ImageEnlarge component). Image-enlarge CSS
|
|
7
|
+
* lives unconditionally in `templates/base/src/styles/global.css` — the
|
|
8
|
+
* selectors only activate when the runtime mounts the .zd-enlarge-btn.
|
|
9
|
+
*/
|
|
10
|
+
export const imageEnlargeFeature = () => ({
|
|
11
|
+
name: "imageEnlarge",
|
|
12
|
+
injections: [],
|
|
13
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature modules for the scaffold composition engine.
|
|
3
|
+
*
|
|
4
|
+
* Each module is a FeatureModule function that returns a FeatureDefinition
|
|
5
|
+
* based on user choices. The definition includes:
|
|
6
|
+
* - injections: code to inject into shared files at anchor points
|
|
7
|
+
* - postProcess: optional hook for complex transformations
|
|
8
|
+
*/
|
|
9
|
+
import type { FeatureModule } from "../compose.js";
|
|
10
|
+
/**
|
|
11
|
+
* All feature modules keyed by their feature name.
|
|
12
|
+
* The "footer" key is a pseudo-feature triggered by footerNavGroup or footerCopyright.
|
|
13
|
+
* Order matches FEATURES array in constants.ts for deterministic injection.
|
|
14
|
+
*/
|
|
15
|
+
export declare const featureModules: Record<string, FeatureModule>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature modules for the scaffold composition engine.
|
|
3
|
+
*
|
|
4
|
+
* Each module is a FeatureModule function that returns a FeatureDefinition
|
|
5
|
+
* based on user choices. The definition includes:
|
|
6
|
+
* - injections: code to inject into shared files at anchor points
|
|
7
|
+
* - postProcess: optional hook for complex transformations
|
|
8
|
+
*/
|
|
9
|
+
import { searchFeature } from "./search.js";
|
|
10
|
+
import { footerFeature } from "./footer.js";
|
|
11
|
+
import { sidebarResizerFeature } from "./sidebar-resizer.js";
|
|
12
|
+
import { sidebarToggleFeature } from "./sidebar-toggle.js";
|
|
13
|
+
import { docHistoryFeature } from "./doc-history.js";
|
|
14
|
+
import { llmsTxtFeature } from "./llms-txt.js";
|
|
15
|
+
import { claudeResourcesFeature } from "./claude-resources.js";
|
|
16
|
+
import { designTokenPanelFeature } from "./design-token-panel.js";
|
|
17
|
+
import { i18nFeature } from "./i18n.js";
|
|
18
|
+
import { versioningFeature } from "./versioning.js";
|
|
19
|
+
import { tauriFeature } from "./tauri.js";
|
|
20
|
+
import { tauriDevFeature } from "./tauri-dev.js";
|
|
21
|
+
import { imageEnlargeFeature } from "./image-enlarge.js";
|
|
22
|
+
import { tagGovernanceFeature } from "./tag-governance.js";
|
|
23
|
+
import { footerTaglistFeature } from "./footer-taglist.js";
|
|
24
|
+
import { bodyFootUtilFeature } from "./body-foot-util.js";
|
|
25
|
+
import { docTagsFeature } from "./doc-tags.js";
|
|
26
|
+
/**
|
|
27
|
+
* All feature modules keyed by their feature name.
|
|
28
|
+
* The "footer" key is a pseudo-feature triggered by footerNavGroup or footerCopyright.
|
|
29
|
+
* Order matches FEATURES array in constants.ts for deterministic injection.
|
|
30
|
+
*/
|
|
31
|
+
export const featureModules = {
|
|
32
|
+
i18n: i18nFeature,
|
|
33
|
+
search: searchFeature,
|
|
34
|
+
// sidebarFilter — built into sidebar-tree.tsx, stays in base
|
|
35
|
+
claudeResources: claudeResourcesFeature,
|
|
36
|
+
designTokenPanel: designTokenPanelFeature,
|
|
37
|
+
sidebarResizer: sidebarResizerFeature,
|
|
38
|
+
sidebarToggle: sidebarToggleFeature,
|
|
39
|
+
versioning: versioningFeature,
|
|
40
|
+
docHistory: docHistoryFeature,
|
|
41
|
+
bodyFootUtil: bodyFootUtilFeature,
|
|
42
|
+
llmsTxt: llmsTxtFeature,
|
|
43
|
+
tauri: tauriFeature,
|
|
44
|
+
tauriDev: tauriDevFeature,
|
|
45
|
+
imageEnlarge: imageEnlargeFeature,
|
|
46
|
+
// skillSymlinker — handled in scaffold.ts
|
|
47
|
+
// claudeSkills — handled in scaffold.ts (copies zudo-doc-* skills from monorepo)
|
|
48
|
+
tagGovernance: tagGovernanceFeature,
|
|
49
|
+
docTags: docTagsFeature,
|
|
50
|
+
footerTaglist: footerTaglistFeature,
|
|
51
|
+
footer: footerFeature, // pseudo-feature: triggered by footerNavGroup, footerCopyright, or footerTaglist
|
|
52
|
+
// changelog — handled in scaffold.ts
|
|
53
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* llms-txt feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): the inject() that previously added `<link rel="alternate">`
|
|
6
|
+
* tags to `<head>` is dropped per locked spec §6.3 — `_head-with-defaults.tsx`
|
|
7
|
+
* does not emit those tags today (neither does host). If a follow-up decides
|
|
8
|
+
* to emit them, add the gated `<link>` rendering inside `_head-with-defaults.tsx`
|
|
9
|
+
* — not in a feature inject. The plugin itself is wired by `zfb-config-gen.ts`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const llmsTxtFeature: FeatureModule;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* llms-txt feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): the inject() that previously added `<link rel="alternate">`
|
|
5
|
+
* tags to `<head>` is dropped per locked spec §6.3 — `_head-with-defaults.tsx`
|
|
6
|
+
* does not emit those tags today (neither does host). If a follow-up decides
|
|
7
|
+
* to emit them, add the gated `<link>` rendering inside `_head-with-defaults.tsx`
|
|
8
|
+
* — not in a feature inject. The plugin itself is wired by `zfb-config-gen.ts`.
|
|
9
|
+
*/
|
|
10
|
+
export const llmsTxtFeature = () => ({
|
|
11
|
+
name: "llmsTxt",
|
|
12
|
+
injections: [],
|
|
13
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Search feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, `pages/lib/_header-with-defaults.tsx` includes
|
|
6
|
+
* the search widget unconditionally — no header injection is required.
|
|
7
|
+
* The search-index plugin is still wired by `zfb-config-gen.ts`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const searchFeature: FeatureModule;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, `pages/lib/_header-with-defaults.tsx` includes
|
|
5
|
+
* the search widget unconditionally — no header injection is required.
|
|
6
|
+
* The search-index plugin is still wired by `zfb-config-gen.ts`.
|
|
7
|
+
*/
|
|
8
|
+
export const searchFeature = () => ({
|
|
9
|
+
name: "search",
|
|
10
|
+
injections: [],
|
|
11
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Sidebar-resizer feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, sidebar resizer pre-paint scripts and runtime
|
|
6
|
+
* initialization are runtime-gated on `settings.sidebarResizer` inside the
|
|
7
|
+
* pages/lib wrappers — no doc-layout injection is required.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: spec-lock §6.5 flagged a pre-paint FOUC question for the
|
|
10
|
+
* `applySidebarWidth` IIFE that previously ran inline in the layout `<head>`.
|
|
11
|
+
* The post-cutover model relies on the pages/lib head wrapper emitting the
|
|
12
|
+
* inline script (when present); this feature module no longer injects it.
|
|
13
|
+
*/
|
|
14
|
+
export declare const sidebarResizerFeature: FeatureModule;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar-resizer feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, sidebar resizer pre-paint scripts and runtime
|
|
5
|
+
* initialization are runtime-gated on `settings.sidebarResizer` inside the
|
|
6
|
+
* pages/lib wrappers — no doc-layout injection is required.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: spec-lock §6.5 flagged a pre-paint FOUC question for the
|
|
9
|
+
* `applySidebarWidth` IIFE that previously ran inline in the layout `<head>`.
|
|
10
|
+
* The post-cutover model relies on the pages/lib head wrapper emitting the
|
|
11
|
+
* inline script (when present); this feature module no longer injects it.
|
|
12
|
+
*/
|
|
13
|
+
export const sidebarResizerFeature = () => ({
|
|
14
|
+
name: "sidebarResizer",
|
|
15
|
+
injections: [],
|
|
16
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Sidebar-toggle feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, the sidebar-toggle is hosted by the pages/lib
|
|
6
|
+
* wrappers which runtime-gate on `settings.sidebarToggle`. The supporting
|
|
7
|
+
* CSS (toggle button positioning, sidebar transitions, `[data-sidebar-hidden]`
|
|
8
|
+
* styles) lives unconditionally in `templates/base/src/styles/global.css`
|
|
9
|
+
* — the selectors only match when the runtime attaches the
|
|
10
|
+
* `data-sidebar-hidden` attribute or mounts the toggle button, so the cost
|
|
11
|
+
* to scaffolds without the feature is one inert rule block.
|
|
12
|
+
*/
|
|
13
|
+
export declare const sidebarToggleFeature: FeatureModule;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar-toggle feature.
|
|
3
|
+
*
|
|
4
|
+
* W7A (#1736): post-cutover, the sidebar-toggle is hosted by the pages/lib
|
|
5
|
+
* wrappers which runtime-gate on `settings.sidebarToggle`. The supporting
|
|
6
|
+
* CSS (toggle button positioning, sidebar transitions, `[data-sidebar-hidden]`
|
|
7
|
+
* styles) lives unconditionally in `templates/base/src/styles/global.css`
|
|
8
|
+
* — the selectors only match when the runtime attaches the
|
|
9
|
+
* `data-sidebar-hidden` attribute or mounts the toggle button, so the cost
|
|
10
|
+
* to scaffolds without the feature is one inert rule block.
|
|
11
|
+
*/
|
|
12
|
+
export const sidebarToggleFeature = () => ({
|
|
13
|
+
name: "sidebarToggle",
|
|
14
|
+
injections: [],
|
|
15
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Tag governance feature.
|
|
4
|
+
*
|
|
5
|
+
* Ships the tag audit and suggest scripts. Settings (`tagVocabulary`,
|
|
6
|
+
* `tagGovernance`) are emitted by `settings-gen.ts`; devDeps and
|
|
7
|
+
* `tags:audit` / `tags:suggest` package scripts are added in
|
|
8
|
+
* `scaffold.ts#generatePackageJson`.
|
|
9
|
+
*
|
|
10
|
+
* `src/config/tag-vocabulary.ts` and `tag-vocabulary-types.ts` stay in the
|
|
11
|
+
* base template because `src/utils/tags.ts` and `settings-types.ts` import
|
|
12
|
+
* from them regardless of whether governance is on.
|
|
13
|
+
*/
|
|
14
|
+
export declare const tagGovernanceFeature: FeatureModule;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag governance feature.
|
|
3
|
+
*
|
|
4
|
+
* Ships the tag audit and suggest scripts. Settings (`tagVocabulary`,
|
|
5
|
+
* `tagGovernance`) are emitted by `settings-gen.ts`; devDeps and
|
|
6
|
+
* `tags:audit` / `tags:suggest` package scripts are added in
|
|
7
|
+
* `scaffold.ts#generatePackageJson`.
|
|
8
|
+
*
|
|
9
|
+
* `src/config/tag-vocabulary.ts` and `tag-vocabulary-types.ts` stay in the
|
|
10
|
+
* base template because `src/utils/tags.ts` and `settings-types.ts` import
|
|
11
|
+
* from them regardless of whether governance is on.
|
|
12
|
+
*/
|
|
13
|
+
export const tagGovernanceFeature = () => ({
|
|
14
|
+
name: "tagGovernance",
|
|
15
|
+
injections: [],
|
|
16
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export const tauriDevFeature = (choices) => ({
|
|
4
|
+
name: "tauriDev",
|
|
5
|
+
injections: [],
|
|
6
|
+
postProcess: async (targetDir) => {
|
|
7
|
+
// Patch Cargo.toml package name — use "-dev" suffix to avoid collision with Mode 1 tauri
|
|
8
|
+
const cargoPath = path.join(targetDir, "src-tauri-dev/Cargo.toml");
|
|
9
|
+
if (await fs.pathExists(cargoPath)) {
|
|
10
|
+
let content = await fs.readFile(cargoPath, "utf-8");
|
|
11
|
+
const safeName = choices.projectName.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
12
|
+
content = content.replace(/name = "zudo-doc-dev"/, `name = "${safeName}-dev"`);
|
|
13
|
+
await fs.writeFile(cargoPath, content);
|
|
14
|
+
}
|
|
15
|
+
// Append src-tauri-dev entries to .gitignore
|
|
16
|
+
const gitignorePath = path.join(targetDir, ".gitignore");
|
|
17
|
+
if (await fs.pathExists(gitignorePath)) {
|
|
18
|
+
let content = await fs.readFile(gitignorePath, "utf-8");
|
|
19
|
+
if (!content.includes("src-tauri-dev/target")) {
|
|
20
|
+
content += "\n# Tauri dev wrapper build artifacts\nsrc-tauri-dev/target\nsrc-tauri-dev/gen\n";
|
|
21
|
+
await fs.writeFile(gitignorePath, content);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Tauri feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, the FindInPage island is mounted by the
|
|
6
|
+
* pages/lib body-end wrapper. The find-match highlight CSS is unconditional
|
|
7
|
+
* in `templates/base/src/styles/global.css` (matches host). Only the
|
|
8
|
+
* postProcess hooks (Cargo.toml / tauri.conf.json / .gitignore patches)
|
|
9
|
+
* remain feature-scoped.
|
|
10
|
+
*/
|
|
11
|
+
export declare const tauriFeature: FeatureModule;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Tauri feature.
|
|
5
|
+
*
|
|
6
|
+
* W7A (#1736): post-cutover, the FindInPage island is mounted by the
|
|
7
|
+
* pages/lib body-end wrapper. The find-match highlight CSS is unconditional
|
|
8
|
+
* in `templates/base/src/styles/global.css` (matches host). Only the
|
|
9
|
+
* postProcess hooks (Cargo.toml / tauri.conf.json / .gitignore patches)
|
|
10
|
+
* remain feature-scoped.
|
|
11
|
+
*/
|
|
12
|
+
export const tauriFeature = (choices) => ({
|
|
13
|
+
name: "tauri",
|
|
14
|
+
injections: [],
|
|
15
|
+
postProcess: async (targetDir) => {
|
|
16
|
+
// Patch Cargo.toml package name
|
|
17
|
+
const cargoPath = path.join(targetDir, "src-tauri/Cargo.toml");
|
|
18
|
+
if (await fs.pathExists(cargoPath)) {
|
|
19
|
+
let content = await fs.readFile(cargoPath, "utf-8");
|
|
20
|
+
const safeName = choices.projectName.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
21
|
+
content = content.replace(/name = "zudo-doc"/, `name = "${safeName}"`);
|
|
22
|
+
await fs.writeFile(cargoPath, content);
|
|
23
|
+
}
|
|
24
|
+
// Patch tauri.conf.json productName, identifier, and beforeDevCommand
|
|
25
|
+
const confPath = path.join(targetDir, "src-tauri/tauri.conf.json");
|
|
26
|
+
if (await fs.pathExists(confPath)) {
|
|
27
|
+
let content = await fs.readFile(confPath, "utf-8");
|
|
28
|
+
const productName = choices.projectName
|
|
29
|
+
.split(/[-_]/)
|
|
30
|
+
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
31
|
+
.join("");
|
|
32
|
+
const identifier = `com.example.${choices.projectName.replace(/[^a-zA-Z0-9-]/g, "-")}`;
|
|
33
|
+
content = content.replace(/"productName": "ZudoDoc"/, `"productName": "${productName}"`);
|
|
34
|
+
content = content.replace(/"identifier": "com.zudolab.zudo-doc"/, `"identifier": "${identifier}"`);
|
|
35
|
+
// Patch beforeDevCommand for the chosen package manager
|
|
36
|
+
const devCmd = choices.packageManager === "npm" || choices.packageManager === "bun"
|
|
37
|
+
? `${choices.packageManager} run dev`
|
|
38
|
+
: `${choices.packageManager} dev`;
|
|
39
|
+
content = content.replace(/"beforeDevCommand": "pnpm dev"/, `"beforeDevCommand": "${devCmd}"`);
|
|
40
|
+
await fs.writeFile(confPath, content);
|
|
41
|
+
}
|
|
42
|
+
// Append src-tauri entries to .gitignore
|
|
43
|
+
const gitignorePath = path.join(targetDir, ".gitignore");
|
|
44
|
+
if (await fs.pathExists(gitignorePath)) {
|
|
45
|
+
let content = await fs.readFile(gitignorePath, "utf-8");
|
|
46
|
+
if (!content.includes("src-tauri/target")) {
|
|
47
|
+
content += "\n# Tauri build artifacts\nsrc-tauri/target\nsrc-tauri/gen\n";
|
|
48
|
+
await fs.writeFile(gitignorePath, content);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FeatureModule } from "../compose.js";
|
|
2
|
+
/**
|
|
3
|
+
* Versioning feature.
|
|
4
|
+
*
|
|
5
|
+
* W7A (#1736): post-cutover, the pages/lib wrappers gate `VersionSwitcher`
|
|
6
|
+
* and `VersionBanner` on `settings.versions`. Doc-layout flow is handled by
|
|
7
|
+
* route enumerators + `_inline-version-switcher.tsx`. The .astro inject
|
|
8
|
+
* calls that used to wire this in have been retired (they targeted dead
|
|
9
|
+
* `src/layouts/doc-layout.astro` + `src/components/header.astro` anchors).
|
|
10
|
+
*
|
|
11
|
+
* W7C (#1738): the versioning feature ships pages under
|
|
12
|
+
* `templates/features/versioning/files/pages/`:
|
|
13
|
+
*
|
|
14
|
+
* docs/versions.tsx (always — versioning gate only)
|
|
15
|
+
* v/[version]/docs/[...slug].tsx (always — versioning gate only)
|
|
16
|
+
* v/[version]/ja/docs/[...slug].tsx (i18n + versioning — see below)
|
|
17
|
+
* [locale]/docs/versions.tsx (i18n + versioning)
|
|
18
|
+
*
|
|
19
|
+
* `copyFeatureFiles` (compose.ts) auto-copies everything under `files/`.
|
|
20
|
+
* postProcess removes the i18n-gated subset when i18n is OFF so single-
|
|
21
|
+
* locale projects don't ship orphan routes.
|
|
22
|
+
*
|
|
23
|
+
* Note: `v/[version]/ja/docs/[...slug].tsx` hardcodes `ja` per W2 spec-lock
|
|
24
|
+
* Decision 9 / §6.4 — matches main verbatim. Future generalization to
|
|
25
|
+
* `[locale]` is deferred (maintainer-question follow-up).
|
|
26
|
+
*/
|
|
27
|
+
export declare const versioningFeature: FeatureModule;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Versioning feature.
|
|
5
|
+
*
|
|
6
|
+
* W7A (#1736): post-cutover, the pages/lib wrappers gate `VersionSwitcher`
|
|
7
|
+
* and `VersionBanner` on `settings.versions`. Doc-layout flow is handled by
|
|
8
|
+
* route enumerators + `_inline-version-switcher.tsx`. The .astro inject
|
|
9
|
+
* calls that used to wire this in have been retired (they targeted dead
|
|
10
|
+
* `src/layouts/doc-layout.astro` + `src/components/header.astro` anchors).
|
|
11
|
+
*
|
|
12
|
+
* W7C (#1738): the versioning feature ships pages under
|
|
13
|
+
* `templates/features/versioning/files/pages/`:
|
|
14
|
+
*
|
|
15
|
+
* docs/versions.tsx (always — versioning gate only)
|
|
16
|
+
* v/[version]/docs/[...slug].tsx (always — versioning gate only)
|
|
17
|
+
* v/[version]/ja/docs/[...slug].tsx (i18n + versioning — see below)
|
|
18
|
+
* [locale]/docs/versions.tsx (i18n + versioning)
|
|
19
|
+
*
|
|
20
|
+
* `copyFeatureFiles` (compose.ts) auto-copies everything under `files/`.
|
|
21
|
+
* postProcess removes the i18n-gated subset when i18n is OFF so single-
|
|
22
|
+
* locale projects don't ship orphan routes.
|
|
23
|
+
*
|
|
24
|
+
* Note: `v/[version]/ja/docs/[...slug].tsx` hardcodes `ja` per W2 spec-lock
|
|
25
|
+
* Decision 9 / §6.4 — matches main verbatim. Future generalization to
|
|
26
|
+
* `[locale]` is deferred (maintainer-question follow-up).
|
|
27
|
+
*/
|
|
28
|
+
export const versioningFeature = (choices) => ({
|
|
29
|
+
name: "versioning",
|
|
30
|
+
postProcess: async (targetDir) => {
|
|
31
|
+
if (!choices.features.includes("i18n")) {
|
|
32
|
+
const localeVersions = path.join(targetDir, "pages", "[locale]", "docs", "versions.tsx");
|
|
33
|
+
if (await fs.pathExists(localeVersions)) {
|
|
34
|
+
await fs.remove(localeVersions);
|
|
35
|
+
}
|
|
36
|
+
const jaVersionedDocs = path.join(targetDir, "pages", "v", "[version]", "ja");
|
|
37
|
+
if (await fs.pathExists(jaVersionedDocs)) {
|
|
38
|
+
await fs.remove(jaVersionedDocs);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
injections: [],
|
|
43
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { parseArgs, printHelp, validateArgs } from "./cli.js";
|
|
5
|
+
import { FEATURES } from "./constants.js";
|
|
6
|
+
import { loadPreset } from "./preset.js";
|
|
7
|
+
import { runPrompts } from "./prompts.js";
|
|
8
|
+
import { scaffold } from "./scaffold.js";
|
|
9
|
+
import { installDependencies } from "./utils.js";
|
|
10
|
+
async function main() {
|
|
11
|
+
const args = parseArgs();
|
|
12
|
+
// Handle --help
|
|
13
|
+
if (args.help) {
|
|
14
|
+
printHelp();
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
// Validate args
|
|
18
|
+
const error = validateArgs(args);
|
|
19
|
+
if (error) {
|
|
20
|
+
console.error(pc.red(`Error: ${error}`));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
console.log();
|
|
24
|
+
p.intro(pc.bgCyan(pc.black(" create-zudo-doc ")));
|
|
25
|
+
// Build PartialChoices: preset first, then CLI args override
|
|
26
|
+
const prefilled = {};
|
|
27
|
+
// Load preset if provided (base layer — CLI flags override below)
|
|
28
|
+
if (args.preset) {
|
|
29
|
+
try {
|
|
30
|
+
const presetChoices = loadPreset(args.preset);
|
|
31
|
+
Object.assign(prefilled, presetChoices);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
p.log.error(`Failed to load preset: ${err instanceof Error ? err.message : String(err)}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// CLI args override preset values
|
|
39
|
+
if (args.name)
|
|
40
|
+
prefilled.projectName = args.name;
|
|
41
|
+
if (args.lang)
|
|
42
|
+
prefilled.defaultLang = args.lang;
|
|
43
|
+
if (args.colorSchemeMode)
|
|
44
|
+
prefilled.colorSchemeMode = args.colorSchemeMode;
|
|
45
|
+
if (args.scheme) {
|
|
46
|
+
prefilled.colorSchemeMode = prefilled.colorSchemeMode ?? "single";
|
|
47
|
+
prefilled.singleScheme = args.scheme;
|
|
48
|
+
}
|
|
49
|
+
if (args.lightScheme)
|
|
50
|
+
prefilled.lightScheme = args.lightScheme;
|
|
51
|
+
if (args.darkScheme)
|
|
52
|
+
prefilled.darkScheme = args.darkScheme;
|
|
53
|
+
if (args.defaultMode !== undefined)
|
|
54
|
+
prefilled.defaultMode = args.defaultMode;
|
|
55
|
+
if (args.respectSystemPreference !== undefined) {
|
|
56
|
+
prefilled.respectPrefersColorScheme = args.respectSystemPreference;
|
|
57
|
+
}
|
|
58
|
+
if (args.pm)
|
|
59
|
+
prefilled.packageManager = args.pm;
|
|
60
|
+
if (args.githubUrl !== undefined)
|
|
61
|
+
prefilled.githubUrl = args.githubUrl;
|
|
62
|
+
// Build feature overrides from explicit flags — driven by FEATURES constant
|
|
63
|
+
const featureFlags = {};
|
|
64
|
+
for (const f of FEATURES) {
|
|
65
|
+
const val = args[f.value];
|
|
66
|
+
if (val !== undefined)
|
|
67
|
+
featureFlags[f.value] = val;
|
|
68
|
+
}
|
|
69
|
+
if (Object.keys(featureFlags).length > 0) {
|
|
70
|
+
prefilled.features = { ...prefilled.features, ...featureFlags };
|
|
71
|
+
}
|
|
72
|
+
// With --yes or --preset: fill all unspecified options with defaults
|
|
73
|
+
if (args.yes || args.preset) {
|
|
74
|
+
prefilled.projectName ??= "my-docs";
|
|
75
|
+
prefilled.defaultLang ??= "en";
|
|
76
|
+
prefilled.colorSchemeMode ??= "light-dark";
|
|
77
|
+
if (prefilled.colorSchemeMode === "light-dark") {
|
|
78
|
+
prefilled.lightScheme ??= "Default Light";
|
|
79
|
+
prefilled.darkScheme ??= "Default Dark";
|
|
80
|
+
prefilled.defaultMode ??= "dark";
|
|
81
|
+
prefilled.respectPrefersColorScheme ??= true;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
prefilled.singleScheme ??= "Dracula";
|
|
85
|
+
}
|
|
86
|
+
prefilled.packageManager ??= "pnpm";
|
|
87
|
+
prefilled.githubUrl ??= "";
|
|
88
|
+
// For features: set defaults for any not explicitly specified
|
|
89
|
+
const featureDefaults = {};
|
|
90
|
+
for (const f of FEATURES) {
|
|
91
|
+
featureDefaults[f.value] = f.default;
|
|
92
|
+
}
|
|
93
|
+
prefilled.features = { ...featureDefaults, ...prefilled.features };
|
|
94
|
+
}
|
|
95
|
+
const choices = await runPrompts(prefilled);
|
|
96
|
+
const targetDir = path.resolve(process.cwd(), choices.projectName);
|
|
97
|
+
const s = p.spinner();
|
|
98
|
+
s.start("Scaffolding project...");
|
|
99
|
+
try {
|
|
100
|
+
await scaffold(choices);
|
|
101
|
+
s.stop("Project scaffolded!");
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
s.stop("Scaffolding failed!");
|
|
105
|
+
p.log.error(err instanceof Error ? err.message : String(err));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
// Install dependencies
|
|
109
|
+
let shouldInstall;
|
|
110
|
+
if (args.install !== undefined) {
|
|
111
|
+
shouldInstall = args.install;
|
|
112
|
+
}
|
|
113
|
+
else if (args.yes || args.preset) {
|
|
114
|
+
// In non-interactive mode, default to installing dependencies
|
|
115
|
+
shouldInstall = true;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const result = await p.confirm({
|
|
119
|
+
message: "Install dependencies?",
|
|
120
|
+
initialValue: true,
|
|
121
|
+
});
|
|
122
|
+
if (p.isCancel(result)) {
|
|
123
|
+
p.outro(`Done! cd ${choices.projectName} and install dependencies manually.`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
shouldInstall = result;
|
|
127
|
+
}
|
|
128
|
+
if (shouldInstall) {
|
|
129
|
+
const s2 = p.spinner();
|
|
130
|
+
s2.start(`Installing dependencies with ${choices.packageManager}...`);
|
|
131
|
+
try {
|
|
132
|
+
installDependencies(targetDir, choices.packageManager);
|
|
133
|
+
s2.stop("Dependencies installed!");
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
s2.stop("Installation failed. Run install manually.");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
p.outro(`${pc.green("Done!")} Your project is ready at ${pc.cyan(choices.projectName)}`);
|
|
140
|
+
console.log();
|
|
141
|
+
console.log(` ${pc.bold("Next steps:")}`);
|
|
142
|
+
console.log(` cd ${choices.projectName}`);
|
|
143
|
+
const runCmd = choices.packageManager === "npm" ? "npm run" : choices.packageManager;
|
|
144
|
+
console.log(` ${runCmd} dev`);
|
|
145
|
+
console.log();
|
|
146
|
+
}
|
|
147
|
+
main().catch((err) => {
|
|
148
|
+
console.error(err);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
});
|