@wenyan-md/core 1.0.13 → 1.0.15
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 +95 -133
- package/dist/browser/wenyan-core.js +51 -51
- package/dist/core.js +430 -278
- package/dist/hltheme.js +39 -22
- package/dist/math/wenyan-math.js +9 -40
- package/dist/publish.js +166 -346
- package/dist/styles/wenyan-styles.js +19 -19
- package/dist/theme.js +388 -34
- package/dist/types/core.d.ts +17 -0
- package/dist/types/runtimeEnv.d.ts +6 -0
- package/dist/types/utils.d.ts +1 -0
- package/dist/utils-YieK94fG.js +9 -0
- package/dist/wrapper.js +15 -10
- package/package.json +8 -5
- package/dist/atom-one-dark.min-hABhDLRj.js +0 -4
- package/dist/atom-one-light.min-CwiVhPEv.js +0 -4
- package/dist/default-D-dyLptq.js +0 -184
- package/dist/dracula.min-OeyC4Nkp.js +0 -11
- package/dist/github-dark.min-DOlD5Ewr.js +0 -13
- package/dist/github.min-BZ2GvPsn.js +0 -14
- package/dist/juejin_default-13x4lhT9.js +0 -134
- package/dist/lapis-BUlsdDG6.js +0 -194
- package/dist/maize-DFW0x6O3.js +0 -194
- package/dist/medium_default-Zyy9RBMn.js +0 -135
- package/dist/monokai.min-CH2iHqHz.js +0 -4
- package/dist/orangeheart-Da7uQj8U.js +0 -184
- package/dist/phycat-CATVZm-R.js +0 -338
- package/dist/pie-Q9UMu3CB.js +0 -240
- package/dist/purple-Da1-Vfos.js +0 -183
- package/dist/rainbow-Bv0kNhYA.js +0 -168
- package/dist/solarized-dark.min-BxbYljx4.js +0 -11
- package/dist/solarized-light.min-Bb25xgOC.js +0 -11
- package/dist/toutiao_default-CLGOaI2x.js +0 -145
- package/dist/xcode.min-CG-lWQgl.js +0 -4
- package/dist/zhihu_default-Cz8bIkGO.js +0 -133
package/README.md
CHANGED
|
@@ -9,30 +9,47 @@
|
|
|
9
9
|

|
|
10
10
|
[](https://github.com/caol64/wenyan-core)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## 简介
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
**文颜(Wenyan)** 是一款多平台 Markdown 排版与发布工具,支持将 Markdown 一键转换并发布至:
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
- 微信公众号
|
|
17
|
+
- 知乎
|
|
18
|
+
- 今日头条
|
|
19
|
+
- 以及其它内容平台(持续扩展中)
|
|
20
|
+
|
|
21
|
+
文颜的目标是:**让写作者与开发者专注内容,而不是排版和平台适配**。
|
|
22
|
+
|
|
23
|
+
本仓库是 **文颜的核心库(CORE)**,适合以下场景:
|
|
24
|
+
|
|
25
|
+
- 嵌入 Node.js / Web 项目
|
|
26
|
+
- 构建自定义写作或发布系统
|
|
27
|
+
- 与 CLI / 桌面端 / MCP / AI 系统集成
|
|
28
|
+
- 二次开发排版或发布能力
|
|
29
|
+
|
|
30
|
+
## 文颜的不同版本
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
文颜目前提供多种形态,覆盖不同使用场景:
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
* [macOS App Store 版](https://github.com/caol64/wenyan) - MAC 桌面应用
|
|
35
|
+
* [跨平台桌面版](https://github.com/caol64/wenyan-pc) - Windows / Linux
|
|
36
|
+
* [CLI 版本](https://github.com/caol64/wenyan-cli) - 命令行 / CI 自动化发布
|
|
37
|
+
* [MCP 版本](https://github.com/caol64/wenyan-mcp) - AI 自动发文
|
|
38
|
+
* 👉 **CORE 版本**(本项目)- 文颜核心能力库
|
|
39
|
+
|
|
40
|
+
## 功能特性
|
|
25
41
|
|
|
26
42
|
* 使用内置主题对 Markdown 内容排版
|
|
27
|
-
*
|
|
28
|
-
*
|
|
43
|
+
* 自动处理并上传图片(本地 / 网络)
|
|
44
|
+
* 支持数学公式(MathJax)
|
|
29
45
|
* 一键发布文章到微信公众号草稿箱
|
|
46
|
+
* 可在 Node / 浏览器 环境中运行
|
|
30
47
|
|
|
31
|
-
##
|
|
48
|
+
## 主题效果预览
|
|
32
49
|
|
|
33
50
|
👉 [内置主题预览](https://yuzhi.tech/docs/wenyan/theme)
|
|
34
51
|
|
|
35
|
-
|
|
52
|
+
文颜内置并适配了多个优秀的 Typora 主题,在此感谢原作者:
|
|
36
53
|
|
|
37
54
|
- [Orange Heart](https://github.com/evgo2017/typora-theme-orange-heart)
|
|
38
55
|
- [Rainbow](https://github.com/thezbm/typora-theme-rainbow)
|
|
@@ -52,7 +69,7 @@ npm install @wenyan-md/core
|
|
|
52
69
|
yarn add @wenyan-md/core
|
|
53
70
|
```
|
|
54
71
|
|
|
55
|
-
##
|
|
72
|
+
## 基本用法
|
|
56
73
|
|
|
57
74
|
### 1. Markdown 排版美化
|
|
58
75
|
|
|
@@ -68,50 +85,37 @@ const { title, cover, content, description } = await getGzhContent(
|
|
|
68
85
|
inputContent,
|
|
69
86
|
theme,
|
|
70
87
|
highlightTheme,
|
|
71
|
-
isMacStyle
|
|
88
|
+
isMacStyle,
|
|
89
|
+
isAddFootnote,
|
|
72
90
|
);
|
|
73
91
|
```
|
|
74
92
|
|
|
75
93
|
#### 参数说明
|
|
76
94
|
|
|
77
|
-
| 参数名
|
|
78
|
-
|
|
|
79
|
-
| `inputContent`
|
|
80
|
-
| `theme`
|
|
81
|
-
| `highlightTheme` | `string`
|
|
82
|
-
| `isMacStyle`
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- orangeheart
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
- purple
|
|
93
|
-
- phycat
|
|
94
|
-
|
|
95
|
-
高亮主题可选参数:
|
|
96
|
-
|
|
97
|
-
- atom-one-dark
|
|
98
|
-
- atom-one-light
|
|
99
|
-
- dracula
|
|
100
|
-
- github-dark
|
|
101
|
-
- github
|
|
102
|
-
- monokai
|
|
103
|
-
- solarized-dark
|
|
104
|
-
- solarized-light
|
|
105
|
-
- xcode
|
|
95
|
+
| 参数名 | 类型 | 说明 |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| `inputContent` | `string` | 输入的 Markdown 文本,必填 |
|
|
98
|
+
| `theme` | `string` | 排版主题 ID,必填 |
|
|
99
|
+
| `highlightTheme` | `string` | 代码高亮主题,必填 |
|
|
100
|
+
| `isMacStyle` | `boolean` | 是否启用代码块 Mac 风格,默认开启 |
|
|
101
|
+
| `isAddFootnote` | `boolean` | 是否将链接转脚注,默认开启 |
|
|
102
|
+
|
|
103
|
+
排版主题:
|
|
104
|
+
|
|
105
|
+
- default / orangeheart / rainbow / lapis / pie / maize / purple / phycat
|
|
106
|
+
|
|
107
|
+
高亮主题:
|
|
108
|
+
|
|
109
|
+
- atom-one-dark / atom-one-light / dracula / github-dark / github / monokai / solarized-dark / solarized-light / xcode
|
|
106
110
|
|
|
107
111
|
#### 返回值
|
|
108
112
|
|
|
109
|
-
| 字段
|
|
110
|
-
|
|
|
111
|
-
| `title`
|
|
112
|
-
| `cover`
|
|
113
|
-
| `content`
|
|
114
|
-
| `description` | `string` |
|
|
113
|
+
| 字段 | 类型 | 说明 |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| `title` | `string` | 从 frontmatter 中获取的文章标题 |
|
|
116
|
+
| `cover` | `string` | 封面图 |
|
|
117
|
+
| `content` | `string` | 转换后的 HTML 内容 |
|
|
118
|
+
| `description` | `string` | frontmatter 中的文章简介 |
|
|
115
119
|
|
|
116
120
|
---
|
|
117
121
|
|
|
@@ -120,129 +124,87 @@ const { title, cover, content, description } = await getGzhContent(
|
|
|
120
124
|
```ts
|
|
121
125
|
import { publishToDraft } from "@wenyan-md/core/publish";
|
|
122
126
|
|
|
123
|
-
|
|
124
|
-
const wechatAppId = process.env.WECHAT_APP_ID;
|
|
125
|
-
const wechatAppSecret = process.env.WECHAT_APP_SECRET;
|
|
126
|
-
|
|
127
|
-
if (!wechatAppId || !wechatAppSecret) {
|
|
128
|
-
console.error("WECHAT_APP_ID and WECHAT_APP_SECRET must be set as environment variables.");
|
|
129
|
-
process.exit(1);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const data = await publishToDraft(title, content, cover);
|
|
127
|
+
const data = await publishToDraft(title, content, cover, wechatAppId, wechatAppSecret);
|
|
133
128
|
|
|
134
129
|
if (data.media_id) {
|
|
135
|
-
console.log(
|
|
136
|
-
} else {
|
|
137
|
-
console.error(`上传失败,\n${data}`);
|
|
130
|
+
console.log("上传成功:", data.media_id);
|
|
138
131
|
}
|
|
139
|
-
|
|
140
|
-
// 方式2,你可以直接以参数形式传入WECHAT_APP_ID和WECHAT_APP_SECRET
|
|
141
|
-
|
|
142
|
-
const data = await publishToDraft(title, content, cover, wechatAppId, wechatAppSecret);
|
|
143
132
|
```
|
|
144
133
|
|
|
145
134
|
#### 参数说明
|
|
146
135
|
|
|
147
|
-
| 参数名
|
|
148
|
-
|
|
|
149
|
-
| `title`
|
|
150
|
-
| `content` | `string` |
|
|
151
|
-
| `cover`
|
|
152
|
-
|
|
153
|
-
|
|
136
|
+
| 参数名 | 类型 | 说明 |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `title` | `string` | 文章标题 |
|
|
139
|
+
| `content` | `string` | HTML 内容 |
|
|
140
|
+
| `cover` | `string` | 封面图 URL |
|
|
141
|
+
| `wechatAppId` | `string` | 微信公众号 APPID |
|
|
142
|
+
| `wechatAppSecret` | `string` | 微信公众号 APP_SECRET |
|
|
154
143
|
|
|
155
|
-
|
|
144
|
+
#### 环境变量注入APPID和APP_SECRET
|
|
156
145
|
|
|
157
|
-
|
|
158
|
-
| ---------- | -------- | --------------------- |
|
|
159
|
-
| `media_id` | `string` | 草稿的 media\_id,后续发布时需要 |
|
|
146
|
+
也可以通过环境变量注入APPID和APP_SECRET:
|
|
160
147
|
|
|
161
|
-
|
|
148
|
+
```sh
|
|
149
|
+
export WECHAT_APP_ID=xxx
|
|
150
|
+
export WECHAT_APP_SECRET=yyy
|
|
151
|
+
```
|
|
162
152
|
|
|
163
|
-
|
|
153
|
+
```ts
|
|
154
|
+
import { publishToDraft } from "@wenyan-md/core/publish";
|
|
164
155
|
|
|
165
|
-
|
|
166
|
-
* `WECHAT_APP_SECRET`
|
|
156
|
+
const data = await publishToDraft(title, content, cover);
|
|
167
157
|
|
|
168
|
-
|
|
158
|
+
if (data.media_id) {
|
|
159
|
+
console.log("上传成功:", data.media_id);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
169
162
|
|
|
170
163
|
## 浏览器直接使用
|
|
171
164
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
推荐使用 **[unpkg](https://unpkg.com/)** 或 **[jsDelivr](https://www.jsdelivr.com/)**。
|
|
175
|
-
|
|
176
|
-
浏览器版本的文颜需自行引入依赖`highlight.js`和`csstree`。
|
|
165
|
+
文颜 CORE 提供浏览器可直接引入的 IIFE 构建版本,适合前端或纯静态页面使用。目前不支持“发布到微信公众号草稿箱”功能。
|
|
177
166
|
|
|
178
167
|
```html
|
|
179
|
-
<!-- 添加依赖 -->
|
|
180
168
|
<script src="https://cdn.jsdelivr.net/npm/css-tree/dist/csstree.js"></script>
|
|
181
169
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
|
|
182
|
-
|
|
183
|
-
<!-- 从 unpkg 引入 -->
|
|
184
|
-
<script src="https://unpkg.com/@wenyan-md/core/dist/math/wenyan-math.js"></script>
|
|
185
|
-
<script src="https://unpkg.com/@wenyan-md/core/dist/styles/wenyan-styles.js"></script>
|
|
186
|
-
<script src="https://unpkg.com/@wenyan-md/core/dist/browser/wenyan-core.js"></script>
|
|
187
|
-
|
|
188
|
-
<!-- 或者从 jsDelivr 引入 -->
|
|
189
|
-
<script src="https://cdn.jsdelivr.net/npm/@wenyan-md/core/dist/math/wenyan-math.js"></script>
|
|
190
|
-
<script src="https://cdn.jsdelivr.net/npm/@wenyan-md/core/dist/styles/wenyan-styles.js"></script>
|
|
191
170
|
<script src="https://cdn.jsdelivr.net/npm/@wenyan-md/core/dist/browser/wenyan-core.js"></script>
|
|
192
171
|
|
|
193
172
|
<script>
|
|
194
|
-
// 使用全局变量 WenyanCore
|
|
195
173
|
const { configureMarked, renderMarkdown, themes } = WenyanCore;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const input = "# Hello from Browser";
|
|
200
|
-
const content = await renderMarkdown(input);
|
|
201
|
-
const theme = themes["lapis"];
|
|
202
|
-
const styledCss = await theme.getCss();
|
|
203
|
-
const style = document.createElement("style");
|
|
204
|
-
style.textContent = styledCss;
|
|
205
|
-
document.head.appendChild(style);
|
|
206
|
-
document.body.innerHTML = content;
|
|
207
|
-
})();
|
|
174
|
+
configureMarked();
|
|
175
|
+
const html = await renderMarkdown('# Hello from Browser');
|
|
176
|
+
document.body.innerHTML = html;
|
|
208
177
|
</script>
|
|
209
178
|
```
|
|
210
179
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
## 微信公众号 IP 白名单
|
|
214
|
-
|
|
215
|
-
请务必将服务器 IP 加入公众号平台的 IP 白名单,以确保上传接口调用成功。
|
|
216
|
-
详细配置说明请参考:[https://yuzhi.tech/docs/wenyan/upload](https://yuzhi.tech/docs/wenyan/upload)
|
|
217
|
-
|
|
218
|
-
## 配置说明(Frontmatter)
|
|
180
|
+
## Markdown Frontmatter 说明
|
|
219
181
|
|
|
220
|
-
|
|
182
|
+
每篇文章顶部需包含 frontmatter:
|
|
221
183
|
|
|
222
184
|
```md
|
|
223
185
|
---
|
|
224
|
-
title:
|
|
225
|
-
cover: /
|
|
226
|
-
description:
|
|
186
|
+
title: 示例文章
|
|
187
|
+
cover: /path/to/cover.jpg
|
|
188
|
+
description: 文章简介
|
|
227
189
|
---
|
|
228
190
|
```
|
|
229
191
|
|
|
230
|
-
* `title
|
|
231
|
-
* `cover
|
|
232
|
-
|
|
233
|
-
* 如果正文有至少一张图片,可省略,此时将使用其中一张作为封面;
|
|
234
|
-
* 如果正文无图片,则必须提供 cover。
|
|
192
|
+
* `title`:必填
|
|
193
|
+
* `cover`:本地路径或网络图片(正文有图可省略)
|
|
235
194
|
|
|
236
|
-
##
|
|
195
|
+
## 微信公众号 IP 白名单
|
|
237
196
|
|
|
238
|
-
|
|
197
|
+
> ⚠️ 重要
|
|
198
|
+
>
|
|
199
|
+
> 请确保运行服务的服务器 IP 已加入微信公众号后台 IP 白名单。
|
|
239
200
|
|
|
240
|
-
|
|
241
|
-
* 网络路径(如:`https://example.com/image.jpg`)
|
|
201
|
+
配置说明:[https://yuzhi.tech/docs/wenyan/upload](https://yuzhi.tech/docs/wenyan/upload)
|
|
242
202
|
|
|
243
203
|
## 赞助
|
|
244
204
|
|
|
245
|
-
|
|
205
|
+
如果你觉得文颜对你有帮助,可以给我家猫咪买点罐头 ❤️
|
|
206
|
+
|
|
207
|
+
[https://yuzhi.tech/sponsor](https://yuzhi.tech/sponsor)
|
|
246
208
|
|
|
247
209
|
## License
|
|
248
210
|
|