md2xhs 1.0.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 +26 -0
- package/README.md +622 -0
- package/dist/assets/auto-render.min.js +1 -0
- package/dist/assets/katex.min.css +1 -0
- package/dist/assets/katex.min.js +1 -0
- package/dist/assets/mermaid.min.js +1646 -0
- package/dist/assets-loader.d.ts +27 -0
- package/dist/assets-loader.js +55 -0
- package/dist/converter.d.ts +87 -0
- package/dist/converter.js +421 -0
- package/dist/extensions.d.ts +20 -0
- package/dist/extensions.js +2 -0
- package/dist/file-utils.d.ts +21 -0
- package/dist/file-utils.js +69 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +24 -0
- package/dist/styles.d.ts +21 -0
- package/dist/styles.js +250 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.js +15 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 md2xhs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
This project is inspired by and based on Madopic (https://github.com/xiaolinbaba/Madopic)
|
|
26
|
+
Madopic is licensed under the MIT License.
|
package/README.md
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
# md2xhs
|
|
2
|
+
|
|
3
|
+
> 将 Markdown 转换为适合社交媒体发布的精美图片
|
|
4
|
+
|
|
5
|
+
一个基于 TypeScript 的 Node.js 库,可以将 Markdown 内容转换为精美的图片,特别适合小红书、朋友圈等社交媒体平台分享。支持数学公式、Mermaid 图表、自定义样式等丰富功能。
|
|
6
|
+
|
|
7
|
+
**本项目基于 [Madopic](https://github.com/xiaolinbaba/Madopic) 进行 Node.js 环境的实现。**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ✨ 核心特性
|
|
12
|
+
|
|
13
|
+
- 🎨 **精美样式** - 8 种内置渐变背景预设,支持自定义配色
|
|
14
|
+
- 📱 **完美适配** - 专为小红书 3:4、朋友圈比例优化
|
|
15
|
+
- 🔢 **数学公式** - 支持 KaTeX 行内和块级公式渲染
|
|
16
|
+
- 📊 **图表支持** - 内置 Mermaid,支持流程图、序列图等
|
|
17
|
+
- 💎 **卡片语法** - 创建 info/success/warning/error 样式卡片
|
|
18
|
+
- ⚙️ **高度定制** - 字体大小、内边距、背景色完全可控
|
|
19
|
+
- 🖼️ **高清输出** - 支持 2 倍及以上缩放,确保清晰度
|
|
20
|
+
- 📦 **TypeScript** - 完整类型定义,智能提示
|
|
21
|
+
- 🚀 **简单易用** - 一行代码完成转换
|
|
22
|
+
- 🔌 **离线可用** - 所有资源本地化,无需联网
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 📦 安装
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install md2xhs
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
或使用其他包管理器:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Yarn
|
|
36
|
+
yarn add md2xhs
|
|
37
|
+
|
|
38
|
+
# pnpm
|
|
39
|
+
pnpm add md2xhs
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**环境要求:**
|
|
43
|
+
|
|
44
|
+
- Node.js >= 16.0.0
|
|
45
|
+
- 自动安装 Puppeteer (用于图片渲染)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 🚀 快速开始
|
|
50
|
+
|
|
51
|
+
### 最简示例
|
|
52
|
+
|
|
53
|
+
三步即可完成 Markdown 到图片的转换:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { md2image } from 'md2xhs';
|
|
57
|
+
|
|
58
|
+
// 1. 准备 Markdown 内容
|
|
59
|
+
const markdown = '# Hello World\n\n这是一个**简单**的示例。';
|
|
60
|
+
|
|
61
|
+
// 2. 转换为图片
|
|
62
|
+
await md2image(markdown, {
|
|
63
|
+
outputPath: './output.png', // 指定输出路径
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 3. 完成!图片已生成
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 方式 1: 转换 Markdown 字符串
|
|
70
|
+
|
|
71
|
+
适合动态生成内容的场景:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { md2image } from 'md2xhs';
|
|
75
|
+
|
|
76
|
+
const markdown = `
|
|
77
|
+
# 你好,世界!
|
|
78
|
+
|
|
79
|
+
这是一个 **Markdown** 转图片的示例。
|
|
80
|
+
|
|
81
|
+
## 支持的功能
|
|
82
|
+
|
|
83
|
+
- 支持列表
|
|
84
|
+
- 支持 *斜体* 和 **粗体**
|
|
85
|
+
- 支持 \`行内代码\`
|
|
86
|
+
|
|
87
|
+
\`\`\`javascript
|
|
88
|
+
// 支持代码块
|
|
89
|
+
console.log('Hello World');
|
|
90
|
+
\`\`\`
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
// 转换为小红书格式(3:4 比例)
|
|
94
|
+
await md2image(markdown, {
|
|
95
|
+
mode: 'xhs',
|
|
96
|
+
outputPath: './output.png',
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 方式 2: 从文件转换
|
|
101
|
+
|
|
102
|
+
适合转换现有的 Markdown 文档:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { md2image } from 'md2xhs';
|
|
106
|
+
|
|
107
|
+
// 自动生成同名 .png 文件
|
|
108
|
+
await md2image('./README.md', {
|
|
109
|
+
mode: 'xhs',
|
|
110
|
+
});
|
|
111
|
+
// 生成 README.png
|
|
112
|
+
|
|
113
|
+
// 或指定输出路径
|
|
114
|
+
await md2image('./docs/guide.md', {
|
|
115
|
+
mode: 'xhs',
|
|
116
|
+
outputPath: './images/guide.png',
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 方式 3: 批量转换目录
|
|
121
|
+
|
|
122
|
+
适合批量处理多个文件:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { md2imageDir } from 'md2xhs';
|
|
126
|
+
|
|
127
|
+
// 转换目录中所有 .md 文件
|
|
128
|
+
const results = await md2imageDir('./docs', {
|
|
129
|
+
mode: 'xhs',
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
console.log(`✅ 成功转换 ${results.length} 个文件`);
|
|
133
|
+
|
|
134
|
+
// 递归转换所有子目录
|
|
135
|
+
await md2imageDir('./docs', { mode: 'xhs' }, true);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 📖 完整 API 参考
|
|
141
|
+
|
|
142
|
+
### 核心函数
|
|
143
|
+
|
|
144
|
+
#### `md2image(input, options?)`
|
|
145
|
+
|
|
146
|
+
**主要转换函数**,自动识别输入类型(字符串内容或文件路径)。
|
|
147
|
+
|
|
148
|
+
**参数:**
|
|
149
|
+
|
|
150
|
+
| 参数 | 类型 | 说明 |
|
|
151
|
+
|-----------|-------------------|-------------------------------|
|
|
152
|
+
| `input` | `string` | Markdown 字符串内容或文件路径 |
|
|
153
|
+
| `options` | `Md2ImageOptions` | 可选配置项(见下方) |
|
|
154
|
+
|
|
155
|
+
**返回值:** `Promise<ConvertResult>`
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
interface ConvertResult {
|
|
159
|
+
imagePath: string; // 生成的图片路径
|
|
160
|
+
width: number; // 图片宽度
|
|
161
|
+
height: number; // 图片高度
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**示例:**
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// 转换字符串
|
|
169
|
+
const result = await md2image('# Hello World');
|
|
170
|
+
console.log(result.imagePath); // 输出: output-xxx.png
|
|
171
|
+
|
|
172
|
+
// 转换文件
|
|
173
|
+
await md2image('./README.md', { outputPath: './readme.png' });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
#### `md2imageDir(dirPath, options?, recursive?)`
|
|
179
|
+
|
|
180
|
+
**批量转换**目录中的所有 Markdown 文件。
|
|
181
|
+
|
|
182
|
+
**参数:**
|
|
183
|
+
|
|
184
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
185
|
+
|------|------|--------|------|
|
|
186
|
+
| `dirPath` | `string` | - | 目录路径 |
|
|
187
|
+
| `options` | `Md2ImageOptions` | `{}` | 可选配置项 |
|
|
188
|
+
| `recursive` | `boolean` | `false` | 是否递归处理子目录 |
|
|
189
|
+
|
|
190
|
+
**返回值:** `Promise<ConvertResult[]>`
|
|
191
|
+
|
|
192
|
+
**示例:**
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// 转换单个目录
|
|
196
|
+
const results = await md2imageDir('./docs');
|
|
197
|
+
|
|
198
|
+
// 递归转换所有子目录
|
|
199
|
+
const allResults = await md2imageDir('./docs', {}, true);
|
|
200
|
+
|
|
201
|
+
// 使用自定义配置
|
|
202
|
+
await md2imageDir('./docs', {
|
|
203
|
+
mode: 'xhs',
|
|
204
|
+
backgroundPreset: 'sunset'
|
|
205
|
+
}, true);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### 高级用法: Md2ImageConverter 类
|
|
211
|
+
|
|
212
|
+
当需要**复用配置**或**批量转换**时,使用 `Md2ImageConverter` 类可以提升性能(复用浏览器实例)。
|
|
213
|
+
|
|
214
|
+
**完整示例:**
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { Md2ImageConverter } from 'md2xhs';
|
|
218
|
+
|
|
219
|
+
// 1. 创建转换器实例(复用配置和浏览器)
|
|
220
|
+
const converter = new Md2ImageConverter({
|
|
221
|
+
mode: 'xhs',
|
|
222
|
+
backgroundPreset: 'sunset',
|
|
223
|
+
fontSize: 20,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// 2. 转换多个 Markdown 字符串
|
|
227
|
+
await converter.convert('# 文章 1', './output1.png');
|
|
228
|
+
await converter.convert('# 文章 2', './output2.png');
|
|
229
|
+
|
|
230
|
+
// 3. 从文件转换
|
|
231
|
+
await converter.convertFromFile('./README.md');
|
|
232
|
+
|
|
233
|
+
// 4. 批量转换
|
|
234
|
+
const results = await converter.convertBatch([
|
|
235
|
+
{ markdown: '# Title 1', outputPath: './1.png' },
|
|
236
|
+
{ markdown: '# Title 2', outputPath: './2.png' },
|
|
237
|
+
]);
|
|
238
|
+
|
|
239
|
+
// 5. 运行时更新配置
|
|
240
|
+
converter.updateOptions({ backgroundPreset: 'blue' });
|
|
241
|
+
|
|
242
|
+
// 6. 完成后关闭浏览器
|
|
243
|
+
await converter.close();
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**方法列表:**
|
|
247
|
+
|
|
248
|
+
| 方法 | 说明 | 返回值 |
|
|
249
|
+
|-----------------------------------------------------------|----------------------|----------------------------|
|
|
250
|
+
| `convert(markdown, outputPath?)` | 转换 Markdown 字符串 | `Promise<ConvertResult>` |
|
|
251
|
+
| `convertFromFile(filePath, outputPath?)` | 从文件转换 | `Promise<ConvertResult>` |
|
|
252
|
+
| `convertFromDirectory(dirPath, outputDir?, recursive?)` | 批量转换目录 | `Promise<ConvertResult[]>` |
|
|
253
|
+
| `convertBatch(items)` | 批量转换字符串数组 | `Promise<ConvertResult[]>` |
|
|
254
|
+
| `updateOptions(options)` | 更新配置 | `void` |
|
|
255
|
+
| `close()` | 关闭浏览器实例 | `Promise<void>` |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## ⚙️ 配置选项详解
|
|
260
|
+
|
|
261
|
+
### 完整配置接口
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
interface Md2ImageOptions {
|
|
265
|
+
// 🎯 导出模式
|
|
266
|
+
mode?: ExportMode | 'free' | 'xhs' | 'pyq'; // 默认: 'xhs'
|
|
267
|
+
|
|
268
|
+
// 📐 尺寸相关
|
|
269
|
+
width?: number; // 图片宽度(像素), 默认: 640
|
|
270
|
+
padding?: number; // 内边距(像素), 默认: 40
|
|
271
|
+
scale?: number; // 导出缩放倍数, 默认: 2
|
|
272
|
+
|
|
273
|
+
// ✏️ 字体相关
|
|
274
|
+
fontSize?: number; // 基础字体大小(像素), 默认: 18
|
|
275
|
+
|
|
276
|
+
// 🎨 背景相关(二选一)
|
|
277
|
+
backgroundPreset?: 'purple' | 'pink' | 'blue' | 'green' |
|
|
278
|
+
'sunset' | 'pastel' | 'peach' | 'rose';
|
|
279
|
+
|
|
280
|
+
customBackground?: {
|
|
281
|
+
colorStart: string; // 渐变起始色, 如: '#667eea'
|
|
282
|
+
colorEnd: string; // 渐变结束色, 如: '#764ba2'
|
|
283
|
+
direction: string; // 渐变方向, 如: '135deg'
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// 📂 输出相关
|
|
287
|
+
outputPath?: string; // 输出文件路径
|
|
288
|
+
|
|
289
|
+
// 🔧 扩展功能
|
|
290
|
+
extensions?: {
|
|
291
|
+
enableMath?: boolean; // 启用数学公式, 默认: true
|
|
292
|
+
enableDiagram?: boolean; // 启用 Mermaid 图表, 默认: true
|
|
293
|
+
enableCard?: boolean; // 启用卡片语法, 默认: true
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 导出模式 (mode)
|
|
299
|
+
|
|
300
|
+
控制图片的宽高比和自适应行为:
|
|
301
|
+
|
|
302
|
+
| 模式 | 说明 | 适用场景 |
|
|
303
|
+
|--------|----------------------------|------------------|
|
|
304
|
+
| `xhs` | 小红书模式,固定 3:4 比例 | 小红书发布(默认) |
|
|
305
|
+
| `pyq` | 朋友圈模式,固定 1290:2796 | 微信朋友圈分享 |
|
|
306
|
+
| `free` | 自由模式,高度自适应内容 | 通用场景 |
|
|
307
|
+
|
|
308
|
+
**使用示例:**
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { md2image, ExportMode } from 'md2xhs';
|
|
312
|
+
|
|
313
|
+
// 方式 1: 使用枚举(推荐,有类型提示)
|
|
314
|
+
await md2image(markdown, { mode: ExportMode.XHS });
|
|
315
|
+
|
|
316
|
+
// 方式 2: 使用字符串
|
|
317
|
+
await md2image(markdown, { mode: 'xhs' });
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 背景预设 (backgroundPreset)
|
|
321
|
+
|
|
322
|
+
内置 8 种精美渐变背景:
|
|
323
|
+
|
|
324
|
+
| 预设 | 描述 | 渐变颜色 |
|
|
325
|
+
|----------|----------|---------------------------|
|
|
326
|
+
| `purple` | 紫色梦幻 | #667eea → #764ba2 |
|
|
327
|
+
| `pink` | 粉红热情 | #f093fb → #f5576c |
|
|
328
|
+
| `blue` | 天空蓝 | #4facfe → #00f2fe |
|
|
329
|
+
| `green` | 清新绿 | #43e97b → #38f9d7 |
|
|
330
|
+
| `sunset` | 暖阳橙 | #fa709a → #fee140 |
|
|
331
|
+
| `pastel` | 温柔粉 | #a8edea → #fed6e3 |
|
|
332
|
+
| `peach` | 柔和橙 | #ffecd2 → #fcb69f |
|
|
333
|
+
| `rose` | 浪漫粉 | #ff9a9e → #fecfef |
|
|
334
|
+
|
|
335
|
+
**使用示例:**
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
await md2image(markdown, {
|
|
339
|
+
backgroundPreset: 'sunset', // 使用暖阳橙预设
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 自定义背景 (customBackground)
|
|
344
|
+
|
|
345
|
+
如果内置预设不满足需求,可以自定义渐变背景:
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
await md2image(markdown, {
|
|
349
|
+
customBackground: {
|
|
350
|
+
colorStart: '#FF6B6B', // 起始颜色
|
|
351
|
+
colorEnd: '#4ECDC4', // 结束颜色
|
|
352
|
+
direction: '45deg', // 渐变方向
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## 🎨 扩展功能详解
|
|
360
|
+
|
|
361
|
+
> **💡 提示**: 所有扩展功能使用**本地资源**,完全离线可用!
|
|
362
|
+
|
|
363
|
+
### 1. 数学公式 (KaTeX)
|
|
364
|
+
|
|
365
|
+
默认启用,支持行内和块级公式。
|
|
366
|
+
|
|
367
|
+
**Markdown 语法:**
|
|
368
|
+
|
|
369
|
+
```markdown
|
|
370
|
+
行内公式: $E = mc^2$
|
|
371
|
+
|
|
372
|
+
块级公式:
|
|
373
|
+
$$
|
|
374
|
+
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
|
|
375
|
+
$$
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**禁用方式:**
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
await md2image(markdown, {
|
|
382
|
+
extensions: { enableMath: false }
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 2. Mermaid 图表
|
|
387
|
+
|
|
388
|
+
默认启用,支持流程图、序列图、甘特图等。
|
|
389
|
+
|
|
390
|
+
**Markdown 语法:**
|
|
391
|
+
|
|
392
|
+
````markdown
|
|
393
|
+
```mermaid
|
|
394
|
+
graph TD
|
|
395
|
+
A[开始] --> B{判断}
|
|
396
|
+
B -->|是| C[执行]
|
|
397
|
+
B -->|否| D[结束]
|
|
398
|
+
```
|
|
399
|
+
````
|
|
400
|
+
|
|
401
|
+
**禁用方式:**
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
await md2image(markdown, {
|
|
405
|
+
extensions: { enableDiagram: false }
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### 3. 卡片语法
|
|
410
|
+
|
|
411
|
+
使用特殊语法创建彩色卡片块。
|
|
412
|
+
|
|
413
|
+
**Markdown 语法:**
|
|
414
|
+
|
|
415
|
+
```markdown
|
|
416
|
+
:::card info
|
|
417
|
+
📘 这是一个信息卡片
|
|
418
|
+
:::
|
|
419
|
+
|
|
420
|
+
:::card success
|
|
421
|
+
✅ 这是一个成功卡片
|
|
422
|
+
:::
|
|
423
|
+
|
|
424
|
+
:::card warning
|
|
425
|
+
⚠️ 这是一个警告卡片
|
|
426
|
+
:::
|
|
427
|
+
|
|
428
|
+
:::card error
|
|
429
|
+
❌ 这是一个错误卡片
|
|
430
|
+
:::
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**禁用方式:**
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
await md2image(markdown, {
|
|
437
|
+
extensions: { enableCard: false }
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 📝 更多示例
|
|
444
|
+
|
|
445
|
+
### 完整配置示例
|
|
446
|
+
|
|
447
|
+
结合所有配置选项的完整示例:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
import { md2image, ExportMode } from 'md2xhs';
|
|
451
|
+
|
|
452
|
+
await md2image(markdown, {
|
|
453
|
+
// 导出模式
|
|
454
|
+
mode: ExportMode.XHS,
|
|
455
|
+
|
|
456
|
+
// 尺寸和样式
|
|
457
|
+
width: 720,
|
|
458
|
+
padding: 50,
|
|
459
|
+
fontSize: 20,
|
|
460
|
+
scale: 3, // 3 倍高清
|
|
461
|
+
|
|
462
|
+
// 背景
|
|
463
|
+
backgroundPreset: 'sunset',
|
|
464
|
+
|
|
465
|
+
// 输出
|
|
466
|
+
outputPath: './my-output.png',
|
|
467
|
+
|
|
468
|
+
// 扩展功能
|
|
469
|
+
extensions: {
|
|
470
|
+
enableMath: true,
|
|
471
|
+
enableDiagram: true,
|
|
472
|
+
enableCard: true,
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### JavaScript (CommonJS) 用法
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
const { md2image } = require('md2xhs');
|
|
481
|
+
|
|
482
|
+
async function convertMarkdown() {
|
|
483
|
+
await md2image('# Hello World', {
|
|
484
|
+
mode: 'xhs',
|
|
485
|
+
outputPath: './output.png',
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
convertMarkdown();
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### 错误处理
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
import { md2image } from 'md2xhs';
|
|
496
|
+
|
|
497
|
+
try {
|
|
498
|
+
const result = await md2image('./article.md', {
|
|
499
|
+
mode: 'xhs',
|
|
500
|
+
outputPath: './output.png',
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
console.log(`✅ 转换成功!`);
|
|
504
|
+
console.log(`📁 文件路径: ${result.imagePath}`);
|
|
505
|
+
console.log(`📐 尺寸: ${result.width}x${result.height}`);
|
|
506
|
+
} catch (error) {
|
|
507
|
+
console.error('❌ 转换失败:', error.message);
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## 🎯 使用场景
|
|
514
|
+
|
|
515
|
+
### 社交媒体
|
|
516
|
+
|
|
517
|
+
- 📱 **小红书** - 使用 `mode: 'xhs'`,完美适配 3:4 比例
|
|
518
|
+
- 💬 **微信朋友圈** - 使用 `mode: 'pyq'`,适配朋友圈分享
|
|
519
|
+
- 📸 **Instagram/微博** - 使用 `mode: 'free'`,自适应内容高度
|
|
520
|
+
|
|
521
|
+
### 内容创作
|
|
522
|
+
|
|
523
|
+
- 📚 **知识卡片** - 制作精美的知识分享图片
|
|
524
|
+
- 💡 **技术教程** - 将代码片段和说明转为图片
|
|
525
|
+
- 📊 **数据报告** - 结合图表功能展示数据
|
|
526
|
+
- 📖 **读书笔记** - 将文字笔记转为精美图片
|
|
527
|
+
|
|
528
|
+
### 教育场景
|
|
529
|
+
|
|
530
|
+
- 🎓 **在线教学** - 制作课件和教学材料
|
|
531
|
+
- 🔢 **数学题目** - 利用公式支持展示数学内容
|
|
532
|
+
- 📝 **学习笔记** - 转换笔记为可分享的图片
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## ❓ 常见问题
|
|
537
|
+
|
|
538
|
+
### 如何提高图片质量?
|
|
539
|
+
|
|
540
|
+
使用更高的 `scale` 值:
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
await md2image(markdown, {
|
|
544
|
+
scale: 3, // 3 倍高清,文件会更大
|
|
545
|
+
});
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### 如何更改图片宽度?
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
await md2image(markdown, {
|
|
552
|
+
width: 720, // 默认 640
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### 支持哪些 Markdown 语法?
|
|
557
|
+
|
|
558
|
+
- ✅ 标题 (H1-H6)
|
|
559
|
+
- ✅ 粗体、斜体、删除线
|
|
560
|
+
- ✅ 列表(有序、无序)
|
|
561
|
+
- ✅ 代码块和行内代码
|
|
562
|
+
- ✅ 引用块
|
|
563
|
+
- ✅ 链接和图片
|
|
564
|
+
- ✅ 表格
|
|
565
|
+
- ✅ 数学公式 (KaTeX)
|
|
566
|
+
- ✅ Mermaid 图表
|
|
567
|
+
- ✅ 自定义卡片语法
|
|
568
|
+
|
|
569
|
+
### 为什么首次运行很慢?
|
|
570
|
+
|
|
571
|
+
首次运行时 Puppeteer 需要下载 Chromium 浏览器,之后就会很快了。
|
|
572
|
+
|
|
573
|
+
### 如何在 Docker 中使用?
|
|
574
|
+
|
|
575
|
+
需要安装 Chromium 依赖:
|
|
576
|
+
|
|
577
|
+
```dockerfile
|
|
578
|
+
RUN apt-get update && apt-get install -y \
|
|
579
|
+
chromium \
|
|
580
|
+
ca-certificates \
|
|
581
|
+
fonts-liberation \
|
|
582
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## 🔧 技术栈
|
|
588
|
+
|
|
589
|
+
- **TypeScript** - 类型安全的开发体验
|
|
590
|
+
- **Puppeteer** - 无头浏览器渲染引擎
|
|
591
|
+
- **Marked** - 高性能 Markdown 解析器
|
|
592
|
+
- **KaTeX** - 快速数学公式渲染
|
|
593
|
+
- **Mermaid** - 强大的图表绘制库
|
|
594
|
+
|
|
595
|
+
设计灵感来自 [Madopic](https://github.com/xiaolinbaba/Madopic) 的精美样式。
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## 📄 开源协议
|
|
600
|
+
|
|
601
|
+
MIT License - 详见 [LICENSE](LICENSE) 文件
|
|
602
|
+
|
|
603
|
+
本项目基于 [Madopic](https://github.com/xiaolinbaba/Madopic) 进行 Node.js 环境的实现,Madopic 同样采用 MIT 许可证。
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
## 🤝 参与贡献
|
|
608
|
+
|
|
609
|
+
欢迎提交 Issue 和 Pull Request!
|
|
610
|
+
|
|
611
|
+
如有问题或建议,请访问 [GitHub Issues](https://github.com/yourusername/md2xhs/issues)。
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## 🙏 致谢
|
|
616
|
+
|
|
617
|
+
- [Madopic](https://github.com/xiaolinbaba/Madopic) - 本项目的灵感来源
|
|
618
|
+
- 感谢 [@xiaolinbaba](https://github.com/xiaolinbaba) 的精美设计
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
**⭐️ 如果这个项目对你有帮助,欢迎给个 Star!**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var i=r[e];if(void 0!==i)return i.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var i={};return function(){n.d(i,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,i=0,a=e.length;n<t.length;){var o=t[n];if(i<=0&&t.slice(n,n+a)===e)return n;"\\"===o?n++:"{"===o?i++:"}"===o&&i--,n++}return-1},a=/^\\begin{/,o=function(e,t){for(var n,i=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(i.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=a.test(d)?d:e.slice(t[l].left.length,n);i.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&i.push({type:"text",data:e}),i},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var i=document.createDocumentFragment(),a=0;a<n.length;a++)if("text"===n[a].type)i.appendChild(document.createTextNode(n[a].data));else{var l=document.createElement("span"),d=n[a].data;r.displayMode=n[a].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[a].data+"` with ",e),i.appendChild(document.createTextNode(n[a].rawData));continue}i.appendChild(l)}return i},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var i=t.childNodes[n];if(3===i.nodeType){for(var a=i.textContent,o=i.nextSibling,d=0;o&&o.nodeType===Node.TEXT_NODE;)a+=o.textContent,o=o.nextSibling,d++;var s=l(a,r);if(s){for(var f=0;f<d;f++)i.nextSibling.remove();n+=s.childNodes.length-1,t.replaceChild(s,i)}else n+=d}else 1===i.nodeType&&function(){var t=" "+i.className+" ";-1===r.ignoredTags.indexOf(i.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(i,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),i=i.default}()}));
|