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/preset.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PartialChoices } from "./prompts.js";
|
|
2
|
+
/**
|
|
3
|
+
* Header-right item shapes accepted in v1 of preset support. Mirrors
|
|
4
|
+
* `HeaderRightComponentItem` and `HeaderRightTriggerItem` from
|
|
5
|
+
* `src/config/settings-types.ts`. The wider `link`/`html` variants are
|
|
6
|
+
* intentionally rejected for now — they need free-text fields that pollute
|
|
7
|
+
* the JSON preset schema and the generator UI.
|
|
8
|
+
*/
|
|
9
|
+
export type PresetHeaderRightComponentName = "theme-toggle" | "language-switcher" | "version-switcher" | "github-link" | "search";
|
|
10
|
+
export type PresetHeaderRightTriggerName = "design-token-panel" | "ai-chat";
|
|
11
|
+
export interface PresetHeaderRightComponentItem {
|
|
12
|
+
type: "component";
|
|
13
|
+
component: PresetHeaderRightComponentName;
|
|
14
|
+
}
|
|
15
|
+
export interface PresetHeaderRightTriggerItem {
|
|
16
|
+
type: "trigger";
|
|
17
|
+
trigger: PresetHeaderRightTriggerName;
|
|
18
|
+
}
|
|
19
|
+
export type PresetHeaderRightItem = PresetHeaderRightComponentItem | PresetHeaderRightTriggerItem;
|
|
20
|
+
export interface PresetJson {
|
|
21
|
+
projectName?: string;
|
|
22
|
+
defaultLang?: string;
|
|
23
|
+
colorSchemeMode?: "single" | "light-dark";
|
|
24
|
+
singleScheme?: string;
|
|
25
|
+
lightScheme?: string;
|
|
26
|
+
darkScheme?: string;
|
|
27
|
+
defaultMode?: "light" | "dark";
|
|
28
|
+
respectPrefersColorScheme?: boolean;
|
|
29
|
+
features?: string[];
|
|
30
|
+
githubUrl?: string;
|
|
31
|
+
cjkFriendly?: boolean;
|
|
32
|
+
packageManager?: "pnpm" | "npm" | "yarn" | "bun";
|
|
33
|
+
headerRightItems?: PresetHeaderRightItem[];
|
|
34
|
+
}
|
|
35
|
+
export declare function loadPreset(pathOrStdin: string): PartialChoices;
|
|
36
|
+
export declare function validatePreset(json: unknown): string | null;
|
|
37
|
+
export declare function presetToChoices(json: PresetJson): PartialChoices;
|
package/dist/preset.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { FEATURES, SINGLE_SCHEMES, SUPPORTED_LANGS } from "./constants.js";
|
|
3
|
+
const VALID_HEADER_RIGHT_COMPONENTS = new Set([
|
|
4
|
+
"theme-toggle",
|
|
5
|
+
"language-switcher",
|
|
6
|
+
"version-switcher",
|
|
7
|
+
"github-link",
|
|
8
|
+
"search",
|
|
9
|
+
]);
|
|
10
|
+
const VALID_HEADER_RIGHT_TRIGGERS = new Set([
|
|
11
|
+
"design-token-panel",
|
|
12
|
+
"ai-chat",
|
|
13
|
+
]);
|
|
14
|
+
export function loadPreset(pathOrStdin) {
|
|
15
|
+
let raw;
|
|
16
|
+
if (pathOrStdin === "-") {
|
|
17
|
+
raw = fs.readFileSync(0, "utf8");
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
raw = fs.readFileSync(pathOrStdin, "utf8");
|
|
21
|
+
}
|
|
22
|
+
const json = JSON.parse(raw);
|
|
23
|
+
const error = validatePreset(json);
|
|
24
|
+
if (error) {
|
|
25
|
+
throw new Error(error);
|
|
26
|
+
}
|
|
27
|
+
return presetToChoices(json);
|
|
28
|
+
}
|
|
29
|
+
const VALID_LANGS = new Set(SUPPORTED_LANGS.map((l) => l.value));
|
|
30
|
+
const VALID_SCHEMES = new Set(SINGLE_SCHEMES);
|
|
31
|
+
const VALID_PMS = new Set(["pnpm", "npm", "yarn", "bun"]);
|
|
32
|
+
export function validatePreset(json) {
|
|
33
|
+
if (json === null || typeof json !== "object" || Array.isArray(json)) {
|
|
34
|
+
return "Preset must be a JSON object";
|
|
35
|
+
}
|
|
36
|
+
const p = json;
|
|
37
|
+
if (p.features !== undefined && !Array.isArray(p.features)) {
|
|
38
|
+
return `"features" must be an array in preset`;
|
|
39
|
+
}
|
|
40
|
+
if (p.defaultLang && !VALID_LANGS.has(p.defaultLang)) {
|
|
41
|
+
return `Invalid language "${p.defaultLang}" in preset`;
|
|
42
|
+
}
|
|
43
|
+
if (p.colorSchemeMode && !["single", "light-dark"].includes(p.colorSchemeMode)) {
|
|
44
|
+
return `Invalid colorSchemeMode "${p.colorSchemeMode}" in preset`;
|
|
45
|
+
}
|
|
46
|
+
if (p.singleScheme && !VALID_SCHEMES.has(p.singleScheme)) {
|
|
47
|
+
return `Unknown color scheme "${p.singleScheme}" in preset`;
|
|
48
|
+
}
|
|
49
|
+
if (p.lightScheme && !VALID_SCHEMES.has(p.lightScheme)) {
|
|
50
|
+
return `Unknown light scheme "${p.lightScheme}" in preset`;
|
|
51
|
+
}
|
|
52
|
+
if (p.darkScheme && !VALID_SCHEMES.has(p.darkScheme)) {
|
|
53
|
+
return `Unknown dark scheme "${p.darkScheme}" in preset`;
|
|
54
|
+
}
|
|
55
|
+
if (p.defaultMode && !["light", "dark"].includes(p.defaultMode)) {
|
|
56
|
+
return `Invalid defaultMode "${p.defaultMode}" in preset`;
|
|
57
|
+
}
|
|
58
|
+
if (p.packageManager && !VALID_PMS.has(p.packageManager)) {
|
|
59
|
+
return `Invalid packageManager "${p.packageManager}" in preset`;
|
|
60
|
+
}
|
|
61
|
+
if (p.cjkFriendly !== undefined && typeof p.cjkFriendly !== "boolean") {
|
|
62
|
+
return `"cjkFriendly" must be a boolean in preset`;
|
|
63
|
+
}
|
|
64
|
+
if (p.headerRightItems !== undefined) {
|
|
65
|
+
if (!Array.isArray(p.headerRightItems)) {
|
|
66
|
+
return `"headerRightItems" must be an array in preset`;
|
|
67
|
+
}
|
|
68
|
+
for (let i = 0; i < p.headerRightItems.length; i++) {
|
|
69
|
+
const item = p.headerRightItems[i];
|
|
70
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
71
|
+
return `headerRightItems[${i}] must be an object`;
|
|
72
|
+
}
|
|
73
|
+
const t = item.type;
|
|
74
|
+
if (t === "link" || t === "html") {
|
|
75
|
+
return `headerRightItems[${i}] type "${t}" is not supported in presets (v1) — edit settings.ts after scaffold`;
|
|
76
|
+
}
|
|
77
|
+
if (t === "component") {
|
|
78
|
+
const component = item.component;
|
|
79
|
+
if (typeof component !== "string") {
|
|
80
|
+
return `headerRightItems[${i}].component must be a string`;
|
|
81
|
+
}
|
|
82
|
+
if (!VALID_HEADER_RIGHT_COMPONENTS.has(component)) {
|
|
83
|
+
return `headerRightItems[${i}] unknown component "${component}". Allowed: ${[
|
|
84
|
+
...VALID_HEADER_RIGHT_COMPONENTS,
|
|
85
|
+
].join(", ")}`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (t === "trigger") {
|
|
89
|
+
const trigger = item.trigger;
|
|
90
|
+
if (typeof trigger !== "string") {
|
|
91
|
+
return `headerRightItems[${i}].trigger must be a string`;
|
|
92
|
+
}
|
|
93
|
+
if (!VALID_HEADER_RIGHT_TRIGGERS.has(trigger)) {
|
|
94
|
+
return `headerRightItems[${i}] unknown trigger "${trigger}". Allowed: ${[
|
|
95
|
+
...VALID_HEADER_RIGHT_TRIGGERS,
|
|
96
|
+
].join(", ")}`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return `headerRightItems[${i}] must have type "component" or "trigger" (got ${JSON.stringify(t)})`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Cross-field validation
|
|
105
|
+
if (p.colorSchemeMode === "single" && (p.lightScheme || p.darkScheme)) {
|
|
106
|
+
return `lightScheme/darkScheme are only valid with colorSchemeMode "light-dark"`;
|
|
107
|
+
}
|
|
108
|
+
if (p.colorSchemeMode === "light-dark" && p.singleScheme) {
|
|
109
|
+
return `singleScheme is only valid with colorSchemeMode "single"`;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const KNOWN_FEATURES = new Set(FEATURES.map((f) => f.value));
|
|
114
|
+
export function presetToChoices(json) {
|
|
115
|
+
const choices = {};
|
|
116
|
+
if (json.projectName)
|
|
117
|
+
choices.projectName = json.projectName;
|
|
118
|
+
if (json.defaultLang)
|
|
119
|
+
choices.defaultLang = json.defaultLang;
|
|
120
|
+
if (json.colorSchemeMode)
|
|
121
|
+
choices.colorSchemeMode = json.colorSchemeMode;
|
|
122
|
+
if (json.singleScheme)
|
|
123
|
+
choices.singleScheme = json.singleScheme;
|
|
124
|
+
if (json.lightScheme)
|
|
125
|
+
choices.lightScheme = json.lightScheme;
|
|
126
|
+
if (json.darkScheme)
|
|
127
|
+
choices.darkScheme = json.darkScheme;
|
|
128
|
+
if (json.defaultMode)
|
|
129
|
+
choices.defaultMode = json.defaultMode;
|
|
130
|
+
if (json.respectPrefersColorScheme !== undefined) {
|
|
131
|
+
choices.respectPrefersColorScheme = json.respectPrefersColorScheme;
|
|
132
|
+
}
|
|
133
|
+
if (json.packageManager)
|
|
134
|
+
choices.packageManager = json.packageManager;
|
|
135
|
+
if (json.githubUrl !== undefined)
|
|
136
|
+
choices.githubUrl = json.githubUrl;
|
|
137
|
+
if (json.cjkFriendly !== undefined)
|
|
138
|
+
choices.cjkFriendly = json.cjkFriendly;
|
|
139
|
+
if (json.headerRightItems !== undefined) {
|
|
140
|
+
choices.headerRightItems = json.headerRightItems;
|
|
141
|
+
}
|
|
142
|
+
if (json.features) {
|
|
143
|
+
// Warn about unrecognized feature names
|
|
144
|
+
for (const name of json.features) {
|
|
145
|
+
if (!KNOWN_FEATURES.has(name)) {
|
|
146
|
+
console.warn(`Warning: unknown feature "${name}" in preset — ignored`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const featureMap = {};
|
|
150
|
+
for (const f of FEATURES) {
|
|
151
|
+
featureMap[f.value] = json.features.includes(f.value);
|
|
152
|
+
}
|
|
153
|
+
choices.features = featureMap;
|
|
154
|
+
}
|
|
155
|
+
return choices;
|
|
156
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PresetHeaderRightItem } from "./preset.js";
|
|
2
|
+
export interface UserChoices {
|
|
3
|
+
projectName: string;
|
|
4
|
+
defaultLang: string;
|
|
5
|
+
colorSchemeMode: "single" | "light-dark";
|
|
6
|
+
singleScheme?: string;
|
|
7
|
+
lightScheme?: string;
|
|
8
|
+
darkScheme?: string;
|
|
9
|
+
respectPrefersColorScheme?: boolean;
|
|
10
|
+
defaultMode?: "light" | "dark";
|
|
11
|
+
features: string[];
|
|
12
|
+
githubUrl?: string;
|
|
13
|
+
cjkFriendly?: boolean;
|
|
14
|
+
packageManager: "pnpm" | "npm" | "yarn" | "bun";
|
|
15
|
+
headerRightItems?: PresetHeaderRightItem[];
|
|
16
|
+
}
|
|
17
|
+
export interface PartialChoices {
|
|
18
|
+
projectName?: string;
|
|
19
|
+
defaultLang?: string;
|
|
20
|
+
colorSchemeMode?: "single" | "light-dark";
|
|
21
|
+
singleScheme?: string;
|
|
22
|
+
lightScheme?: string;
|
|
23
|
+
darkScheme?: string;
|
|
24
|
+
respectPrefersColorScheme?: boolean;
|
|
25
|
+
defaultMode?: "light" | "dark";
|
|
26
|
+
features?: Partial<Record<string, boolean>>;
|
|
27
|
+
githubUrl?: string;
|
|
28
|
+
cjkFriendly?: boolean;
|
|
29
|
+
packageManager?: "pnpm" | "npm" | "yarn" | "bun";
|
|
30
|
+
headerRightItems?: PresetHeaderRightItem[];
|
|
31
|
+
}
|
|
32
|
+
export declare function runPrompts(prefilled?: PartialChoices): Promise<UserChoices>;
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { LIGHT_DARK_PAIRINGS, SINGLE_SCHEMES, FEATURES, SUPPORTED_LANGS } from "./constants.js";
|
|
3
|
+
export async function runPrompts(prefilled = {}) {
|
|
4
|
+
// 1. Project name
|
|
5
|
+
let projectName;
|
|
6
|
+
if (prefilled.projectName) {
|
|
7
|
+
projectName = prefilled.projectName;
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
const result = await p.text({
|
|
11
|
+
message: "What is your project name?",
|
|
12
|
+
placeholder: "my-docs",
|
|
13
|
+
defaultValue: "my-docs",
|
|
14
|
+
validate(value) {
|
|
15
|
+
if (!value.trim())
|
|
16
|
+
return "Project name is required";
|
|
17
|
+
if (/^[./]|\.\./.test(value))
|
|
18
|
+
return "Project name must not contain path traversal characters";
|
|
19
|
+
if (/[<>:"|?*\\]/.test(value))
|
|
20
|
+
return "Project name contains invalid characters";
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
if (p.isCancel(result))
|
|
24
|
+
process.exit(0);
|
|
25
|
+
projectName = result;
|
|
26
|
+
}
|
|
27
|
+
// 2. Default language
|
|
28
|
+
let defaultLang;
|
|
29
|
+
if (prefilled.defaultLang) {
|
|
30
|
+
defaultLang = prefilled.defaultLang;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const result = await p.select({
|
|
34
|
+
message: "Default language:",
|
|
35
|
+
options: SUPPORTED_LANGS.map((l) => ({
|
|
36
|
+
value: l.value,
|
|
37
|
+
label: `${l.label} (${l.value})`,
|
|
38
|
+
})),
|
|
39
|
+
initialValue: "en",
|
|
40
|
+
});
|
|
41
|
+
if (p.isCancel(result))
|
|
42
|
+
process.exit(0);
|
|
43
|
+
defaultLang = result;
|
|
44
|
+
}
|
|
45
|
+
// 3. Color scheme mode
|
|
46
|
+
let colorSchemeMode;
|
|
47
|
+
if (prefilled.colorSchemeMode) {
|
|
48
|
+
colorSchemeMode = prefilled.colorSchemeMode;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const result = await p.select({
|
|
52
|
+
message: "Color scheme mode:",
|
|
53
|
+
options: [
|
|
54
|
+
{
|
|
55
|
+
value: "light-dark",
|
|
56
|
+
label: "Light & Dark (toggle)",
|
|
57
|
+
hint: "Users can switch between light and dark themes",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
value: "single",
|
|
61
|
+
label: "Single scheme",
|
|
62
|
+
hint: "One color scheme for the entire site",
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
if (p.isCancel(result))
|
|
67
|
+
process.exit(0);
|
|
68
|
+
colorSchemeMode = result;
|
|
69
|
+
}
|
|
70
|
+
let singleScheme;
|
|
71
|
+
let lightScheme;
|
|
72
|
+
let darkScheme;
|
|
73
|
+
let respectPrefersColorScheme = prefilled.respectPrefersColorScheme ?? true;
|
|
74
|
+
let defaultMode = prefilled.defaultMode ?? "dark";
|
|
75
|
+
if (colorSchemeMode === "single") {
|
|
76
|
+
if (prefilled.singleScheme) {
|
|
77
|
+
singleScheme = prefilled.singleScheme;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const scheme = await p.select({
|
|
81
|
+
message: "Choose a color scheme:",
|
|
82
|
+
options: SINGLE_SCHEMES.map((s) => ({ value: s, label: s })),
|
|
83
|
+
});
|
|
84
|
+
if (p.isCancel(scheme))
|
|
85
|
+
process.exit(0);
|
|
86
|
+
singleScheme = scheme;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
if (prefilled.lightScheme && prefilled.darkScheme) {
|
|
91
|
+
lightScheme = prefilled.lightScheme;
|
|
92
|
+
darkScheme = prefilled.darkScheme;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const pairingChoice = await p.select({
|
|
96
|
+
message: "Choose a light/dark pairing:",
|
|
97
|
+
options: [
|
|
98
|
+
...LIGHT_DARK_PAIRINGS.map((pair) => ({
|
|
99
|
+
value: pair.label,
|
|
100
|
+
label: `${pair.light} + ${pair.dark}`,
|
|
101
|
+
hint: pair.label,
|
|
102
|
+
})),
|
|
103
|
+
{
|
|
104
|
+
value: "custom",
|
|
105
|
+
label: "Pick individually",
|
|
106
|
+
hint: "Choose light and dark schemes separately",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
});
|
|
110
|
+
if (p.isCancel(pairingChoice))
|
|
111
|
+
process.exit(0);
|
|
112
|
+
if (pairingChoice === "custom") {
|
|
113
|
+
const lightSchemes = SINGLE_SCHEMES.filter((s) => ["Light", "Latte", "Dawn"].some((k) => s.includes(k)));
|
|
114
|
+
const darkSchemes = SINGLE_SCHEMES.filter((s) => !["Light", "Latte", "Dawn"].some((k) => s.includes(k)));
|
|
115
|
+
const light = await p.select({
|
|
116
|
+
message: "Choose light scheme:",
|
|
117
|
+
options: lightSchemes.map((s) => ({ value: s, label: s })),
|
|
118
|
+
});
|
|
119
|
+
if (p.isCancel(light))
|
|
120
|
+
process.exit(0);
|
|
121
|
+
lightScheme = light;
|
|
122
|
+
const dark = await p.select({
|
|
123
|
+
message: "Choose dark scheme:",
|
|
124
|
+
options: darkSchemes.map((s) => ({ value: s, label: s })),
|
|
125
|
+
});
|
|
126
|
+
if (p.isCancel(dark))
|
|
127
|
+
process.exit(0);
|
|
128
|
+
darkScheme = dark;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const pairing = LIGHT_DARK_PAIRINGS.find((pair) => pair.label === pairingChoice);
|
|
132
|
+
if (pairing) {
|
|
133
|
+
lightScheme = pairing.light;
|
|
134
|
+
darkScheme = pairing.dark;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Default mode
|
|
139
|
+
if (prefilled.defaultMode === undefined) {
|
|
140
|
+
const modeResult = await p.select({
|
|
141
|
+
message: "Default color mode:",
|
|
142
|
+
options: [
|
|
143
|
+
{
|
|
144
|
+
value: "dark",
|
|
145
|
+
label: "Dark",
|
|
146
|
+
hint: "Start in dark mode",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
value: "light",
|
|
150
|
+
label: "Light",
|
|
151
|
+
hint: "Start in light mode",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
});
|
|
155
|
+
if (p.isCancel(modeResult))
|
|
156
|
+
process.exit(0);
|
|
157
|
+
defaultMode = modeResult;
|
|
158
|
+
}
|
|
159
|
+
// Respect system preference
|
|
160
|
+
if (prefilled.respectPrefersColorScheme === undefined) {
|
|
161
|
+
const respect = await p.confirm({
|
|
162
|
+
message: "Respect system color scheme preference?",
|
|
163
|
+
initialValue: true,
|
|
164
|
+
});
|
|
165
|
+
if (p.isCancel(respect))
|
|
166
|
+
process.exit(0);
|
|
167
|
+
respectPrefersColorScheme = respect;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// 4. Features
|
|
171
|
+
let features;
|
|
172
|
+
if (prefilled.features) {
|
|
173
|
+
// Build features from explicit overrides + defaults
|
|
174
|
+
features = FEATURES.filter((f) => {
|
|
175
|
+
if (f.value in prefilled.features) {
|
|
176
|
+
return prefilled.features[f.value];
|
|
177
|
+
}
|
|
178
|
+
return f.default;
|
|
179
|
+
}).map((f) => f.value);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const result = await p.multiselect({
|
|
183
|
+
message: "Include extra features:",
|
|
184
|
+
options: FEATURES.map((f) => ({
|
|
185
|
+
value: f.value,
|
|
186
|
+
label: f.label,
|
|
187
|
+
hint: f.hint,
|
|
188
|
+
})),
|
|
189
|
+
initialValues: FEATURES.filter((f) => f.default).map((f) => f.value),
|
|
190
|
+
required: false,
|
|
191
|
+
});
|
|
192
|
+
if (p.isCancel(result))
|
|
193
|
+
process.exit(0);
|
|
194
|
+
features = result;
|
|
195
|
+
}
|
|
196
|
+
// 5. GitHub URL (drives header GitHub icon + view-source link)
|
|
197
|
+
let githubUrl = prefilled.githubUrl;
|
|
198
|
+
if (githubUrl === undefined) {
|
|
199
|
+
const result = await p.text({
|
|
200
|
+
message: "GitHub repository URL (optional, leave blank to disable):",
|
|
201
|
+
placeholder: "https://github.com/you/your-repo",
|
|
202
|
+
defaultValue: "",
|
|
203
|
+
validate(value) {
|
|
204
|
+
if (!value)
|
|
205
|
+
return;
|
|
206
|
+
if (!/^https?:\/\//.test(value))
|
|
207
|
+
return "URL must start with http(s)://";
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
if (p.isCancel(result))
|
|
211
|
+
process.exit(0);
|
|
212
|
+
githubUrl = result;
|
|
213
|
+
}
|
|
214
|
+
// 6. Package manager
|
|
215
|
+
let packageManager;
|
|
216
|
+
if (prefilled.packageManager) {
|
|
217
|
+
packageManager = prefilled.packageManager;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const result = await p.select({
|
|
221
|
+
message: "Package manager:",
|
|
222
|
+
options: [
|
|
223
|
+
{ value: "pnpm", label: "pnpm", hint: "Recommended" },
|
|
224
|
+
{ value: "npm", label: "npm" },
|
|
225
|
+
{ value: "yarn", label: "yarn" },
|
|
226
|
+
{ value: "bun", label: "bun" },
|
|
227
|
+
],
|
|
228
|
+
});
|
|
229
|
+
if (p.isCancel(result))
|
|
230
|
+
process.exit(0);
|
|
231
|
+
packageManager = result;
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
projectName,
|
|
235
|
+
defaultLang,
|
|
236
|
+
colorSchemeMode,
|
|
237
|
+
singleScheme,
|
|
238
|
+
lightScheme,
|
|
239
|
+
darkScheme,
|
|
240
|
+
respectPrefersColorScheme,
|
|
241
|
+
defaultMode,
|
|
242
|
+
features,
|
|
243
|
+
githubUrl,
|
|
244
|
+
cjkFriendly: prefilled.cjkFriendly,
|
|
245
|
+
packageManager,
|
|
246
|
+
headerRightItems: prefilled.headerRightItems,
|
|
247
|
+
};
|
|
248
|
+
}
|