component-auto-docs 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/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # component-auto-docs
2
+
3
+ uni-app 组件库文档自动化 CLI。
4
+
5
+ 它会从组件源码中自动抽取 `defineProps`、`defineEmits`、slots、JSDoc 和类型信息,再结合每个组件目录下的 `docs.meta.json`,生成 Markdown 文档、App 内组件文档页数据、AI 结构化索引和质量报告。
6
+
7
+ ## 安装
8
+
9
+ ```bash
10
+ pnpm add -D component-auto-docs
11
+ ```
12
+
13
+ ## 快速使用
14
+
15
+ ```bash
16
+ pnpm exec component-auto-docs scaffold
17
+ pnpm exec component-auto-docs init
18
+ pnpm exec component-auto-docs gen
19
+ pnpm exec component-auto-docs check
20
+ ```
21
+
22
+ 执行后会生成或更新:
23
+
24
+ - `docs/components/*.md`:给开发者阅读的组件 Markdown 文档。
25
+ - `docs/ai/components.catalog.json`:AI 和检索系统使用的结构化组件目录。
26
+ - `docs/ai/components.index.md`、`docs/ai/llms.txt`:AI 友好的文本索引。
27
+ - `docs/ai/components.quality.json`:文档质量报告。
28
+ - `src/docs/data.json`、`src/docs/components/*/data.json`:App 内文档页数据。
29
+ - `src/docs/components/*/index.vue`:可交互组件文档页。
30
+
31
+ ## 命令说明
32
+
33
+ - `scaffold`:向当前项目复制 `docs.config.mjs`、`src/docs/runtime/*`、`src/docs/index.vue` 和文档接入说明,并向 `package.json` 写入 `docs:init`、`docs:gen`、`docs:check`、`docs:dev` 脚本。
34
+ - `init`:初始化或补齐组件的 `docs.meta.json`、自动文档页、文档入口路由和组件文档路由。
35
+ - `gen`:生成 Markdown 文档、AI catalog、页面数据和质量报告。
36
+ - `check`:执行生成流程,并在质量报告存在 error 时以非 0 状态退出,适合放进 CI。
37
+
38
+ 已有模板文件默认不会覆盖。如需覆盖,使用:
39
+
40
+ ```bash
41
+ pnpm exec component-auto-docs scaffold --force
42
+ ```
43
+
44
+ 如果只想复制模板,不想自动修改 `package.json` 脚本,使用:
45
+
46
+ ```bash
47
+ pnpm exec component-auto-docs scaffold --no-scripts
48
+ ```
49
+
50
+ ## 配置
51
+
52
+ CLI 默认读取当前项目根目录的 `docs.config.mjs`。可以通过命令指定其他配置文件:
53
+
54
+ ```bash
55
+ pnpm exec component-auto-docs gen --config ./docs.config.mjs
56
+ ```
57
+
58
+ 也可以通过环境变量指定:
59
+
60
+ ```bash
61
+ DOCS_CONFIG=./docs.config.mjs pnpm exec component-auto-docs gen
62
+ ```
63
+
64
+ 常用配置项:
65
+
66
+ - `projectName`:项目名称,会写入 AI 文档标题。
67
+ - `componentRoot`:组件目录,默认 `src/components`。
68
+ - `metaFileName`:组件元数据文件名,默认 `docs.meta.json`。
69
+ - `output`:Markdown、AI 文档、页面数据和质量报告输出位置。
70
+ - `routes`:是否自动写入 `pages.json`,以及文档路由前缀、插入锚点、标题后缀。
71
+ - `runtime`:自动文档页使用的页面壳、hook 和组件导入别名。
72
+ - `quality`:质量检查规则,例如是否要求 App 内文档页存在。
73
+
74
+ ## docs.meta.json
75
+
76
+ 每个组件目录下建议维护一个 `docs.meta.json`:
77
+
78
+ ```json
79
+ {
80
+ "title": "按钮",
81
+ "category": "基础组件",
82
+ "description": "用于触发页面动作、提交表单或打开小程序开放能力的通用按钮。",
83
+ "useWhen": ["需要用户明确触发一个主要或次要操作时。"],
84
+ "avoidWhen": ["只展示静态文本,不需要点击反馈时。"],
85
+ "related": ["app-input", "app-dialog"],
86
+ "notes": ["新增按钮视觉类型时,应同步维护类型定义。"],
87
+ "examples": [
88
+ {
89
+ "title": "基础按钮",
90
+ "description": "使用默认主按钮样式触发提交动作。",
91
+ "code": "<app-button @click=\"onSubmit\">提交</app-button>"
92
+ }
93
+ ]
94
+ }
95
+ ```
96
+
97
+ API 信息优先从组件源码自动抽取,`docs.meta.json` 主要负责补充业务语义、使用建议和高质量示例。
98
+
99
+ ## 典型接入流程
100
+
101
+ 1. 在目标项目安装依赖:`pnpm add -D component-auto-docs`。
102
+ 2. 执行 `pnpm exec component-auto-docs scaffold`,生成配置和文档页模板。
103
+ 3. 按目标项目目录结构调整 `docs.config.mjs`。
104
+ 4. 执行 `pnpm exec component-auto-docs init`,初始化组件元数据和文档页。
105
+ 5. 人工优化各组件的 `docs.meta.json`。
106
+ 6. 执行 `pnpm exec component-auto-docs gen` 生成文档。
107
+ 7. 执行 `pnpm exec component-auto-docs check` 校验质量报告。
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
8
+ const projectRoot = process.cwd();
9
+ const command = process.argv[2] || 'help';
10
+ const args = process.argv.slice(3);
11
+
12
+ function hasFlag(name) {
13
+ return args.includes(name);
14
+ }
15
+
16
+ function printHelp() {
17
+ console.log(`component-auto-docs <command>
18
+
19
+ Commands:
20
+ scaffold Copy docs config/runtime templates into the current project
21
+ init Initialize component docs metadata, pages, and routes
22
+ gen Generate Markdown, AI catalog, and page data
23
+ check Generate docs and fail when quality errors exist
24
+
25
+ Options:
26
+ --config <path> Use a custom docs config file
27
+ --force Overwrite existing scaffold files
28
+ --no-scripts Do not add package.json docs scripts during scaffold
29
+ `);
30
+ }
31
+
32
+ function runCore(extraArgs = []) {
33
+ const coreFile = path.join(packageRoot, 'core/generate-component-docs.mjs');
34
+ const result = spawnSync(process.execPath, [coreFile, ...extraArgs, ...args], {
35
+ cwd: projectRoot,
36
+ stdio: 'inherit',
37
+ });
38
+
39
+ process.exit(result.status ?? 1);
40
+ }
41
+
42
+ function copyTemplateFile(relativePath, options) {
43
+ const source = path.join(packageRoot, 'templates', relativePath);
44
+ const target = path.join(projectRoot, relativePath);
45
+
46
+ if (!fs.existsSync(source)) return false;
47
+ if (fs.existsSync(target) && !options.force) {
48
+ options.skipped.push(relativePath);
49
+ return false;
50
+ }
51
+
52
+ fs.mkdirSync(path.dirname(target), { recursive: true });
53
+ fs.copyFileSync(source, target);
54
+ options.copied.push(relativePath);
55
+ return true;
56
+ }
57
+
58
+ function addPackageScripts(options) {
59
+ const packageFile = path.join(projectRoot, 'package.json');
60
+ if (!fs.existsSync(packageFile)) {
61
+ options.skipped.push('package.json scripts (package.json not found)');
62
+ return;
63
+ }
64
+
65
+ const packageJson = JSON.parse(fs.readFileSync(packageFile, 'utf8'));
66
+ packageJson.scripts ||= {};
67
+
68
+ const scripts = {
69
+ 'docs:init': 'component-auto-docs init',
70
+ 'docs:gen': 'component-auto-docs gen',
71
+ 'docs:check': 'component-auto-docs check',
72
+ 'docs:dev': "pnpm docs:gen && DOCS_OPEN_PATH='/#/docs/index' uni --mode development",
73
+ };
74
+
75
+ let changed = false;
76
+ for (const [name, value] of Object.entries(scripts)) {
77
+ if (packageJson.scripts[name] && !options.force) {
78
+ options.skipped.push(`package.json scripts.${name}`);
79
+ continue;
80
+ }
81
+
82
+ packageJson.scripts[name] = value;
83
+ changed = true;
84
+ }
85
+
86
+ if (changed) {
87
+ fs.writeFileSync(packageFile, `${JSON.stringify(packageJson, null, 2)}\n`);
88
+ options.copied.push('package.json docs scripts');
89
+ }
90
+ }
91
+
92
+ function scaffold() {
93
+ const options = {
94
+ force: hasFlag('--force'),
95
+ copied: [],
96
+ skipped: [],
97
+ };
98
+ const templateFiles = [
99
+ 'docs.config.mjs',
100
+ 'docs/components/README.md',
101
+ 'src/docs/index.vue',
102
+ 'src/docs/runtime/component-doc-page.vue',
103
+ 'src/docs/runtime/use-auto-component-doc.ts',
104
+ ];
105
+
106
+ for (const file of templateFiles) {
107
+ copyTemplateFile(file, options);
108
+ }
109
+
110
+ if (!hasFlag('--no-scripts')) {
111
+ addPackageScripts(options);
112
+ }
113
+
114
+ console.log(`Scaffold complete.
115
+ Copied: ${options.copied.join(', ') || 'none'}
116
+ Skipped: ${options.skipped.join(', ') || 'none'}`);
117
+ }
118
+
119
+ if (command === 'init') {
120
+ runCore(['--init']);
121
+ } else if (command === 'gen' || command === 'generate') {
122
+ runCore([]);
123
+ } else if (command === 'check') {
124
+ runCore(['--check']);
125
+ } else if (command === 'scaffold') {
126
+ scaffold();
127
+ } else {
128
+ printHelp();
129
+ process.exit(command === 'help' || command === '--help' || command === '-h' ? 0 : 1);
130
+ }