czon 0.6.8 → 0.7.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 +56 -30
- package/dist/process/template.js +5 -1
- package/dist/services/openai.js +14 -10
- package/package.json +4 -5
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
+
<div style="text-align: center; margin-bottom: 20px; font-size: 2em; font-weight: bold;">
|
|
4
|
+
<a href="https://czon.zccz14.com/">
|
|
5
|
+
🌐 View Website of CZON 🚀
|
|
6
|
+
</a>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
3
9
|
# CZON - AI-Native Markdown 内容引擎
|
|
4
10
|
|
|
5
11
|
- **C**: **C**ontent oriented | 内容为王,专注内容
|
|
@@ -7,8 +13,6 @@
|
|
|
7
13
|
- **O**: **O**rganic AI-Native | 有机的 AI 原生,深度集成 AI
|
|
8
14
|
- **N**: **N**-shaped Energy Curve | N 型能量曲线,介入创作-分发-反馈的各个环节
|
|
9
15
|
|
|
10
|
-
[> Website Demo](https://czon.zccz14.com/)
|
|
11
|
-
|
|
12
16
|
AI 时代下,作为网站内容创作者,我们可以有更智能的内容创作引擎。
|
|
13
17
|
|
|
14
18
|
**回归内容:最小化打扰,专注写作**
|
|
@@ -23,55 +27,77 @@ AI 时代下,作为网站内容创作者,我们可以有更智能的内容
|
|
|
23
27
|
|
|
24
28
|
人生苦短,我懒得翻译。人在使用母语时,才是最能发挥自身思考深度的。但同时与世界保持连接又是必要的,我不想放弃多语言的交流。于是我希望有一个工具,能让我用母语写作,同时又能让更多人看到我的内容。现在的 i18n 需要自己翻译不说,还得自己维护内容更新,太麻烦了。我选择使用 LLM 来帮我做翻译,省下了我很多时间,并且可以一键完成多国语言翻译。
|
|
25
29
|
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
1. 🌍 **自动多语言翻译**:使用 AI 进行增量翻译,让用户使用母语编写 Markdown,但是用户可以是多语言的。
|
|
29
|
-
2. 💭 **自动摘要提取**:使用 AI 对原始文本进行内容分析和提取。
|
|
30
|
-
3. 🏷️ **自动标签分类**:使用 AI 对内容进行标签和分类的提取和管理。
|
|
31
|
-
4. 🧭 **智能分类导航**:使用 AI 生成站点地图和导航,源文件的位置不敏感。
|
|
32
|
-
|
|
33
|
-
## 静态站点生成 (SSG)
|
|
34
|
-
|
|
35
|
-
CZON 内置了一个 SSG 方案,可以将任意一个包含 Markdown 的 git 文件夹构建成一个静态 HTML 站点。
|
|
30
|
+
## ✨ 核心功能
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
1. 🌍 **AI 多语言翻译**:使用 AI 进行增量翻译,让用户使用母语编写 Markdown,但是用户可以是多语言的。
|
|
33
|
+
2. 📊 **AI 元数据提取**:自动提取标题、描述、摘要、关键词、目标读者、URL 友好别名等。
|
|
34
|
+
3. 🏷️ **AI 标签分类**:使用 AI 对内容进行标签和分类的提取和管理。
|
|
35
|
+
4. 🧭 **AI 分类导航**:使用 AI 生成站点地图和导航,源文件的位置不敏感。
|
|
36
|
+
5. 🤖 **AI 全站摘要**:可使用多种风格生成全站摘要。
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
以及一些非 AI 功能点:
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
1. ⚙️ **零配置**:所有配置和缓存隐藏在 `.czon` 目录,项目结构保持整洁。
|
|
41
|
+
2. 🔄 **增量构建**:基于内容哈希检测更改,仅处理变更文件。
|
|
42
|
+
3. 📚 **Markdown 扩展支持**:原生支持 KaTeX 数学公式、Mermaid 图表、Embla 轮播图、脚注等。
|
|
43
|
+
4. 🚀 **静态站点生成**:内置 React-based SSG,生成多语言静态站点。
|
|
44
|
+
5. 🌐 **自动根据访问者语言路由**:根据访问者的语言自动路由到对应的语言版本。
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
## 📦 快速开始
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
### 前提条件
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- 已安装 [Node.js](https://nodejs.org/)(建议版本 18 及以上,需要有 npx 命令)
|
|
50
|
+
- 已安装 [Node.js](https://nodejs.org/)(建议使用 LTS 版本 24,或者版本 18 及以上,需要有 npx 命令)
|
|
50
51
|
- 已获取 [OpenAI API Key](https://platform.openai.com/account/api-keys),或者 OPENAI 兼容的 API Key
|
|
51
52
|
- 已安装 Git(用于从 Git 列出 Markdown 文件,忽略 .gitignore 规则过滤的文件)
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
配置环境变量
|
|
54
|
+
### 环境变量配置
|
|
56
55
|
|
|
57
56
|
```bash
|
|
58
57
|
export OPENAI_API_KEY="sk-xxxxxx" # 必须:请替换为您的 OpenAI API Key
|
|
59
58
|
export OPENAI_BASE_URL="https://api.openai.com/v1" # 可选,默认使用 OpenAI 官方 API
|
|
60
59
|
export OPENAI_MODEL="gpt-3.5-turbo" # 可选,默认使用 gpt-3.5-turbo 模型
|
|
61
60
|
export OPENAI_MAX_TOKENS="4096" # 可选,设置最大 token 数量限制 (忽略则使用模型的默认值,对于长文本翻译建议设置更高的值,例如 8192,具体取决于所使用的模型支持的最大 token 数量)
|
|
61
|
+
|
|
62
|
+
# 如果需要使用 HTTP 代理访问 OpenAI API,可以设置以下变量
|
|
63
|
+
export HTTPS_PROXY="http://your-proxy.com:8080" # 可选,设置 HTTPS 代理
|
|
64
|
+
export HTTP_PROXY="http://your-proxy.com:8080" # 可选,设置 HTTP 代理
|
|
62
65
|
```
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
### 构建多语言站点
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
- 不需要配置源语言,CZON 会自动检测。
|
|
69
|
+
在任意 Git 管理的文件夹中运行:
|
|
68
70
|
|
|
69
71
|
```bash
|
|
70
72
|
npx czon@latest build --lang zh-Hans --lang en-US
|
|
71
73
|
```
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
由于语言代码后续会用作静态站点生成中许多功能的一部分,请确保使用 BCP 47 标准的语言代码。例如,`zh-Hans` 代表简体中文,`en-US` 代表美国英语。您可以根据需要添加更多语言,例如 `es-ES` (西班牙语) `ja-JP`(日语)、`ko-KR`(韩语)等。
|
|
76
|
+
标准语言代码列表请参考 [IETF language tag - Wikipedia](https://en.wikipedia.org/wiki/IETF_language_tag#List_of_common_primary_language_subtags)。
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
输出目录:`.czon/dist`,后续需要部署该目录下的内容到静态站点托管平台。
|
|
79
|
+
|
|
80
|
+
详细用法请运行 `npx czon@latest --help`。
|
|
81
|
+
|
|
82
|
+
## 🔗 与其他工具的比较
|
|
83
|
+
|
|
84
|
+
| 特性 | CZON | Docusaurus | VuePress | Astro |
|
|
85
|
+
| ------------------ | ------------------------ | --------------- | --------------- | --------------- |
|
|
86
|
+
| **AI 原生** | ✅ 深度集成 | ❌ | ❌ | ❌ |
|
|
87
|
+
| **零配置** | ✅ 隐藏配置 | ❌ 需要配置文件 | ❌ 需要配置文件 | ❌ 需要配置文件 |
|
|
88
|
+
| **多语言 AI 翻译** | ✅ 自动增量翻译 | ❌ 手动翻译 | ❌ 手动翻译 | ❌ 手动翻译 |
|
|
89
|
+
| **自动分类/标签** | ✅ AI 提取 | ❌ 手动配置 | ❌ 手动配置 | ❌ 手动配置 |
|
|
90
|
+
| **Markdown 扩展** | ✅ KaTeX, Mermaid, Embla | ✅ 通过插件 | ✅ 通过插件 | ✅ 通过插件 |
|
|
91
|
+
| **主题定制** | ❌ 有限 | ✅ 丰富 | ✅ 丰富 | ✅ 丰富 |
|
|
92
|
+
|
|
93
|
+
CZON 定位为 **AI 增强的内容引擎**,而非全功能 SSG。它专注于通过 AI 提升内容创作效率,适合注重内容质量、希望减少配置负担的创作者。实际上,CZON 可以与 Docusaurus、VuePress、Astro 等 SSG 工具结合使用,作为内容生成和管理的前端引擎。
|
|
94
|
+
|
|
95
|
+
## 📞 支持
|
|
96
|
+
|
|
97
|
+
- 项目主页: [https://github.com/zccz14/CZON](https://github.com/zccz14/CZON)
|
|
98
|
+
- GitHub Issues: [https://github.com/zccz14/CZON/issues](https://github.com/zccz14/CZON/issues)
|
|
99
|
+
- Discord 讨论区: [https://discord.gg/h3QrCmz24n](https://discord.gg/h3QrCmz24n)
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
_让写作回归宁静,让内容自然生长。_
|
package/dist/process/template.js
CHANGED
|
@@ -32,9 +32,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.downloadCDNResources = exports.spiderStaticSiteGenerator = void 0;
|
|
37
40
|
const fs = __importStar(require("fs/promises"));
|
|
41
|
+
const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
|
|
38
42
|
const path = __importStar(require("path"));
|
|
39
43
|
const sitemap_1 = require("../build/sitemap");
|
|
40
44
|
const metadata_1 = require("../metadata");
|
|
@@ -147,7 +151,7 @@ const downloadCDNResources = async () => {
|
|
|
147
151
|
for (const resource of resourceMap_1.EXTERNAL_RESOURCES) {
|
|
148
152
|
const targetFilePath = path.join(paths_1.CZON_DIST_DIR, 'assets', resource.name);
|
|
149
153
|
console.info(`⬇️ Downloading resource: ${resource.url} -> ${targetFilePath}`);
|
|
150
|
-
const response = await
|
|
154
|
+
const response = await (0, make_fetch_happen_1.default)(resource.url);
|
|
151
155
|
if (!response.ok) {
|
|
152
156
|
console.error(`❌ Failed to download resource: ${resource.url}, status: ${response.status}`);
|
|
153
157
|
throw new Error(`Failed to download resource: ${resource.url}`);
|
package/dist/services/openai.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.completeMessages = void 0;
|
|
7
|
+
// 使用 make-fetch-happen 以支持代理选项 (支持环境变量 HTTP_PROXY, HTTPS_PROXY, PROXY, NO_PROXY)
|
|
8
|
+
const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
|
|
4
9
|
const startTime = Date.now();
|
|
5
10
|
let totalContentGenerated = 0;
|
|
6
11
|
const processingTaskIds = new Set();
|
|
@@ -70,7 +75,7 @@ const completeMessages = async (messages, options) => {
|
|
|
70
75
|
// for (const msg of messages) {
|
|
71
76
|
// console.info(`💬 [${msg.role}] ${msg.content}`);
|
|
72
77
|
// }
|
|
73
|
-
const response = await
|
|
78
|
+
const response = await (0, make_fetch_happen_1.default)(`${baseUrl}/chat/completions`, {
|
|
74
79
|
method: 'POST',
|
|
75
80
|
headers: {
|
|
76
81
|
'Content-Type': 'application/json',
|
|
@@ -83,17 +88,10 @@ const completeMessages = async (messages, options) => {
|
|
|
83
88
|
throw new Error(`OpenAI API error (${response.status}): ${errorText}`);
|
|
84
89
|
}
|
|
85
90
|
// 处理流式响应
|
|
86
|
-
const reader = response.body?.getReader();
|
|
87
|
-
if (!reader) {
|
|
88
|
-
throw new Error('No response body reader available');
|
|
89
|
-
}
|
|
90
91
|
const decoder = new TextDecoder();
|
|
91
92
|
let buffer = '';
|
|
92
93
|
let content = '';
|
|
93
|
-
|
|
94
|
-
const { done, value } = await reader.read();
|
|
95
|
-
if (done)
|
|
96
|
-
break;
|
|
94
|
+
const handleData = (value) => {
|
|
97
95
|
buffer += decoder.decode(value, { stream: true });
|
|
98
96
|
const lines = buffer.split('\n');
|
|
99
97
|
buffer = lines.pop() || ''; // 保留未完成的行
|
|
@@ -134,7 +132,13 @@ const completeMessages = async (messages, options) => {
|
|
|
134
132
|
}
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
|
-
}
|
|
135
|
+
};
|
|
136
|
+
//
|
|
137
|
+
await new Promise((resolve, reject) => {
|
|
138
|
+
response.body.on('data', handleData);
|
|
139
|
+
response.body.on('end', () => resolve());
|
|
140
|
+
response.body.on('error', err => reject(err));
|
|
141
|
+
});
|
|
138
142
|
// 确保所有剩余数据被解码
|
|
139
143
|
if (buffer) {
|
|
140
144
|
buffer += decoder.decode();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "czon",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "CZON - AI enhanced Markdown content engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": "dist/cli.js",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
]
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@types/chokidar": "^1.7.5",
|
|
44
43
|
"@types/express": "^5.0.6",
|
|
44
|
+
"@types/make-fetch-happen": "^10.0.4",
|
|
45
45
|
"@types/node": "^25.0.3",
|
|
46
46
|
"@types/yaml": "^1.9.6",
|
|
47
47
|
"husky": "^9.1.7",
|
|
@@ -54,11 +54,10 @@
|
|
|
54
54
|
"@opencode-ai/sdk": "^1.1.34",
|
|
55
55
|
"@types/react": "^19.2.7",
|
|
56
56
|
"@types/react-dom": "^19.2.3",
|
|
57
|
-
"chokidar": "^5.0.0",
|
|
58
57
|
"clipanion": "^4.0.0-rc.4",
|
|
59
58
|
"dotenv": "^16.4.7",
|
|
60
|
-
"express": "^4.21.2",
|
|
61
59
|
"highlight.js": "^11.11.1",
|
|
60
|
+
"make-fetch-happen": "^15.0.3",
|
|
62
61
|
"marked": "^17.0.1",
|
|
63
62
|
"marked-footnote": "^1.4.0",
|
|
64
63
|
"marked-katex-extension": "^5.1.6",
|