zengen 0.1.35 → 0.2.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.
Files changed (134) hide show
  1. package/.github/workflows/bump-version.yml +112 -0
  2. package/.github/workflows/ci.yml +2 -2
  3. package/.github/workflows/pages.yml +1 -7
  4. package/.zen/meta.json +155 -0
  5. package/.zen/src/en-US/01d04f7c17b4a541ead9d759d877b30b403e15b849182a49eb1f62bd29ecd18c.md +120 -0
  6. package/.zen/src/en-US/1b798c44a4f353e47296ca83d5905e37e6aba3e90bbd9bc3b3d34fc12059a2ca.md +75 -0
  7. package/.zen/src/en-US/1e96be58d76c60056b708eb5bd8b8b81d7b5845d9cfe0b879d85068a5f11df3a.md +189 -0
  8. package/.zen/src/en-US/5ec990146b35e00de2630559126ee07f7cdcddeb23b0e8cab3d85b4181353e26.md +53 -0
  9. package/.zen/src/en-US/6124ea88edec5bde737b26b21f71ecfeffe4e73151784856edf813ee231a4baa.md +11 -0
  10. package/.zen/src/en-US/80ae9bed74fc6348a7c1fe9f33e86b65f5d919169721f77bcf0e1bc29fbdb4f9.md +61 -0
  11. package/.zen/src/en-US/f0c2799126931ccd113a0c45b1e623870b0d4f4f400becf6dd877da8f1011517.md +41 -0
  12. package/.zen/src/en-US/fdfca9b960d0eaa8b2b96fe988ead7481d2c0b16f66ebc94fb477139b4178cdc.md +65 -0
  13. package/.zen/src/zh-Hans/01d04f7c17b4a541ead9d759d877b30b403e15b849182a49eb1f62bd29ecd18c.md +120 -0
  14. package/.zen/src/zh-Hans/1b798c44a4f353e47296ca83d5905e37e6aba3e90bbd9bc3b3d34fc12059a2ca.md +77 -0
  15. package/.zen/src/zh-Hans/1e96be58d76c60056b708eb5bd8b8b81d7b5845d9cfe0b879d85068a5f11df3a.md +189 -0
  16. package/.zen/src/zh-Hans/5ec990146b35e00de2630559126ee07f7cdcddeb23b0e8cab3d85b4181353e26.md +55 -0
  17. package/.zen/src/zh-Hans/6124ea88edec5bde737b26b21f71ecfeffe4e73151784856edf813ee231a4baa.md +1 -0
  18. package/.zen/src/zh-Hans/6ad8db715a1b60613fe934fefb29fa981ecad9b63145593accff144d73b44bde.md +175 -0
  19. package/.zen/src/zh-Hans/80ae9bed74fc6348a7c1fe9f33e86b65f5d919169721f77bcf0e1bc29fbdb4f9.md +63 -0
  20. package/.zen/src/zh-Hans/a1580f71c6c6c1ff4a314be72d410a8507af2f087d56360c7f5048d349c21953.md +48 -0
  21. package/.zen/src/zh-Hans/d49012f98c4367b34034063400e2f7826bf0615952210c82396920172d468e2c.md +107 -0
  22. package/.zen/src/zh-Hans/f0c2799126931ccd113a0c45b1e623870b0d4f4f400becf6dd877da8f1011517.md +41 -0
  23. package/.zen/src/zh-Hans/fdfca9b960d0eaa8b2b96fe988ead7481d2c0b16f66ebc94fb477139b4178cdc.md +65 -0
  24. package/assets/templates/default/layout.html +274 -0
  25. package/dist/ai/extractMetadataFromMarkdown.d.ts +8 -0
  26. package/dist/ai/extractMetadataFromMarkdown.d.ts.map +1 -0
  27. package/dist/ai/extractMetadataFromMarkdown.js +88 -0
  28. package/dist/ai/extractMetadataFromMarkdown.js.map +1 -0
  29. package/dist/ai/translateMarkdown.d.ts +8 -0
  30. package/dist/ai/translateMarkdown.d.ts.map +1 -0
  31. package/dist/ai/translateMarkdown.js +29 -0
  32. package/dist/ai/translateMarkdown.js.map +1 -0
  33. package/dist/build/pipeline.d.ts +6 -0
  34. package/dist/build/pipeline.d.ts.map +1 -0
  35. package/dist/build/pipeline.js +218 -0
  36. package/dist/build/pipeline.js.map +1 -0
  37. package/dist/cli.js +17 -83
  38. package/dist/cli.js.map +1 -1
  39. package/dist/findEntries.d.ts +10 -0
  40. package/dist/findEntries.d.ts.map +1 -0
  41. package/dist/findEntries.js +38 -0
  42. package/dist/findEntries.js.map +1 -0
  43. package/dist/index.d.ts +1 -32
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -35
  46. package/dist/index.js.map +1 -1
  47. package/dist/metadata.d.ts +14 -0
  48. package/dist/metadata.d.ts.map +1 -0
  49. package/dist/metadata.js +78 -0
  50. package/dist/metadata.js.map +1 -0
  51. package/dist/paths.d.ts +6 -0
  52. package/dist/paths.d.ts.map +1 -0
  53. package/dist/paths.js +10 -0
  54. package/dist/paths.js.map +1 -0
  55. package/dist/process/extractMetadataByAI.d.ts +5 -0
  56. package/dist/process/extractMetadataByAI.d.ts.map +1 -0
  57. package/dist/process/extractMetadataByAI.js +31 -0
  58. package/dist/process/extractMetadataByAI.js.map +1 -0
  59. package/dist/process/template.d.ts +5 -0
  60. package/dist/process/template.d.ts.map +1 -0
  61. package/dist/process/template.js +188 -0
  62. package/dist/process/template.js.map +1 -0
  63. package/dist/scan/files.d.ts +7 -0
  64. package/dist/scan/files.d.ts.map +1 -0
  65. package/dist/scan/files.js +54 -0
  66. package/dist/scan/files.js.map +1 -0
  67. package/dist/services/openai.d.ts +41 -0
  68. package/dist/services/openai.d.ts.map +1 -0
  69. package/dist/services/openai.js +54 -0
  70. package/dist/services/openai.js.map +1 -0
  71. package/dist/types.d.ts +26 -46
  72. package/dist/types.d.ts.map +1 -1
  73. package/dist/utils/convertMarkdownToHtml.d.ts +7 -0
  74. package/dist/utils/convertMarkdownToHtml.d.ts.map +1 -0
  75. package/dist/utils/convertMarkdownToHtml.js +39 -0
  76. package/dist/utils/convertMarkdownToHtml.js.map +1 -0
  77. package/dist/utils/frontmatter.d.ts +6 -0
  78. package/dist/utils/frontmatter.d.ts.map +1 -0
  79. package/dist/utils/frontmatter.js +22 -0
  80. package/dist/utils/frontmatter.js.map +1 -0
  81. package/docs/advanced-usage.md +39 -0
  82. package/docs/deployment/github-pages.md +1 -2
  83. package/docs/getting-started.md +26 -0
  84. package/docs/guides/best-practices.md +4 -117
  85. package/docs/guides/config.md +0 -238
  86. package/package.json +5 -2
  87. package/src/ai/extractMetadataFromMarkdown.ts +95 -0
  88. package/src/ai/translateMarkdown.ts +29 -0
  89. package/src/build/pipeline.ts +211 -0
  90. package/src/cli.ts +18 -94
  91. package/src/findEntries.ts +37 -0
  92. package/src/index.ts +1 -40
  93. package/src/metadata.ts +44 -0
  94. package/src/paths.ts +7 -0
  95. package/src/process/extractMetadataByAI.ts +29 -0
  96. package/src/process/template.ts +201 -0
  97. package/src/scan/files.ts +17 -0
  98. package/src/services/openai.ts +92 -0
  99. package/src/types.ts +29 -47
  100. package/src/utils/convertMarkdownToHtml.ts +32 -0
  101. package/src/utils/frontmatter.ts +18 -0
  102. package/test-multilang.js +44 -0
  103. package/dist/builder.d.ts +0 -46
  104. package/dist/builder.d.ts.map +0 -1
  105. package/dist/builder.js +0 -443
  106. package/dist/builder.js.map +0 -1
  107. package/dist/gitignore.d.ts +0 -40
  108. package/dist/gitignore.d.ts.map +0 -1
  109. package/dist/gitignore.js +0 -184
  110. package/dist/gitignore.js.map +0 -1
  111. package/dist/gitignore.test.d.ts +0 -2
  112. package/dist/gitignore.test.d.ts.map +0 -1
  113. package/dist/gitignore.test.js +0 -244
  114. package/dist/gitignore.test.js.map +0 -1
  115. package/dist/markdown.d.ts +0 -30
  116. package/dist/markdown.d.ts.map +0 -1
  117. package/dist/markdown.js +0 -199
  118. package/dist/markdown.js.map +0 -1
  119. package/dist/navigation.d.ts +0 -46
  120. package/dist/navigation.d.ts.map +0 -1
  121. package/dist/navigation.js +0 -196
  122. package/dist/navigation.js.map +0 -1
  123. package/dist/template.d.ts +0 -29
  124. package/dist/template.d.ts.map +0 -1
  125. package/dist/template.js +0 -385
  126. package/dist/template.js.map +0 -1
  127. package/docs/ci/github-ci-cd.md +0 -127
  128. package/docs/guides/api.md +0 -277
  129. package/src/builder.ts +0 -458
  130. package/src/gitignore.test.ts +0 -253
  131. package/src/gitignore.ts +0 -173
  132. package/src/markdown.ts +0 -184
  133. package/src/navigation.ts +0 -237
  134. package/src/template.ts +0 -365
@@ -2,95 +2,6 @@
2
2
 
3
3
  本文档介绍使用 ZEN 构建文档站点的最佳实践。
4
4
 
5
- ## 文件组织
6
-
7
- ### 推荐的文件结构
8
-
9
- ```
10
- project/
11
- ├── docs/ # 文档源文件
12
- │ ├── index.md # 首页
13
- │ ├── getting-started.md # 入门指南
14
- │ ├── api/ # API 文档目录
15
- │ │ ├── overview.md
16
- │ │ ├── core-api.md
17
- │ │ └── plugins.md
18
- │ ├── guides/ # 指南目录
19
- │ │ ├── installation.md
20
- │ │ └── configuration.md
21
- │ └── resources/ # 资源文件
22
- │ └── images/
23
- └── package.json
24
- ```
25
-
26
- **注意**: ZEN 强制使用当前目录作为源目录,所以应该切换到 `docs/` 目录下运行构建命令:
27
-
28
- ```bash
29
- cd docs
30
- npx zengen build
31
- ```
32
-
33
- ### 命名约定
34
-
35
- - 使用小写字母和连字符:`getting-started.md`
36
- - 避免特殊字符和空格
37
- - 主要页面使用简短名称:`index.md`, `api.md`
38
- - 分类页面使用目录组织
39
-
40
- ## 写作规范
41
-
42
- ### Markdown 语法
43
-
44
- **推荐:**
45
-
46
- ````markdown
47
- # 一级标题
48
-
49
- ## 二级标题
50
-
51
- ### 三级标题
52
-
53
- 使用 **粗体** 和 _斜体_ 强调重要内容。
54
-
55
- - 列表项 1
56
- - 列表项 2
57
- - 子列表项
58
-
59
- 1. 有序列表项 1
60
- 2. 有序列表项 2
61
-
62
- > 引用重要的说明或提示。
63
-
64
- `行内代码` 用于技术术语。
65
-
66
- ```javascript
67
- // 代码块示例
68
- console.log('Hello ZEN!');
69
- ```
70
- ````
71
-
72
- ````
73
-
74
- **避免:**
75
- - 过多的标题层级(超过 4 级)
76
- - 复杂的表格(考虑使用简单列表替代)
77
- - 过长的行(建议 80-100 字符换行)
78
-
79
- ### 元数据使用
80
-
81
- 在每个 Markdown 文件顶部添加 frontmatter:
82
-
83
- ```yaml
84
- ---
85
- title: 页面标题
86
- description: 简洁的页面描述
87
- keywords: [关键词1, 关键词2]
88
- author: 作者名
89
- date: 2024-01-01
90
- last_modified: 2024-01-15
91
- ---
92
- ````
93
-
94
5
  ## 多语言管理
95
6
 
96
7
  ### 翻译策略
@@ -100,30 +11,6 @@ last_modified: 2024-01-15
100
11
  3. **术语一致**: 建立术语表保持翻译一致性
101
12
  4. **人工校对**: AI 翻译后建议人工校对
102
13
 
103
- ### 翻译文件管理
104
-
105
- ```
106
- docs/
107
- ├── index.zh-CN.md # 中文源文件
108
- ├── index.en-US.md # 英文翻译
109
- ├── api/
110
- │ ├── overview.zh-CN.md
111
- │ └── overview.en-US.md
112
- └── glossary.json # 术语表
113
- ```
114
-
115
- ### 配置示例
116
-
117
- ```json
118
- {
119
- "i18n": {
120
- "sourceLang": "zh-CN",
121
- "targetLangs": ["en-US", "ja-JP"],
122
- "apiKey": "your-openai-api-key"
123
- }
124
- }
125
- ```
126
-
127
14
  ## 性能优化
128
15
 
129
16
  ### 构建优化
@@ -143,7 +30,7 @@ npx zengen build --watch
143
30
  npx zengen build --watch --serve
144
31
 
145
32
  # 生产构建
146
- npx zengen build --clean
33
+ npx zengen build
147
34
  ```
148
35
 
149
36
  ## 部署策略
@@ -176,7 +63,7 @@ jobs:
176
63
  - name: Build documentation
177
64
  run: |
178
65
  cd docs
179
- npx zengen build --clean --base-url /my-docs
66
+ npx zengen build --base-url /my-docs
180
67
 
181
68
  - name: Deploy to GitHub Pages
182
69
  uses: peaceiris/actions-gh-pages@v3
@@ -194,8 +81,8 @@ jobs:
194
81
  # 切换到文档目录
195
82
  cd docs
196
83
 
197
- # 清理并构建
198
- npx zengen build --clean
84
+ # 构建文档
85
+ npx zengen build
199
86
 
200
87
  # 同步到服务器
201
88
  rsync -avz .zen/dist/ user@server:/var/www/docs/
@@ -19,12 +19,6 @@ npx zengen build --watch --serve
19
19
  # 自定义端口
20
20
  npx zengen build --watch --serve --port 8080
21
21
 
22
- # 使用配置文件
23
- npx zengen build --config zen.config.json
24
-
25
- # 清理输出目录
26
- npx zengen build --clean
27
-
28
22
  # 显示详细日志
29
23
  npx zengen build --verbose
30
24
 
@@ -49,238 +43,6 @@ npx zengen
49
43
  | `--serve` | `-s` | 启动开发服务器(需要 `--watch`) | `false` |
50
44
  | `--port` | `-p` | 开发服务器端口 | `3000` |
51
45
  | `--host` | | 开发服务器主机 | `localhost` |
52
- | `--template` | `-t` | 自定义模板文件路径 | 内置模板 |
53
- | `--config` | `-c` | 配置文件路径 | 无 |
54
46
  | `--verbose` | `-v` | 显示详细日志 | `false` |
55
- | `--clean` | | 清理输出目录 | `false` |
56
47
  | `--base-url` | | 站点基础 URL | 无 |
57
48
  | `--help` | `-h` | 显示帮助信息 | 无 |
58
-
59
- ## 配置文件
60
-
61
- ### 配置文件格式
62
-
63
- 在项目根目录创建 `zen.config.json` 文件:
64
-
65
- ```json
66
- {
67
- "template": "./custom-template.html",
68
- "baseUrl": "/my-docs",
69
- "i18n": {
70
- "sourceLang": "zh-CN",
71
- "targetLangs": ["en-US", "ja-JP"],
72
- "apiKey": "your-openai-api-key"
73
- },
74
- "includePattern": "**/*.md",
75
- "excludePattern": "**/_*.md"
76
- }
77
- ```
78
-
79
- ### 配置项说明
80
-
81
- #### `template`
82
-
83
- - **类型**: `string`
84
- - **描述**: 自定义模板文件路径
85
- - **示例**: `"./templates/custom.html"`
86
-
87
- #### `baseUrl`
88
-
89
- - **类型**: `string`
90
- - **描述**: 站点基础 URL,用于生成绝对路径
91
- - **示例**: `"/docs"`, `"/my-project"`
92
-
93
- #### `i18n`
94
-
95
- - **类型**: `object`
96
- - **描述**: 多语言翻译配置
97
- - **字段**:
98
- - `sourceLang`: 源语言代码(如 `"zh-CN"`)
99
- - `targetLangs`: 目标语言代码数组(如 `["en-US", "ja-JP"]`)
100
- - `apiKey`: OpenAI API 密钥(可选,从环境变量读取)
101
-
102
- #### `includePattern`
103
-
104
- - **类型**: `string`
105
- - **描述**: 包含的文件模式(glob 语法)
106
- - **默认**: `"**/*.md"`
107
- - **示例**: `"**/*.{md,markdown}"`
108
-
109
- #### `excludePattern`
110
-
111
- - **类型**: `string`
112
- - **描述**: 排除的文件模式(glob 语法)
113
- - **默认**: 无
114
- - **示例**: `"**/_*.md"`, `"**/node_modules/**"`
115
-
116
- ## 模板配置
117
-
118
- ### 默认模板
119
-
120
- ZEN 使用内置的极简模板,包含:
121
-
122
- - 响应式布局
123
- - 代码高亮(使用 highlight.js)
124
- - 导航菜单
125
- - 深色/浅色主题切换
126
-
127
- ### 自定义模板
128
-
129
- 创建自定义模板文件 `custom-template.html`:
130
-
131
- ```html
132
- <!DOCTYPE html>
133
- <html lang="zh-CN">
134
- <head>
135
- <meta charset="UTF-8" />
136
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
137
- <title>{{title}}</title>
138
- <link rel="stylesheet" href="/styles.css" />
139
- </head>
140
- <body>
141
- <nav class="sidebar">{{navigation}}</nav>
142
- <main class="content">{{content}}</main>
143
- <footer>
144
- <p>由 ZEN 生成</p>
145
- </footer>
146
- </body>
147
- </html>
148
- ```
149
-
150
- **可用模板变量:**
151
-
152
- | 变量 | 描述 |
153
- | ----------------- | ------------------------- |
154
- | `{{title}}` | 页面标题 |
155
- | `{{content}}` | 转换后的 HTML 内容 |
156
- | `{{navigation}}` | 导航菜单 HTML |
157
- | `{{metadata}}` | 页面元数据(JSON 字符串) |
158
- | `{{currentPath}}` | 当前页面路径 |
159
-
160
- ### 模板位置
161
-
162
- 1. **命令行指定**: `--template ./my-template.html`
163
- 2. **配置文件指定**: `"template": "./my-template.html"`
164
- 3. **默认模板**: 内置模板
165
-
166
- ## 多语言配置
167
-
168
- ### 基本配置
169
-
170
- ```json
171
- {
172
- "i18n": {
173
- "sourceLang": "zh-CN",
174
- "targetLangs": ["en-US", "ja-JP"],
175
- "apiKey": "sk-..."
176
- }
177
- }
178
- ```
179
-
180
- ### 环境变量
181
-
182
- 也可以使用环境变量配置 API 密钥:
183
-
184
- ```bash
185
- export OPENAI_API_KEY="sk-..."
186
- npx zengen build
187
- ```
188
-
189
- ### 翻译文件结构
190
-
191
- ```
192
- docs/
193
- ├── index.md # 源文件(中文)
194
- ├── index.en-US.md # 英文翻译(自动生成)
195
- └── index.ja-JP.md # 日文翻译(自动生成)
196
- ```
197
-
198
- ### 翻译流程
199
-
200
- 1. **首次构建**: 翻译所有内容
201
- 2. **增量更新**: 只翻译新增或修改的内容
202
- 3. **手动更新**: 可以直接编辑翻译文件
203
-
204
- ## 文件处理配置
205
-
206
- ### 文件过滤
207
-
208
- ```json
209
- {
210
- "includePattern": "**/*.{md,markdown}",
211
- "excludePattern": "**/{_*,node_modules}/**"
212
- }
213
- ```
214
-
215
- ### 元数据提取
216
-
217
- 在 Markdown 文件顶部添加 YAML frontmatter:
218
-
219
- ```yaml
220
- ---
221
- title: 页面标题
222
- description: 页面描述
223
- author: 作者名
224
- date: 2024-01-01
225
- tags: [文档, 教程]
226
- ---
227
- ```
228
-
229
- ### 自定义处理器
230
-
231
- 通过 API 使用自定义处理器,配置文件不支持直接配置处理器。
232
-
233
- ## 开发服务器配置
234
-
235
- ### 基本配置
236
-
237
- ```bash
238
- # 启动开发服务器
239
- npx zengen build --watch --serve
240
-
241
- # 自定义端口和主机
242
- npx zengen build --watch --serve --port 8080 --host 0.0.0.0
243
- ```
244
-
245
- ### 服务器特性
246
-
247
- - 自动重载:文件变化时自动刷新浏览器
248
- - 静态文件服务:提供构建的文档站点
249
- - 实时预览:即时查看修改效果
250
-
251
- ## 环境配置
252
-
253
- ### Node.js 版本
254
-
255
- - **最低版本**: Node.js 16.x
256
- - **推荐版本**: Node.js 18.x 或更高
257
-
258
- ### 内存要求
259
-
260
- - 小型项目:~100MB
261
- - 大型项目:~500MB(包含翻译)
262
-
263
- ### 网络要求
264
-
265
- - 使用 AI 翻译时需要网络连接
266
- - 纯本地构建无需网络
267
-
268
- ## 最佳实践
269
-
270
- ### 配置文件管理
271
-
272
- 1. **版本控制**: 将 `zen.config.json` 加入版本控制
273
- 2. **环境变量**: 敏感信息(如 API 密钥)使用环境变量
274
- 3. **模板分离**: 自定义模板单独存放
275
-
276
- ### 性能优化
277
-
278
- 1. **增量构建**: 使用 `--watch` 模式开发
279
- 2. **文件组织**: 合理组织文档结构
280
- 3. **缓存利用**: ZEN 会自动缓存处理结果
281
-
282
- ### 错误处理
283
-
284
- 1. **详细日志**: 使用 `--verbose` 查看详细错误信息
285
- 2. **配置验证**: ZEN 会自动验证配置
286
- 3. **错误恢复**: 构建失败时会保留上次成功的结果
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zengen",
3
- "version": "0.1.35",
3
+ "version": "0.2.0",
4
4
  "description": "ZEN - A minimalist Markdown documentation site builder",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,6 +10,7 @@
10
10
  "scripts": {
11
11
  "build": "npx rimraf dist && tsc",
12
12
  "dev": "ts-node src/cli.ts",
13
+ "build:doc": "npm run build && node dist/cli.js build --lang zh-Hans --lang en-US --verbose",
13
14
  "test": "npm run build && node --test dist/**/*.test.js",
14
15
  "test:types": "tsc --noEmit",
15
16
  "test:build": "npm run build && test -f dist/index.js && test -f dist/cli.js",
@@ -54,9 +55,11 @@
54
55
  "dependencies": {
55
56
  "chokidar": "^5.0.0",
56
57
  "clipanion": "^4.0.0-rc.4",
58
+ "dotenv": "^16.4.7",
57
59
  "express": "^4.21.2",
58
60
  "highlight.js": "^11.11.1",
59
61
  "marked": "^17.0.1",
60
- "minimatch": "^10.1.1"
62
+ "minimatch": "^10.1.1",
63
+ "yaml": "^2.8.2"
61
64
  }
62
65
  }
@@ -0,0 +1,95 @@
1
+ import { completeMessages, OpenAIMessage } from '../services/openai';
2
+ import { AIMetadata } from '../types';
3
+
4
+ /**
5
+ * 从 markdown 内容中提取 metadata
6
+ * @param content Markdown 内容
7
+ * @returns Promise<AIMetadata> 提取的元数据,失败时抛出错误
8
+ */
9
+ export async function extractMetadataFromMarkdown(content: string): Promise<AIMetadata> {
10
+ const prompt = buildMetadataPrompt(content);
11
+ const messages: OpenAIMessage[] = [
12
+ {
13
+ role: 'system',
14
+ content:
15
+ '你是一个专业的文档分析助手,擅长从文档中提取结构化信息。请严格按照要求的 JSON 格式返回结果。',
16
+ },
17
+ {
18
+ role: 'user',
19
+ content: prompt,
20
+ },
21
+ ];
22
+
23
+ const response = await completeMessages(messages, {
24
+ response_format: { type: 'json_object' },
25
+ });
26
+
27
+ const metadata = parseMetadataResponse(response.choices[0].message.content);
28
+
29
+ // 添加 tokens 使用情况
30
+ metadata.tokens_used = {
31
+ prompt: response.usage.prompt_tokens,
32
+ completion: response.usage.completion_tokens,
33
+ total: response.usage.total_tokens,
34
+ };
35
+
36
+ return metadata;
37
+ }
38
+
39
+ /**
40
+ * 构建提取 metadata 的 prompt
41
+ */
42
+ function buildMetadataPrompt(content: string): string {
43
+ // 限制内容长度以避免 token 超限
44
+ const maxContentLength = 8000;
45
+ const truncatedContent =
46
+ content.length > maxContentLength
47
+ ? content.substring(0, maxContentLength) + '... [内容已截断]'
48
+ : content;
49
+
50
+ return `请分析以下文档内容,提取以下信息并返回 JSON 格式:
51
+
52
+ 文档内容:
53
+ """
54
+ ${truncatedContent}
55
+ """
56
+
57
+ 请提取:
58
+ 1. title: 文档的标题(简洁明了,不超过 20 个字)
59
+ 2. summary: 文档摘要(控制在 100 字以内,概括主要内容)
60
+ 3. tags: 关键词列表(3-8 个关键词,使用中文或英文)
61
+ 4. inferred_date: 文档中隐含的创建日期(如果有的话,格式:YYYY-MM-DD,没有就留空字符串)
62
+ 5. inferred_lang: 文档使用的语言代码(例如:zh-Hans 表示简体中文,en-US 表示美式英语)
63
+
64
+ 请严格按照以下 JSON 格式返回,不要包含任何其他文本:
65
+ {
66
+ "title": "文档标题",
67
+ "summary": "文档摘要...",
68
+ "tags": ["关键词1", "关键词2", "关键词3"],
69
+ "inferred_date": "2023-01-01",
70
+ "inferred_lang": "zh-Hans"
71
+ }`;
72
+ }
73
+
74
+ /**
75
+ * 解析 AI 返回的 metadata
76
+ */
77
+ function parseMetadataResponse(responseContent: string): AIMetadata {
78
+ try {
79
+ const metadata = JSON.parse(responseContent);
80
+
81
+ // 验证和清理数据
82
+ return {
83
+ title: metadata.title?.trim() || '未命名文档',
84
+ summary: metadata.summary?.trim() || '',
85
+ tags: Array.isArray(metadata.tags)
86
+ ? metadata.tags.map((tag: string) => tag.trim()).filter(Boolean)
87
+ : [],
88
+ inferred_date: metadata.inferred_date?.trim() || undefined,
89
+ inferred_lang: metadata.inferred_lang?.trim() || 'zh-Hans',
90
+ };
91
+ } catch (error) {
92
+ console.error('❌ Failed to parse AI response:', error, 'Response:', responseContent);
93
+ throw error;
94
+ }
95
+ }
@@ -0,0 +1,29 @@
1
+ import { completeMessages, OpenAIMessage } from '../services/openai';
2
+
3
+ /**
4
+ * 将 markdown 翻译为指定的语言
5
+ * @param content Markdown 内容
6
+ * @param targetLang 目标语言代码(例如:zh-Hans, en-US)
7
+ * @returns Promise<string> 翻译后的 Markdown 内容
8
+ */
9
+ export async function translateMarkdown(content: string, targetLang: string): Promise<string> {
10
+ const messages: OpenAIMessage[] = [
11
+ {
12
+ role: 'system',
13
+ content: `你是一个专业的翻译助手,擅长将文档翻译成不同语言,同时保持原有的格式和结构。请将用户输入翻译成 ${targetLang},注意保持 Markdown 格式不变,链接不变,不要翻译代码,但是可以翻译代码中的注释。`,
14
+ },
15
+ {
16
+ role: 'user',
17
+ content: content,
18
+ },
19
+ ];
20
+
21
+ const response = await completeMessages(messages);
22
+ const translatedContent = response.choices[0]?.message?.content?.trim() || '';
23
+
24
+ if (!translatedContent) {
25
+ throw new Error('Empty translation response');
26
+ }
27
+
28
+ return translatedContent;
29
+ }