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/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import matter from "gray-matter";
|
|
4
|
+
import { escapeForMdx } from "./escape-for-mdx";
|
|
5
|
+
|
|
6
|
+
export interface ClaudeResourcesConfig {
|
|
7
|
+
claudeDir: string;
|
|
8
|
+
projectRoot?: string;
|
|
9
|
+
docsDir: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ClaudeMdItem {
|
|
13
|
+
displayPath: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
relPath: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface CommandItem {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SkillReference {
|
|
24
|
+
name: string;
|
|
25
|
+
title: string;
|
|
26
|
+
content: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface SkillItem {
|
|
30
|
+
name: string;
|
|
31
|
+
dir: string;
|
|
32
|
+
description: string;
|
|
33
|
+
references: SkillReference[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface AgentItem {
|
|
37
|
+
name: string;
|
|
38
|
+
file: string;
|
|
39
|
+
description: string;
|
|
40
|
+
model: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Utility
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
function ensureDir(dir: string) {
|
|
48
|
+
if (!fs.existsSync(dir)) {
|
|
49
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function cleanDir(dir: string) {
|
|
54
|
+
if (!fs.existsSync(dir)) return;
|
|
55
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseFrontmatter(content: string) {
|
|
59
|
+
try {
|
|
60
|
+
return matter(content);
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function escapeTitle(s: string): string {
|
|
67
|
+
return s.replace(/"/g, '\\"');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function listFiles(dir: string): string[] {
|
|
71
|
+
if (!fs.existsSync(dir)) return [];
|
|
72
|
+
return fs
|
|
73
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
74
|
+
.filter((d) => d.isFile())
|
|
75
|
+
.map((d) => d.name)
|
|
76
|
+
.sort();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function writeCategoryMeta(
|
|
80
|
+
outputDir: string,
|
|
81
|
+
label: string,
|
|
82
|
+
position: number,
|
|
83
|
+
description: string,
|
|
84
|
+
noPage = true,
|
|
85
|
+
) {
|
|
86
|
+
const meta: Record<string, unknown> = { label, position, description };
|
|
87
|
+
if (noPage) meta.noPage = true;
|
|
88
|
+
fs.writeFileSync(
|
|
89
|
+
path.join(outputDir, "_category_.json"),
|
|
90
|
+
JSON.stringify(meta, null, 2) + "\n",
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// CLAUDE.md discovery
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
function findClaudeMdFiles(dir: string, excludeDirs: string[]): string[] {
|
|
99
|
+
const results: string[] = [];
|
|
100
|
+
if (!fs.existsSync(dir)) return results;
|
|
101
|
+
|
|
102
|
+
for (const item of fs.readdirSync(dir)) {
|
|
103
|
+
if (item === "node_modules") continue;
|
|
104
|
+
if (item.startsWith(".")) continue;
|
|
105
|
+
const itemPath = path.join(dir, item);
|
|
106
|
+
if (excludeDirs.some((d) => itemPath.startsWith(d))) continue;
|
|
107
|
+
|
|
108
|
+
// lstat (not stat) so symlinks aren't followed — a symlinked dir can point
|
|
109
|
+
// back into the project (e.g. e2e fixtures linking to packages/) or out to
|
|
110
|
+
// a slow mount (e.g. /mnt/c on WSL) and either turns the walk into a
|
|
111
|
+
// multi-minute hang.
|
|
112
|
+
let stat: fs.Stats;
|
|
113
|
+
try {
|
|
114
|
+
stat = fs.lstatSync(itemPath);
|
|
115
|
+
} catch {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (stat.isDirectory()) {
|
|
119
|
+
results.push(...findClaudeMdFiles(itemPath, excludeDirs));
|
|
120
|
+
} else if (stat.isFile() && item === "CLAUDE.md") {
|
|
121
|
+
results.push(itemPath);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// CLAUDE.md generation
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
|
|
131
|
+
function generateClaudemdDocs(
|
|
132
|
+
config: ClaudeResourcesConfig,
|
|
133
|
+
): ClaudeMdItem[] {
|
|
134
|
+
const projectRoot = config.projectRoot ?? path.dirname(config.claudeDir);
|
|
135
|
+
const outputDir = path.join(config.docsDir, "claude-md");
|
|
136
|
+
|
|
137
|
+
cleanDir(outputDir);
|
|
138
|
+
|
|
139
|
+
const excludeDirs = [
|
|
140
|
+
path.join(projectRoot, ".git"),
|
|
141
|
+
path.join(projectRoot, "node_modules"),
|
|
142
|
+
path.join(projectRoot, "worktrees"),
|
|
143
|
+
path.join(projectRoot, "dist"),
|
|
144
|
+
path.join(projectRoot, "out"),
|
|
145
|
+
path.join(projectRoot, "public"),
|
|
146
|
+
path.join(projectRoot, "__inbox"),
|
|
147
|
+
path.join(projectRoot, "test-results"),
|
|
148
|
+
path.join(projectRoot, "e2e", "fixtures"),
|
|
149
|
+
path.join(config.docsDir),
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
const files = findClaudeMdFiles(projectRoot, excludeDirs);
|
|
153
|
+
if (files.length === 0) return [];
|
|
154
|
+
|
|
155
|
+
ensureDir(outputDir);
|
|
156
|
+
const items: ClaudeMdItem[] = [];
|
|
157
|
+
|
|
158
|
+
for (const filePath of files) {
|
|
159
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
160
|
+
const relPath = path.relative(projectRoot, filePath);
|
|
161
|
+
const displayPath = `/${relPath}`;
|
|
162
|
+
const dirPart = path.dirname(relPath);
|
|
163
|
+
const slug = dirPart === "." ? "root" : dirPart.replace(/\//g, "--");
|
|
164
|
+
|
|
165
|
+
items.push({ displayPath, slug, relPath });
|
|
166
|
+
|
|
167
|
+
const pos = items.length + 1;
|
|
168
|
+
const mdx = `---
|
|
169
|
+
title: "${escapeTitle(displayPath)}"
|
|
170
|
+
description: "CLAUDE.md at ${escapeTitle(displayPath)}"
|
|
171
|
+
sidebar_position: ${pos}
|
|
172
|
+
sidebar_label: "${escapeTitle(relPath)}"
|
|
173
|
+
generated: true
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
**Path:** \`${relPath}\`
|
|
177
|
+
|
|
178
|
+
${escapeForMdx(content.trim())}
|
|
179
|
+
`;
|
|
180
|
+
fs.writeFileSync(path.join(outputDir, `${slug}.mdx`), mdx);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Sort: root first, then alphabetically
|
|
184
|
+
items.sort((a, b) => {
|
|
185
|
+
if (a.slug === "root") return -1;
|
|
186
|
+
if (b.slug === "root") return 1;
|
|
187
|
+
return a.displayPath.localeCompare(b.displayPath);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
writeCategoryMeta(outputDir, "CLAUDE.md", 900, "Project-specific instructions");
|
|
191
|
+
return items;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
// Commands generation
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
function generateCommandsDocs(config: ClaudeResourcesConfig): CommandItem[] {
|
|
199
|
+
const commandsDir = path.join(config.claudeDir, "commands");
|
|
200
|
+
const outputDir = path.join(config.docsDir, "claude-commands");
|
|
201
|
+
|
|
202
|
+
cleanDir(outputDir);
|
|
203
|
+
|
|
204
|
+
if (!fs.existsSync(commandsDir)) return [];
|
|
205
|
+
|
|
206
|
+
const files = fs.readdirSync(commandsDir).filter((f) => f.endsWith(".md"));
|
|
207
|
+
if (files.length === 0) return [];
|
|
208
|
+
|
|
209
|
+
ensureDir(outputDir);
|
|
210
|
+
const items: CommandItem[] = [];
|
|
211
|
+
|
|
212
|
+
for (const file of files) {
|
|
213
|
+
const content = fs.readFileSync(path.join(commandsDir, file), "utf8");
|
|
214
|
+
const parsed = parseFrontmatter(content);
|
|
215
|
+
if (!parsed) continue;
|
|
216
|
+
|
|
217
|
+
const name = file.replace(/\.md$/, "");
|
|
218
|
+
const description = (parsed.data.description as string) || "";
|
|
219
|
+
|
|
220
|
+
items.push({ name, description });
|
|
221
|
+
|
|
222
|
+
const mdx = `---
|
|
223
|
+
title: "${escapeTitle(name)}"
|
|
224
|
+
description: "${escapeTitle(description)}"
|
|
225
|
+
sidebar_label: "${escapeTitle(name)}"
|
|
226
|
+
generated: true
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
${escapeForMdx(parsed.content.trim())}
|
|
230
|
+
`;
|
|
231
|
+
fs.writeFileSync(path.join(outputDir, `${name}.mdx`), mdx);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
items.sort((a, b) => a.name.localeCompare(b.name));
|
|
235
|
+
|
|
236
|
+
writeCategoryMeta(outputDir, "Commands", 901, "Custom slash commands");
|
|
237
|
+
return items;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// Skills generation
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
|
|
244
|
+
type TreeEntry =
|
|
245
|
+
| { isDir: false; name: string }
|
|
246
|
+
| { isDir: true; name: string; children: string[] };
|
|
247
|
+
|
|
248
|
+
function getSkillFileTree(
|
|
249
|
+
skillDir: string,
|
|
250
|
+
subDirs: { name: string; files: string[] }[],
|
|
251
|
+
): string {
|
|
252
|
+
const lines: string[] = [`${skillDir}/`];
|
|
253
|
+
const entries: TreeEntry[] = [{ isDir: false, name: "SKILL.md" }];
|
|
254
|
+
|
|
255
|
+
for (const sub of subDirs) {
|
|
256
|
+
entries.push({ isDir: true, name: sub.name, children: sub.files });
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
for (let i = 0; i < entries.length; i++) {
|
|
260
|
+
const entry = entries[i];
|
|
261
|
+
const isLast = i === entries.length - 1;
|
|
262
|
+
const prefix = isLast ? "└── " : "├── ";
|
|
263
|
+
|
|
264
|
+
if (!entry.isDir) {
|
|
265
|
+
lines.push(`${prefix}${entry.name}`);
|
|
266
|
+
} else {
|
|
267
|
+
lines.push(`${prefix}${entry.name}/`);
|
|
268
|
+
for (let j = 0; j < entry.children.length; j++) {
|
|
269
|
+
const child = entry.children[j];
|
|
270
|
+
const childIsLast = j === entry.children.length - 1;
|
|
271
|
+
const continuation = isLast ? " " : "│ ";
|
|
272
|
+
const childPrefix = childIsLast ? "└── " : "├── ";
|
|
273
|
+
lines.push(`${continuation}${childPrefix}${child}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return lines.join("\n");
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getScriptDescription(filePath: string): string {
|
|
282
|
+
try {
|
|
283
|
+
const topLines = fs.readFileSync(filePath, "utf8").split("\n", 2);
|
|
284
|
+
// Skip shebang, use second line if available
|
|
285
|
+
const commentLine = topLines[0].startsWith("#!")
|
|
286
|
+
? topLines[1] || ""
|
|
287
|
+
: topLines[0];
|
|
288
|
+
// Match # comments (shell/python) or // comments (JS/TS)
|
|
289
|
+
const match = commentLine.match(/^(?:#|\/\/)\s*(.+)/);
|
|
290
|
+
return match ? ` — ${match[1]}` : "";
|
|
291
|
+
} catch {
|
|
292
|
+
return "";
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function getSkillReferences(
|
|
297
|
+
skillsDir: string,
|
|
298
|
+
skillDir: string,
|
|
299
|
+
): SkillReference[] {
|
|
300
|
+
const refsDir = path.join(skillsDir, skillDir, "references");
|
|
301
|
+
if (!fs.existsSync(refsDir)) return [];
|
|
302
|
+
|
|
303
|
+
return fs
|
|
304
|
+
.readdirSync(refsDir)
|
|
305
|
+
.filter((f) => f.endsWith(".md"))
|
|
306
|
+
.map((f) => {
|
|
307
|
+
const content = fs.readFileSync(path.join(refsDir, f), "utf8");
|
|
308
|
+
const name = f.replace(/\.md$/, "");
|
|
309
|
+
const h1Match = content.match(/^#\s+(.+)$/m);
|
|
310
|
+
const title = h1Match ? h1Match[1] : name;
|
|
311
|
+
return { name, title, content };
|
|
312
|
+
})
|
|
313
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function generateSkillsDocs(config: ClaudeResourcesConfig): SkillItem[] {
|
|
317
|
+
const skillsDir = path.join(config.claudeDir, "skills");
|
|
318
|
+
const outputDir = path.join(config.docsDir, "claude-skills");
|
|
319
|
+
|
|
320
|
+
cleanDir(outputDir);
|
|
321
|
+
|
|
322
|
+
if (!fs.existsSync(skillsDir)) return [];
|
|
323
|
+
|
|
324
|
+
const dirs = fs.readdirSync(skillsDir).filter((d) => {
|
|
325
|
+
const skillPath = path.join(skillsDir, d);
|
|
326
|
+
return (
|
|
327
|
+
fs.statSync(skillPath).isDirectory() &&
|
|
328
|
+
fs.existsSync(path.join(skillPath, "SKILL.md"))
|
|
329
|
+
);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
if (dirs.length === 0) return [];
|
|
333
|
+
|
|
334
|
+
ensureDir(outputDir);
|
|
335
|
+
const items: SkillItem[] = [];
|
|
336
|
+
|
|
337
|
+
for (const dir of dirs) {
|
|
338
|
+
const content = fs.readFileSync(
|
|
339
|
+
path.join(skillsDir, dir, "SKILL.md"),
|
|
340
|
+
"utf8",
|
|
341
|
+
);
|
|
342
|
+
const parsed = parseFrontmatter(content);
|
|
343
|
+
if (!parsed) continue;
|
|
344
|
+
|
|
345
|
+
const name = (parsed.data.name as string) || dir;
|
|
346
|
+
const description = (parsed.data.description as string) || "";
|
|
347
|
+
const references = getSkillReferences(skillsDir, dir);
|
|
348
|
+
|
|
349
|
+
items.push({ name, dir, description, references });
|
|
350
|
+
|
|
351
|
+
const scriptFiles = listFiles(path.join(skillsDir, dir, "scripts"));
|
|
352
|
+
const assetFiles = listFiles(path.join(skillsDir, dir, "assets"));
|
|
353
|
+
const refFiles = references.map((r) => `${r.name}.md`);
|
|
354
|
+
|
|
355
|
+
// Collect non-empty subdirectories for tree display
|
|
356
|
+
const subDirs: { name: string; files: string[] }[] = [];
|
|
357
|
+
if (scriptFiles.length > 0) subDirs.push({ name: "scripts", files: scriptFiles });
|
|
358
|
+
if (refFiles.length > 0) subDirs.push({ name: "references", files: refFiles });
|
|
359
|
+
if (assetFiles.length > 0) subDirs.push({ name: "assets", files: assetFiles });
|
|
360
|
+
|
|
361
|
+
// File tree + links to renderable .md sub-files
|
|
362
|
+
let fileStructureSection = "";
|
|
363
|
+
if (subDirs.length > 0) {
|
|
364
|
+
const tree = `\`\`\`\n${getSkillFileTree(dir, subDirs)}\n\`\`\``;
|
|
365
|
+
|
|
366
|
+
// Collect links to all .md sub-files that get pages
|
|
367
|
+
// Links use ./<subpage> which resolves correctly from the skill page URL
|
|
368
|
+
// (the page URL already includes the dir, e.g. /docs/claude-skills/<dir>/)
|
|
369
|
+
const links: string[] = [];
|
|
370
|
+
for (const ref of references) {
|
|
371
|
+
links.push(`- [references/${ref.name}.md](./ref-${ref.name})`);
|
|
372
|
+
}
|
|
373
|
+
for (const f of scriptFiles.filter((s) => s.endsWith(".md"))) {
|
|
374
|
+
const slug = f.replace(/\.md$/, "");
|
|
375
|
+
links.push(`- [scripts/${f}](./script-${slug})`);
|
|
376
|
+
}
|
|
377
|
+
for (const f of assetFiles.filter((a) => a.endsWith(".md"))) {
|
|
378
|
+
const slug = f.replace(/\.md$/, "");
|
|
379
|
+
links.push(`- [assets/${f}](./asset-${slug})`);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const linkList = links.length > 0 ? `\n\n${links.join("\n")}` : "";
|
|
383
|
+
fileStructureSection = `## File Structure\n\n${tree}${linkList}`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const shortDesc = description.length > 200
|
|
387
|
+
? description.substring(0, 200) + "..."
|
|
388
|
+
: description;
|
|
389
|
+
|
|
390
|
+
// Rewrite references/scripts/assets links in skill body to match doc site URLs
|
|
391
|
+
let skillBody = parsed.content.trim();
|
|
392
|
+
skillBody = skillBody
|
|
393
|
+
.replace(/\]\(references\/([^)]+)\.md\)/g, "](./ref-$1)")
|
|
394
|
+
.replace(/\]\(scripts\/([^)]+)\.md\)/g, "](./script-$1)")
|
|
395
|
+
.replace(/\]\(assets\/([^)]+)\.md\)/g, "](./asset-$1)");
|
|
396
|
+
|
|
397
|
+
const body = [
|
|
398
|
+
fileStructureSection,
|
|
399
|
+
escapeForMdx(skillBody),
|
|
400
|
+
]
|
|
401
|
+
.filter(Boolean)
|
|
402
|
+
.join("\n\n");
|
|
403
|
+
|
|
404
|
+
const mdx = `---
|
|
405
|
+
title: "${escapeTitle(name)}"
|
|
406
|
+
description: "${escapeTitle(shortDesc)}"
|
|
407
|
+
sidebar_label: "${escapeTitle(name)}"
|
|
408
|
+
generated: true
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
${body}`;
|
|
412
|
+
|
|
413
|
+
// Write skill page as flat file
|
|
414
|
+
fs.writeFileSync(path.join(outputDir, `${dir}.mdx`), mdx);
|
|
415
|
+
|
|
416
|
+
// Generate unlisted sub-pages (flat files with custom slug for nested breadcrumbs)
|
|
417
|
+
// File: <dir>--ref-<name>.mdx, slug: claude-skills/<dir>/ref-<name>
|
|
418
|
+
const skillSlugBase = `claude-skills/${dir}`;
|
|
419
|
+
|
|
420
|
+
for (const ref of references) {
|
|
421
|
+
const subSlug = `${skillSlugBase}/ref-${ref.name}`;
|
|
422
|
+
const refMdx = `---
|
|
423
|
+
title: "${escapeTitle(ref.title)}"
|
|
424
|
+
slug: "${subSlug}"
|
|
425
|
+
unlisted: true
|
|
426
|
+
generated: true
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
${escapeForMdx(ref.content.trim())}
|
|
430
|
+
`;
|
|
431
|
+
fs.writeFileSync(path.join(outputDir, `${dir}--ref-${ref.name}.mdx`), refMdx);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
for (const f of scriptFiles.filter((s) => s.endsWith(".md"))) {
|
|
435
|
+
const slug = f.replace(/\.md$/, "");
|
|
436
|
+
const subSlug = `${skillSlugBase}/script-${slug}`;
|
|
437
|
+
const raw = fs.readFileSync(
|
|
438
|
+
path.join(skillsDir, dir, "scripts", f),
|
|
439
|
+
"utf8",
|
|
440
|
+
);
|
|
441
|
+
const h1Match = raw.match(/^#\s+(.+)$/m);
|
|
442
|
+
const title = h1Match ? h1Match[1] : slug;
|
|
443
|
+
fs.writeFileSync(
|
|
444
|
+
path.join(outputDir, `${dir}--script-${slug}.mdx`),
|
|
445
|
+
`---\ntitle: "${escapeTitle(title)}"\nslug: "${subSlug}"\nunlisted: true\ngenerated: true\n---\n\n${escapeForMdx(raw.trim())}\n`,
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
for (const f of assetFiles.filter((a) => a.endsWith(".md"))) {
|
|
450
|
+
const slug = f.replace(/\.md$/, "");
|
|
451
|
+
const subSlug = `${skillSlugBase}/asset-${slug}`;
|
|
452
|
+
const raw = fs.readFileSync(
|
|
453
|
+
path.join(skillsDir, dir, "assets", f),
|
|
454
|
+
"utf8",
|
|
455
|
+
);
|
|
456
|
+
const h1Match = raw.match(/^#\s+(.+)$/m);
|
|
457
|
+
const title = h1Match ? h1Match[1] : slug;
|
|
458
|
+
fs.writeFileSync(
|
|
459
|
+
path.join(outputDir, `${dir}--asset-${slug}.mdx`),
|
|
460
|
+
`---\ntitle: "${escapeTitle(title)}"\nslug: "${subSlug}"\nunlisted: true\ngenerated: true\n---\n\n${escapeForMdx(raw.trim())}\n`,
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
items.sort((a, b) => a.name.localeCompare(b.name));
|
|
466
|
+
|
|
467
|
+
writeCategoryMeta(outputDir, "Skills", 902, "Skill packages");
|
|
468
|
+
return items;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ---------------------------------------------------------------------------
|
|
472
|
+
// Agents generation
|
|
473
|
+
// ---------------------------------------------------------------------------
|
|
474
|
+
|
|
475
|
+
function generateAgentsDocs(config: ClaudeResourcesConfig): AgentItem[] {
|
|
476
|
+
const agentsDir = path.join(config.claudeDir, "agents");
|
|
477
|
+
const outputDir = path.join(config.docsDir, "claude-agents");
|
|
478
|
+
|
|
479
|
+
cleanDir(outputDir);
|
|
480
|
+
|
|
481
|
+
if (!fs.existsSync(agentsDir)) return [];
|
|
482
|
+
|
|
483
|
+
const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md"));
|
|
484
|
+
if (files.length === 0) return [];
|
|
485
|
+
|
|
486
|
+
ensureDir(outputDir);
|
|
487
|
+
const items: AgentItem[] = [];
|
|
488
|
+
|
|
489
|
+
for (const file of files) {
|
|
490
|
+
const content = fs.readFileSync(path.join(agentsDir, file), "utf8");
|
|
491
|
+
const parsed = parseFrontmatter(content);
|
|
492
|
+
if (!parsed) continue;
|
|
493
|
+
|
|
494
|
+
const name = (parsed.data.name as string) || file.replace(/\.md$/, "");
|
|
495
|
+
const description = (parsed.data.description as string) || "";
|
|
496
|
+
const model = (parsed.data.model as string) || "";
|
|
497
|
+
const fileSlug = file.replace(/\.md$/, "");
|
|
498
|
+
|
|
499
|
+
items.push({ name, file: fileSlug, description, model });
|
|
500
|
+
|
|
501
|
+
const modelBadge = model ? `**Model:** \`${model}\`\n` : "";
|
|
502
|
+
|
|
503
|
+
const mdx = `---
|
|
504
|
+
title: "${escapeTitle(name)}"
|
|
505
|
+
description: "${escapeTitle(description)}"
|
|
506
|
+
sidebar_label: "${escapeTitle(name)}"
|
|
507
|
+
generated: true
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
${modelBadge}
|
|
511
|
+
${escapeForMdx(parsed.content.trim())}
|
|
512
|
+
`;
|
|
513
|
+
fs.writeFileSync(path.join(outputDir, `${fileSlug}.mdx`), mdx);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
items.sort((a, b) => a.name.localeCompare(b.name));
|
|
517
|
+
|
|
518
|
+
writeCategoryMeta(outputDir, "Agents", 903, "Custom subagents");
|
|
519
|
+
return items;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
// Main
|
|
524
|
+
// ---------------------------------------------------------------------------
|
|
525
|
+
|
|
526
|
+
function generateOverviewIndex(
|
|
527
|
+
config: ClaudeResourcesConfig,
|
|
528
|
+
{
|
|
529
|
+
hasCommands,
|
|
530
|
+
hasSkills,
|
|
531
|
+
hasAgents,
|
|
532
|
+
hasClaudemd,
|
|
533
|
+
}: { hasCommands: boolean; hasSkills: boolean; hasAgents: boolean; hasClaudemd: boolean },
|
|
534
|
+
) {
|
|
535
|
+
const outputDir = path.join(config.docsDir, "claude");
|
|
536
|
+
cleanDir(outputDir);
|
|
537
|
+
ensureDir(outputDir);
|
|
538
|
+
|
|
539
|
+
// Build the explicit slug list from whichever sub-categories were generated.
|
|
540
|
+
// CategoryNav with `categories` renders cards for each slug by resolving
|
|
541
|
+
// the node in the nav tree (including noPage auto-index categories) and
|
|
542
|
+
// falling back to docsUrl(slug, locale) for the href when noPage=true.
|
|
543
|
+
const categorySlugs: string[] = [];
|
|
544
|
+
if (hasClaudemd) categorySlugs.push("claude-md");
|
|
545
|
+
if (hasSkills) categorySlugs.push("claude-skills");
|
|
546
|
+
if (hasAgents) categorySlugs.push("claude-agents");
|
|
547
|
+
if (hasCommands) categorySlugs.push("claude-commands");
|
|
548
|
+
|
|
549
|
+
const categoriesAttr = JSON.stringify(categorySlugs);
|
|
550
|
+
|
|
551
|
+
const index = `---
|
|
552
|
+
title: "Claude"
|
|
553
|
+
description: "Claude Code configuration reference."
|
|
554
|
+
sidebar_position: 899
|
|
555
|
+
generated: true
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
Claude Code configuration reference.
|
|
559
|
+
|
|
560
|
+
## Resources
|
|
561
|
+
|
|
562
|
+
<CategoryNav categories={${categoriesAttr}} />
|
|
563
|
+
`;
|
|
564
|
+
fs.writeFileSync(path.join(outputDir, "index.mdx"), index);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export function generateClaudeResourcesDocs(config: ClaudeResourcesConfig) {
|
|
568
|
+
const claudemds = generateClaudemdDocs(config);
|
|
569
|
+
const commands = generateCommandsDocs(config);
|
|
570
|
+
const skills = generateSkillsDocs(config);
|
|
571
|
+
const agents = generateAgentsDocs(config);
|
|
572
|
+
|
|
573
|
+
generateOverviewIndex(config, {
|
|
574
|
+
hasClaudemd: claudemds.length > 0,
|
|
575
|
+
hasCommands: commands.length > 0,
|
|
576
|
+
hasSkills: skills.length > 0,
|
|
577
|
+
hasAgents: agents.length > 0,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
return {
|
|
581
|
+
claudemd: claudemds.length,
|
|
582
|
+
commands: commands.length,
|
|
583
|
+
skills: skills.length,
|
|
584
|
+
agents: agents.length,
|
|
585
|
+
};
|
|
586
|
+
}
|
package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// Side-effect import — running this module in the browser triggers
|
|
4
|
+
// configurePanel(designTokenPanelConfig) which mounts the zdtp panel
|
|
5
|
+
// and registers the `toggle-design-token-panel` window listener.
|
|
6
|
+
import "@/lib/design-token-panel-bootstrap";
|
|
7
|
+
|
|
8
|
+
import type { JSX } from "preact";
|
|
9
|
+
|
|
10
|
+
function DesignTokenPanelBootstrap(): JSX.Element | null {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
DesignTokenPanelBootstrap.displayName = "DesignTokenPanelBootstrap";
|
|
14
|
+
|
|
15
|
+
export default DesignTokenPanelBootstrap;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zdtp (zudo-design-token-panel) PanelConfig for this project.
|
|
3
|
+
*
|
|
4
|
+
* This config object is the single source of truth passed to
|
|
5
|
+
* `configurePanel(designTokenPanelConfig)` in the bootstrap module.
|
|
6
|
+
*
|
|
7
|
+
* Type notes:
|
|
8
|
+
* - zdtp's `ColorScheme` requires a `shikiTheme: string` field that is not
|
|
9
|
+
* present in zudo-doc's local `ColorScheme` type or data. The cast below
|
|
10
|
+
* (`as unknown as Record<string, ZdtpColorScheme>`) is intentional: zdtp
|
|
11
|
+
* uses `shikiTheme` only for the code-block preview inside the panel; when
|
|
12
|
+
* absent at runtime it falls back to `colorCluster.defaultShikiTheme`. No
|
|
13
|
+
* user-visible regression results from the missing field.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type {
|
|
17
|
+
PanelConfig,
|
|
18
|
+
ColorScheme as ZdtpColorScheme,
|
|
19
|
+
} from "@takazudo/zdtp";
|
|
20
|
+
import {
|
|
21
|
+
SPACING_TOKENS,
|
|
22
|
+
FONT_TOKENS,
|
|
23
|
+
SIZE_TOKENS,
|
|
24
|
+
COLOR_TOKENS,
|
|
25
|
+
} from "./design-tokens-manifest";
|
|
26
|
+
import { colorSchemes } from "./color-schemes";
|
|
27
|
+
import { SEMANTIC_DEFAULTS, SEMANTIC_CSS_NAMES } from "./color-scheme-utils";
|
|
28
|
+
import { settings } from "./settings";
|
|
29
|
+
import { DESIGN_TOKEN_SCHEMA } from "@takazudo/zudo-doc/theme";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Base-role fallback indices. Background defaults to palette index 0,
|
|
33
|
+
* foreground to 15, cursor to 6, selection to 0/15.
|
|
34
|
+
*/
|
|
35
|
+
const BASE_DEFAULTS = {
|
|
36
|
+
background: 0,
|
|
37
|
+
foreground: 15,
|
|
38
|
+
cursor: 6,
|
|
39
|
+
selectionBg: 0,
|
|
40
|
+
selectionFg: 15,
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Fallback Shiki theme used when a color scheme's `shikiTheme` field is absent.
|
|
45
|
+
*/
|
|
46
|
+
const DEFAULT_SHIKI_THEME = "github-dark";
|
|
47
|
+
|
|
48
|
+
export const designTokenPanelConfig: PanelConfig = {
|
|
49
|
+
// Customize these values to match your project name to avoid localStorage
|
|
50
|
+
// collisions when multiple zudo-doc projects run in the same browser.
|
|
51
|
+
storagePrefix: "my-doc-tweak",
|
|
52
|
+
consoleNamespace: "myDoc",
|
|
53
|
+
modalClassPrefix: "my-doc-design-token-panel-modal",
|
|
54
|
+
// Must match DESIGN_TOKEN_SCHEMA in @takazudo/zudo-doc/theme so that
|
|
55
|
+
// exported JSON files remain importable across panel versions.
|
|
56
|
+
schemaId: DESIGN_TOKEN_SCHEMA,
|
|
57
|
+
exportFilenameBase: "my-doc-design-tokens",
|
|
58
|
+
tokens: {
|
|
59
|
+
spacing: SPACING_TOKENS,
|
|
60
|
+
// TokenManifest uses "typography" (not "font") per zdtp's §3.1 contract.
|
|
61
|
+
typography: FONT_TOKENS,
|
|
62
|
+
size: SIZE_TOKENS,
|
|
63
|
+
// Empty — color is cluster-driven; zdtp reads palette via colorCluster.
|
|
64
|
+
color: COLOR_TOKENS,
|
|
65
|
+
},
|
|
66
|
+
colorCluster: {
|
|
67
|
+
id: "my-doc",
|
|
68
|
+
label: "My Doc",
|
|
69
|
+
paletteSize: 16,
|
|
70
|
+
// {n} placeholder replaced by resolvePaletteCssVar(cluster, i) at use time.
|
|
71
|
+
paletteCssVarTemplate: "--zd-{n}",
|
|
72
|
+
baseRoles: {
|
|
73
|
+
background: "--zd-bg",
|
|
74
|
+
foreground: "--zd-fg",
|
|
75
|
+
cursor: "--zd-cursor",
|
|
76
|
+
selectionBg: "--zd-sel-bg",
|
|
77
|
+
selectionFg: "--zd-sel-fg",
|
|
78
|
+
},
|
|
79
|
+
semanticDefaults: SEMANTIC_DEFAULTS,
|
|
80
|
+
semanticCssNames: SEMANTIC_CSS_NAMES,
|
|
81
|
+
baseDefaults: BASE_DEFAULTS,
|
|
82
|
+
defaultShikiTheme: DEFAULT_SHIKI_THEME,
|
|
83
|
+
// Local ColorScheme lacks shikiTheme (not in zudo-doc's type). Cast is safe:
|
|
84
|
+
// zdtp falls back to defaultShikiTheme when shikiTheme is absent at runtime.
|
|
85
|
+
colorSchemes: colorSchemes as unknown as Record<string, ZdtpColorScheme>,
|
|
86
|
+
panelSettings: {
|
|
87
|
+
colorScheme: settings.colorScheme,
|
|
88
|
+
// colorMode: strip off respectPrefersColorScheme (not in zdtp's shape).
|
|
89
|
+
colorMode: settings.colorMode
|
|
90
|
+
? {
|
|
91
|
+
defaultMode: settings.colorMode.defaultMode,
|
|
92
|
+
lightScheme: settings.colorMode.lightScheme,
|
|
93
|
+
darkScheme: settings.colorMode.darkScheme,
|
|
94
|
+
}
|
|
95
|
+
: false,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
colorPresets: {},
|
|
99
|
+
};
|