markdown-to-mfuns-json 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/README.md ADDED
@@ -0,0 +1,457 @@
1
+ # markdown-to-mfuns-json
2
+
3
+ 将 Markdown 格式的内容转换为喵御宅(Mfuns)定制的 Quill Delta JSON 格式。
4
+
5
+ 适用于:文章正文、视频简介、动态正文、评论正文等场景。
6
+
7
+ ## 安装
8
+
9
+ ```bash
10
+ npm install markdown-to-mfuns-json
11
+ ```
12
+
13
+ ```bash
14
+ yarn add markdown-to-mfuns-json
15
+ ```
16
+
17
+ ## 快速开始
18
+
19
+ ### ESM (import)
20
+
21
+ ```typescript
22
+ import { markdownToQuillDelta } from "markdown-to-mfuns-json";
23
+
24
+ const markdown = `
25
+ ## 标题
26
+
27
+ 这是一段**粗体**和*斜体*的文字。
28
+
29
+ - 列表项 1
30
+ - 列表项 2
31
+ `;
32
+
33
+ const deltaJson = markdownToQuillDelta(markdown);
34
+ console.log(deltaJson);
35
+ // 输出: {"ops":[{"insert":"标题"},{"insert":"\n","attributes":{"header":2}},{"insert":"这是一段"},{"insert":"粗体","attributes":{"bold":true}},{"insert":"和"},{"insert":"斜体","attributes":{"italic":true}},{"insert":"的文字。"},{"insert":"\n"},{"insert":"列表项 1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"列表项 2"},{"insert":"\n","attributes":{"list":"bullet"}}]}
36
+ ```
37
+
38
+ ### CommonJS (require)
39
+
40
+ ```javascript
41
+ const { markdownToQuillDelta } = require("markdown-to-mfuns-json");
42
+
43
+ const markdown = `## Hello World`;
44
+ const deltaJson = markdownToQuillDelta(markdown);
45
+ console.log(deltaJson);
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `markdownToQuillDelta(markdown, options?, uploadOptions?)`
51
+
52
+ 将 Markdown 文本转换为 Quill Delta JSON 字符串。
53
+
54
+ **参数:**
55
+
56
+ | 参数 | 类型 | 必填 | 说明 |
57
+ | --------------- | ---------------- | ---- | ----------------------------------------- |
58
+ | `markdown` | `string` | 是 | Markdown 格式的文本 |
59
+ | `options` | `ParserOptions` | 否 | 解析器配置选项 |
60
+ | `uploadOptions` | `UploadOptions` | 否 | 图片上传配置(需要上传图片到 Mfuns 时必填) |
61
+
62
+ **返回值:**
63
+
64
+ `Promise<string>` - Quill Delta JSON 格式的字符串
65
+
66
+ **示例:**
67
+
68
+ ```typescript
69
+ import { markdownToQuillDelta } from "markdown-to-mfuns-json";
70
+
71
+ // 基础用法(无图片上传)
72
+ const deltaJson = await markdownToQuillDelta("## Hello World");
73
+
74
+ // 带图片上传(需要登录后的 session token)
75
+ const deltaJson = await markdownToQuillDelta(
76
+ markdown,
77
+ {}, // ParserOptions
78
+ {
79
+ token: "your-session-token",
80
+ deviceInfo: {
81
+ clientType: "web",
82
+ deviceId: "xxx",
83
+ },
84
+ }
85
+ );
86
+ ```
87
+
88
+ ---
89
+
90
+ ### `markdownToQuillDeltaObject(markdown, options?, uploadOptions?)`
91
+
92
+ 将 Markdown 文本转换为 Quill Delta 对象(非 JSON 字符串)。
93
+
94
+ **参数:**
95
+
96
+ | 参数 | 类型 | 必填 | 说明 |
97
+ | --------------- | ---------------- | ---- | ----------------------------------------- |
98
+ | `markdown` | `string` | 是 | Markdown 格式的文本 |
99
+ | `options` | `ParserOptions` | 否 | 解析器配置选项 |
100
+ | `uploadOptions` | `UploadOptions` | 否 | 图片上传配置(需要上传图片到 Mfuns 时必填) |
101
+
102
+ **返回值:**
103
+
104
+ `Promise<QuillDelta>` - Quill Delta 对象
105
+
106
+ **示例:**
107
+
108
+ ```typescript
109
+ import { markdownToQuillDeltaObject } from "markdown-to-mfuns-json";
110
+
111
+ const deltaObj = await markdownToQuillDeltaObject("## Hello");
112
+ console.log(deltaObj.ops); // 访问 ops 数组
113
+ ```
114
+
115
+ ---
116
+
117
+ ### 空行处理说明
118
+
119
+ **默认情况下,空行会被跳过,不生成任何 Delta 操作。**
120
+
121
+ 这是因为 Quill Delta 中的空行(`{ insert: "\n" }`)在 Mfuns 平台的某些场景(如文章正文、评论等)可能会导致显示异常或多余的换行。因此默认行为是忽略所有空行。
122
+
123
+ 如果需要保留空行,可以设置 `preserveEmptyLines: true`:
124
+
125
+ ```typescript
126
+ const markdown = `第一行
127
+
128
+ 第二行`;
129
+
130
+ // 默认:跳过空行
131
+ const result1 = markdownToQuillDelta(markdown);
132
+ // 输出: [{ insert: '第一行' }, { insert: '\n' }, { insert: '第二行' }, { insert: '\n' }]
133
+
134
+ // 保留空行
135
+ const result2 = markdownToQuillDelta(markdown, { preserveEmptyLines: true });
136
+ // 输出: [{ insert: '第一行' }, { insert: '\n' }, { insert: '\n' }, { insert: '第二行' }, { insert: '\n' }]
137
+ ```
138
+
139
+ ---
140
+
141
+ ### `ParserOptions`
142
+
143
+ 解析器配置选项接口。
144
+
145
+ ```typescript
146
+ interface ParserOptions {
147
+ /**
148
+ * 是否跳过一级标题(#)
149
+ *
150
+ * **设计原因**:
151
+ * 文章/视频标题本身就是页面的 H1,正文再次出现 H1 会导致:
152
+ * 1. SEO 问题 - 搜索引擎难以确定页面核心主题,分散权重
153
+ * 2. 不符合最佳实践 - 每个页面应只有一个 H1(W3C 和无障碍访问规范)
154
+ * 3. 喵御宅建议 - 正文不建议使用一级标题
155
+ *
156
+ * @default true
157
+ */
158
+ skipH1?: boolean;
159
+
160
+ /**
161
+ * 是否跳过四级及以上标题(####, #####, ######)
162
+ *
163
+ * **设计原因**:
164
+ * 喵御宅平台只支持 1、2、3 级标题,四级及以上会被忽略
165
+ *
166
+ * @default true
167
+ */
168
+ skipHighLevelHeaders?: boolean;
169
+
170
+ /**
171
+ * 是否保留空行
172
+ *
173
+ * **设计原因**:
174
+ * 默认 false(跳过空行)。Quill Delta 中的空行在喵御宅某些场景
175
+ * (如文章正文、评论)可能导致排版异常或多余换行
176
+ *
177
+ * @default false
178
+ */
179
+ preserveEmptyLines?: boolean;
180
+ }
181
+ ```
182
+
183
+ **示例:**
184
+
185
+ ```typescript
186
+ import { markdownToQuillDelta } from "markdown-to-mfuns-json";
187
+
188
+ const markdown = `
189
+ # 一级标题(会被跳过)
190
+ ## 二级标题
191
+
192
+ 正文内容
193
+ `;
194
+
195
+ // 默认配置(跳过一级标题)
196
+ const defaultResult = markdownToQuillDelta(markdown);
197
+
198
+ // 保留一级标题
199
+ const withH1 = markdownToQuillDelta(markdown, { skipH1: false });
200
+
201
+ // 保留空行
202
+ const withEmptyLines = markdownToQuillDelta(markdown, {
203
+ preserveEmptyLines: true,
204
+ });
205
+ ```
206
+
207
+ ---
208
+
209
+ ### `UploadOptions`
210
+
211
+ 图片上传配置选项接口(用于自动上传图片到喵御宅服务器)。
212
+
213
+ ```typescript
214
+ interface UploadOptions {
215
+ /**
216
+ * Redis session token(喵御宅登录后的 session token)
217
+ * 必须提供才能上传图片到喵御宅服务器
218
+ */
219
+ token: string;
220
+
221
+ /**
222
+ * 可选设备信息
223
+ * 用于上传图片时的设备标识
224
+ */
225
+ deviceInfo?: {
226
+ clientType?: string;
227
+ deviceId?: string;
228
+ osName?: string;
229
+ osVersion?: string;
230
+ deviceModel?: string;
231
+ };
232
+
233
+ /**
234
+ * 图片上传失败时的回调
235
+ * - 'throw': 抛出错误(默认)
236
+ * - 'skip': 跳过该图片(不插入到结果中)
237
+ * - 'keep-original': 保留原 URL(base64 图片不支持)
238
+ */
239
+ onImageUploadError?: (error: Error, url: string) => 'throw' | 'skip' | 'keep-original';
240
+ }
241
+ ```
242
+
243
+ **图片处理规则:**
244
+
245
+ 1. **提供了 `token`**:
246
+ - 网络图片 URL(`https://...`):自动下载并上传到 Mfuns 服务器
247
+ - Base64 图片:解码并上传到 Mfuns 服务器
248
+ - 上传成功后,图片 URL 会被替换为 Mfuns 的 CDN 地址
249
+
250
+ 2. **未提供 `token`**:
251
+ - 网络图片 URL:保留原 URL,不上传
252
+ - Base64 图片:**抛出错误**(Mfuns 禁止 base64 格式)
253
+
254
+ **示例:**
255
+
256
+ ```typescript
257
+ import { markdownToQuillDelta } from "markdown-to-mfuns-json";
258
+
259
+ const markdown = `
260
+ ## 带图片的文章
261
+
262
+ ![网络图片](https://example.com/image.png)
263
+ ![Base64图片](data:image/png;base64,iVBORw0KGgo...)
264
+ `;
265
+
266
+ // 自动上传所有图片到 Mfuns
267
+ const deltaJson = await markdownToQuillDelta(
268
+ markdown,
269
+ {},
270
+ {
271
+ token: "your-session-token",
272
+ deviceInfo: {
273
+ clientType: "web",
274
+ deviceId: "unique-device-id",
275
+ },
276
+ }
277
+ );
278
+ ```
279
+
280
+ ---
281
+
282
+ ### `uploadImageToMfuns(file, options)`
283
+
284
+ 单独上传图片到喵御宅服务器。如果只需要上传图片而不转换 Markdown,可以使用此函数。
285
+
286
+ **参数:**
287
+
288
+ | 参数 | 类型 | 必填 | 说明 |
289
+ | --------- | --------------- | ---- | ----------------------------- |
290
+ | `file` | `File \| Blob` | 是 | 要上传的图片文件 |
291
+ | `options` | `UploadOptions` | 是 | 上传配置(必须包含 `token`) |
292
+
293
+ **返回值:**
294
+
295
+ `Promise<string>` - 上传成功后的图片 URL
296
+
297
+ **示例:**
298
+
299
+ ```typescript
300
+ import { uploadImageToMfuns } from "markdown-to-mfuns-json";
301
+
302
+ // 从文件选择器获取 File 对象
303
+ const fileInput = document.getElementById('fileInput') as HTMLInputElement;
304
+ const file = fileInput.files![0];
305
+
306
+ const imageUrl = await uploadImageToMfuns(file, {
307
+ token: "your-session-token",
308
+ });
309
+ console.log("上传成功:", imageUrl);
310
+ ```
311
+
312
+ ---
313
+
314
+ ### 类型定义
315
+
316
+ ```typescript
317
+ // Delta 操作项
318
+ interface DeltaOp {
319
+ insert: string | { [key: string]: unknown };
320
+ attributes?: { [key: string]: unknown };
321
+ }
322
+
323
+ // Quill Delta 对象
324
+ interface QuillDelta {
325
+ ops: DeltaOp[];
326
+ }
327
+ ```
328
+
329
+ ## 支持的 Markdown 语法
330
+
331
+ ### 块级元素
332
+
333
+ | Markdown | 说明 | 输出属性 |
334
+ | ------------------ | -------- | ---------------------- |
335
+ | `## 标题` | 二级标题 | `{"header": 2}` |
336
+ | `### 标题` | 三级标题 | `{"header": 3}` |
337
+ | `- 项目` | 无序列表 | `{"list": "bullet"}` |
338
+ | `1. 项目` | 有序列表 | `{"list": "ordered"}` |
339
+ | `\`\`\`code\`\`\`` | 代码块 | `{"code-block": true}` |
340
+ | `---` 或 `***` | 分割线 | `{"divider": true}` |
341
+
342
+ ### 行内格式
343
+
344
+ | Markdown | 说明 | 输出属性 |
345
+ | --------------- | -------- | --------------------- |
346
+ | `**粗体**` | 粗体 | `{"bold": true}` |
347
+ | `*斜体*` | 斜体 | `{"italic": true}` |
348
+ | `~~删除线~~` | 删除线 | `{"strike": true}` |
349
+ | `<u>下划线</u>` | 下划线 | `{"underline": true}` |
350
+ | `[链接](url)` | 链接 | `{"link": "url"}` |
351
+ | `![图片](url)` | 图片 | `{"image": "url"}` |
352
+ | `` `代码` `` | 行内代码 | `{"code": true}` |
353
+
354
+ ### 不支持的语法
355
+
356
+ 以下 Markdown 语法会被跳过或作为普通文本处理:
357
+
358
+ - 一级标题 `# `(默认跳过,可通过 `skipH1: false` 开启)
359
+ - 四级及以上标题 `#### `(默认跳过)
360
+ - 引用块 `> `
361
+ - 表格
362
+ - 任务列表 `- [ ]`
363
+
364
+ ### 图片格式支持
365
+
366
+ | 类型 | 说明 | 处理方式 |
367
+ | ----------- | ------------------------- | --------------------------------- |
368
+ | 网络图片 | `https://example.com/xxx.png` | 提供 token 时自动下载上传,否则保留原 URL |
369
+ | Base64 图片 | `data:image/png;base64,...` | 必须提供 token,否则报错 |
370
+
371
+ 支持的图片格式:`jpg`, `jpeg`, `png`, `gif`, `webp`, `bmp`, `svg`
372
+
373
+ 最大支持:20MB
374
+
375
+ ## 完整示例
376
+
377
+ ```typescript
378
+ import {
379
+ markdownToQuillDelta,
380
+ markdownToQuillDeltaObject,
381
+ } from "markdown-to-mfuns-json";
382
+
383
+ const markdown = `
384
+ ## 文章标题
385
+
386
+ 这是一篇**示例文章**,包含多种格式:
387
+
388
+ ### 列表
389
+
390
+ - 无序列表项 1
391
+ - 无序列表项 2
392
+
393
+ 1. 有序列表项 1
394
+ 2. 有序列表项 2
395
+
396
+ ### 格式
397
+
398
+ - **粗体文字**
399
+ - *斜体文字*
400
+ - ~~删除线~~
401
+ - <u>下划线</u>
402
+ - [链接](https://example.com)
403
+ - 行内代码 \`console.log('hello')\`
404
+
405
+ ### 代码块
406
+
407
+ \`\`\`javascript
408
+ function hello() {
409
+ console.log('Hello World');
410
+ }
411
+ \`\`\`
412
+
413
+ ---
414
+
415
+ ![示例图片](https://example.com/image.png)
416
+ `;
417
+
418
+ async function main() {
419
+ // 基础用法(无图片上传)
420
+ const deltaJson = await markdownToQuillDelta(markdown);
421
+ console.log("JSON:", deltaJson);
422
+
423
+ // 获取对象
424
+ const deltaObj = await markdownToQuillDeltaObject(markdown);
425
+ console.log("对象:", deltaObj);
426
+ console.log("操作数:", deltaObj.ops.length);
427
+
428
+ // 带图片上传(需要登录后的 session token)
429
+ const deltaWithUpload = await markdownToQuillDelta(
430
+ markdown,
431
+ {}, // ParserOptions
432
+ {
433
+ token: "your-session-token-here",
434
+ }
435
+ );
436
+ console.log("带上传的 JSON:", deltaWithUpload);
437
+ }
438
+
439
+ main();
440
+ ```
441
+
442
+ ## 应用场景
443
+
444
+ 本库专为喵御宅(Mfuns)平台设计,可用于:
445
+
446
+ 1. **文章正文** - 将用户输入的 Markdown 转换为平台文章格式
447
+ 2. **视频简介** - 转换视频描述内容
448
+ 3. **动态正文** - 转换用户动态/帖子内容
449
+ 4. **评论正文** - 转换评论内容
450
+
451
+ ## Node.js 版本要求
452
+
453
+ - Node.js >= 16.0.0
454
+
455
+ ## License
456
+
457
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,6 @@
1
+ // 导出核心函数
2
+ const { markdownToQuillDelta, markdownToQuillDeltaObject, } = require('./parser.cjs');
3
+ module.exports = { markdownToQuillDelta, markdownToQuillDeltaObject, };
4
+ // 导出图片上传相关函数
5
+ const { uploadImageToMfuns, processImageUrl, isBase64Image, isImageUrl, } = require('./upload.cjs');
6
+ module.exports = { uploadImageToMfuns, processImageUrl, isBase64Image, isImageUrl, };
@@ -0,0 +1,4 @@
1
+ export type { DeltaOp, QuillDelta, InlineParseResult, ParserOptions, UploadOptions, DeviceInfo, ImageUploadErrorHandler, InlineFormat, BlockElement, } from './types.mjs';
2
+ export { markdownToQuillDelta, markdownToQuillDeltaObject, } from './parser.mjs';
3
+ export { uploadImageToMfuns, processImageUrl, isBase64Image, isImageUrl, type DeviceInfo as UploadDeviceInfo, } from './upload.mjs';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ export type { DeltaOp, QuillDelta, InlineParseResult, ParserOptions, UploadOptions, DeviceInfo, ImageUploadErrorHandler, InlineFormat, BlockElement, } from './types';
2
+ export { markdownToQuillDelta, markdownToQuillDeltaObject, } from './parser';
3
+ export { uploadImageToMfuns, processImageUrl, isBase64Image, isImageUrl, type DeviceInfo as UploadDeviceInfo, } from './upload';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,OAAO,EACP,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,UAAU,EACV,uBAAuB,EACvB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,UAAU,EACV,KAAK,UAAU,IAAI,gBAAgB,GACpC,MAAM,aAAa,CAAC"}
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ // 导出核心函数
2
+ export { markdownToQuillDelta, markdownToQuillDeltaObject, } from './parser.mjs';
3
+ // 导出图片上传相关函数
4
+ export { uploadImageToMfuns, processImageUrl, isBase64Image, isImageUrl, } from './upload.mjs';