feishu-mcp 0.0.3 → 0.0.5
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 +86 -7
- package/dist/server.js +517 -133
- package/dist/services/feishu.js +247 -16
- package/dist/services/feishuBlocks.js +135 -0
- package/package.json +1 -1
package/dist/services/feishu.js
CHANGED
|
@@ -41,6 +41,36 @@ export class FeishuService {
|
|
|
41
41
|
this.appId = appId;
|
|
42
42
|
this.appSecret = appSecret;
|
|
43
43
|
}
|
|
44
|
+
// 包装和重新抛出错误的辅助方法
|
|
45
|
+
wrapAndThrowError(message, originalError) {
|
|
46
|
+
Logger.error(`${message}:`, originalError);
|
|
47
|
+
// 如果原始错误已经是FeishuError格式,直接重新抛出
|
|
48
|
+
if (originalError && typeof originalError === 'object' && 'status' in originalError && 'err' in originalError) {
|
|
49
|
+
throw originalError;
|
|
50
|
+
}
|
|
51
|
+
// 如果是AxiosError,抽取有用信息
|
|
52
|
+
if (originalError instanceof AxiosError && originalError.response) {
|
|
53
|
+
throw {
|
|
54
|
+
status: originalError.response.status,
|
|
55
|
+
err: `${message}: ${originalError.response.data?.msg || originalError.message || 'Unknown error'}`,
|
|
56
|
+
apiError: originalError.response.data
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// 其他类型的错误,包装为一致的格式
|
|
60
|
+
if (originalError instanceof Error) {
|
|
61
|
+
throw {
|
|
62
|
+
status: 500,
|
|
63
|
+
err: `${message}: ${originalError.message}`,
|
|
64
|
+
apiError: originalError
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// 未知错误类型
|
|
68
|
+
throw {
|
|
69
|
+
status: 500,
|
|
70
|
+
err: message,
|
|
71
|
+
apiError: originalError
|
|
72
|
+
};
|
|
73
|
+
}
|
|
44
74
|
isTokenExpired() {
|
|
45
75
|
if (!this.accessToken || !this.tokenExpireTime)
|
|
46
76
|
return true;
|
|
@@ -62,7 +92,7 @@ export class FeishuService {
|
|
|
62
92
|
Logger.log(`请求方法: POST`);
|
|
63
93
|
Logger.log(`请求数据: ${JSON.stringify(requestData, null, 2)}`);
|
|
64
94
|
const response = await axios.post(url, requestData);
|
|
65
|
-
Logger.log(`响应状态码: ${response
|
|
95
|
+
Logger.log(`响应状态码: ${response?.status}`);
|
|
66
96
|
Logger.log(`响应头: ${JSON.stringify(response.headers, null, 2)}`);
|
|
67
97
|
Logger.log(`响应数据: ${JSON.stringify(response.data, null, 2)}`);
|
|
68
98
|
if (response.data.code !== 0) {
|
|
@@ -70,6 +100,7 @@ export class FeishuService {
|
|
|
70
100
|
throw {
|
|
71
101
|
status: response.status,
|
|
72
102
|
err: response.data.msg || "Unknown error",
|
|
103
|
+
apiError: response.data
|
|
73
104
|
};
|
|
74
105
|
}
|
|
75
106
|
this.accessToken = response.data.tenant_access_token;
|
|
@@ -86,6 +117,7 @@ export class FeishuService {
|
|
|
86
117
|
throw {
|
|
87
118
|
status: error.response.status,
|
|
88
119
|
err: error.response.data?.msg || "Unknown error",
|
|
120
|
+
apiError: error.response.data
|
|
89
121
|
};
|
|
90
122
|
}
|
|
91
123
|
Logger.error('获取访问令牌时发生未知错误:', error);
|
|
@@ -128,6 +160,7 @@ export class FeishuService {
|
|
|
128
160
|
throw {
|
|
129
161
|
status: error.response.status,
|
|
130
162
|
err: error.response.data?.msg || "Unknown error",
|
|
163
|
+
apiError: error.response.data
|
|
131
164
|
};
|
|
132
165
|
}
|
|
133
166
|
Logger.error('发送请求时发生未知错误:', error);
|
|
@@ -157,16 +190,7 @@ export class FeishuService {
|
|
|
157
190
|
return docInfo;
|
|
158
191
|
}
|
|
159
192
|
catch (error) {
|
|
160
|
-
|
|
161
|
-
if (error instanceof AxiosError) {
|
|
162
|
-
Logger.error(`请求URL: ${error.config?.url}`);
|
|
163
|
-
Logger.error(`请求方法: ${error.config?.method?.toUpperCase()}`);
|
|
164
|
-
Logger.error(`状态码: ${error.response?.status}`);
|
|
165
|
-
if (error.response?.data) {
|
|
166
|
-
Logger.error(`错误详情: ${JSON.stringify(error.response.data, null, 2)}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
throw error;
|
|
193
|
+
this.wrapAndThrowError('创建文档失败', error);
|
|
170
194
|
}
|
|
171
195
|
}
|
|
172
196
|
// 获取文档信息
|
|
@@ -336,14 +360,119 @@ export class FeishuService {
|
|
|
336
360
|
throw error;
|
|
337
361
|
}
|
|
338
362
|
}
|
|
363
|
+
// 创建文本块内容
|
|
364
|
+
createTextBlockContent(textContents, align = 1) {
|
|
365
|
+
return {
|
|
366
|
+
block_type: 2, // 2表示文本块
|
|
367
|
+
text: {
|
|
368
|
+
elements: textContents.map(content => ({
|
|
369
|
+
text_run: {
|
|
370
|
+
content: content.text,
|
|
371
|
+
text_element_style: content.style || {}
|
|
372
|
+
}
|
|
373
|
+
})),
|
|
374
|
+
style: {
|
|
375
|
+
align: align // 1 居左,2 居中,3 居右
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
// 创建代码块内容
|
|
381
|
+
createCodeBlockContent(code, language = 0, wrap = false) {
|
|
382
|
+
return {
|
|
383
|
+
block_type: 14, // 14表示代码块
|
|
384
|
+
code: {
|
|
385
|
+
elements: [
|
|
386
|
+
{
|
|
387
|
+
text_run: {
|
|
388
|
+
content: code,
|
|
389
|
+
text_element_style: {
|
|
390
|
+
bold: false,
|
|
391
|
+
inline_code: false,
|
|
392
|
+
italic: false,
|
|
393
|
+
strikethrough: false,
|
|
394
|
+
underline: false
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
style: {
|
|
400
|
+
language: language,
|
|
401
|
+
wrap: wrap
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
// 创建标题块内容
|
|
407
|
+
createHeadingBlockContent(text, level = 1, align = 1) {
|
|
408
|
+
// 确保标题级别在有效范围内(1-9)
|
|
409
|
+
const safeLevel = Math.max(1, Math.min(9, level));
|
|
410
|
+
// 确保align值在合法范围内(1-3)
|
|
411
|
+
// 1表示居左,2表示居中,3表示居右
|
|
412
|
+
const safeAlign = (align === 1 || align === 2 || align === 3) ? align : 1;
|
|
413
|
+
// 根据标题级别设置block_type和对应的属性名
|
|
414
|
+
// 飞书API中,一级标题的block_type为3,二级标题为4,以此类推
|
|
415
|
+
const blockType = 2 + safeLevel; // 一级标题为3,二级标题为4,以此类推
|
|
416
|
+
const headingKey = `heading${safeLevel}`; // heading1, heading2, ...
|
|
417
|
+
// 构建块内容
|
|
418
|
+
const blockContent = {
|
|
419
|
+
block_type: blockType
|
|
420
|
+
};
|
|
421
|
+
// 设置对应级别的标题属性
|
|
422
|
+
blockContent[headingKey] = {
|
|
423
|
+
elements: [
|
|
424
|
+
{
|
|
425
|
+
text_run: {
|
|
426
|
+
content: text,
|
|
427
|
+
text_element_style: {}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
],
|
|
431
|
+
style: {
|
|
432
|
+
align: safeAlign,
|
|
433
|
+
folded: false
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
return blockContent;
|
|
437
|
+
}
|
|
438
|
+
// 批量创建文档块
|
|
439
|
+
async createDocumentBlocks(documentId, parentBlockId, blockContents, index = 0) {
|
|
440
|
+
try {
|
|
441
|
+
const docId = this.extractDocIdFromUrl(documentId);
|
|
442
|
+
if (!docId) {
|
|
443
|
+
throw new Error(`无效的文档ID: ${documentId}`);
|
|
444
|
+
}
|
|
445
|
+
Logger.log(`开始批量创建文档块,文档ID: ${docId},父块ID: ${parentBlockId},块数量: ${blockContents.length},插入位置: ${index}`);
|
|
446
|
+
const endpoint = `/docx/v1/documents/${docId}/blocks/${parentBlockId}/children?document_revision_id=-1`;
|
|
447
|
+
Logger.log(`准备请求API端点: ${endpoint}`);
|
|
448
|
+
const data = {
|
|
449
|
+
children: blockContents,
|
|
450
|
+
index: index
|
|
451
|
+
};
|
|
452
|
+
Logger.log(`请求数据: ${JSON.stringify(data, null, 2)}`);
|
|
453
|
+
const response = await this.request(endpoint, 'POST', data);
|
|
454
|
+
if (response.code !== 0) {
|
|
455
|
+
throw new Error(`批量创建文档块失败: ${response.msg}`);
|
|
456
|
+
}
|
|
457
|
+
Logger.log(`批量文档块创建成功: ${JSON.stringify(response.data, null, 2)}`);
|
|
458
|
+
return response.data;
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
Logger.error(`批量创建文档块失败:`, error);
|
|
462
|
+
throw error;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
339
465
|
// 创建标题块
|
|
340
|
-
async createHeadingBlock(documentId, parentBlockId, text, level = 1, index = 0) {
|
|
466
|
+
async createHeadingBlock(documentId, parentBlockId, text, level = 1, index = 0, align = 1) {
|
|
341
467
|
try {
|
|
342
468
|
const docId = this.extractDocIdFromUrl(documentId);
|
|
343
469
|
if (!docId) {
|
|
344
470
|
throw new Error(`无效的文档ID: ${documentId}`);
|
|
345
471
|
}
|
|
346
|
-
|
|
472
|
+
// 确保align值在合法范围内(1-3)
|
|
473
|
+
// 1表示居左,2表示居中,3表示居右
|
|
474
|
+
const safeAlign = (align === 1 || align === 2 || align === 3) ? align : 1;
|
|
475
|
+
Logger.log(`开始创建标题块,文档ID: ${docId},父块ID: ${parentBlockId},标题级别: ${level},对齐方式: ${safeAlign},插入位置: ${index}`);
|
|
347
476
|
// 确保标题级别在有效范围内(1-9)
|
|
348
477
|
const safeLevel = Math.max(1, Math.min(9, level));
|
|
349
478
|
// 根据标题级别设置block_type和对应的属性名
|
|
@@ -365,7 +494,7 @@ export class FeishuService {
|
|
|
365
494
|
}
|
|
366
495
|
],
|
|
367
496
|
style: {
|
|
368
|
-
align:
|
|
497
|
+
align: safeAlign,
|
|
369
498
|
folded: false
|
|
370
499
|
}
|
|
371
500
|
};
|
|
@@ -373,8 +502,110 @@ export class FeishuService {
|
|
|
373
502
|
return await this.createDocumentBlock(documentId, parentBlockId, blockContent, index);
|
|
374
503
|
}
|
|
375
504
|
catch (error) {
|
|
376
|
-
|
|
377
|
-
|
|
505
|
+
this.wrapAndThrowError(`创建标题块失败`, error);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
// 获取块内容
|
|
509
|
+
async getBlockContent(documentId, blockId) {
|
|
510
|
+
try {
|
|
511
|
+
const docId = this.extractDocIdFromUrl(documentId);
|
|
512
|
+
if (!docId) {
|
|
513
|
+
throw new Error(`无效的文档ID: ${documentId}`);
|
|
514
|
+
}
|
|
515
|
+
Logger.log(`开始获取块内容,文档ID: ${docId},块ID: ${blockId}`);
|
|
516
|
+
const endpoint = `/docx/v1/documents/${docId}/blocks/${blockId}?document_revision_id=-1`;
|
|
517
|
+
Logger.log(`准备请求API端点: ${endpoint}`);
|
|
518
|
+
const response = await this.request(endpoint);
|
|
519
|
+
if (response.code !== 0) {
|
|
520
|
+
throw new Error(`获取块内容失败: ${response.msg}`);
|
|
521
|
+
}
|
|
522
|
+
const blockContent = response.data?.block;
|
|
523
|
+
Logger.log(`块内容获取成功: ${JSON.stringify(blockContent, null, 2)}`);
|
|
524
|
+
return blockContent;
|
|
525
|
+
}
|
|
526
|
+
catch (error) {
|
|
527
|
+
this.wrapAndThrowError(`获取块内容失败`, error);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
// 更新块文本内容
|
|
531
|
+
async updateBlockTextContent(documentId, blockId, textElements) {
|
|
532
|
+
try {
|
|
533
|
+
const docId = this.extractDocIdFromUrl(documentId);
|
|
534
|
+
if (!docId) {
|
|
535
|
+
throw new Error(`无效的文档ID: ${documentId}`);
|
|
536
|
+
}
|
|
537
|
+
Logger.log(`开始更新块文本内容,文档ID: ${docId},块ID: ${blockId}`);
|
|
538
|
+
const endpoint = `/docx/v1/documents/${docId}/blocks/${blockId}?document_revision_id=-1`;
|
|
539
|
+
Logger.log(`准备请求API端点: ${endpoint}`);
|
|
540
|
+
const elements = textElements.map(item => ({
|
|
541
|
+
text_run: {
|
|
542
|
+
content: item.text,
|
|
543
|
+
text_element_style: item.style || {}
|
|
544
|
+
}
|
|
545
|
+
}));
|
|
546
|
+
const data = {
|
|
547
|
+
update_text_elements: {
|
|
548
|
+
elements: elements
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
Logger.log(`请求数据: ${JSON.stringify(data, null, 2)}`);
|
|
552
|
+
const response = await this.request(endpoint, 'PATCH', data);
|
|
553
|
+
if (response.code !== 0) {
|
|
554
|
+
throw new Error(`更新块文本内容失败: ${response.msg}`);
|
|
555
|
+
}
|
|
556
|
+
Logger.log(`块文本内容更新成功: ${JSON.stringify(response.data, null, 2)}`);
|
|
557
|
+
return response.data;
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
this.wrapAndThrowError(`更新块文本内容失败`, error);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
// 创建列表块内容(有序或无序)
|
|
564
|
+
createListBlockContent(text, isOrdered = false, align = 1) {
|
|
565
|
+
// 确保 align 值在合法范围内(1-3)
|
|
566
|
+
const safeAlign = (align === 1 || align === 2 || align === 3) ? align : 1;
|
|
567
|
+
// 有序列表是 block_type: 13,无序列表是 block_type: 12
|
|
568
|
+
const blockType = isOrdered ? 13 : 12;
|
|
569
|
+
const propertyKey = isOrdered ? "ordered" : "bullet";
|
|
570
|
+
// 构建块内容
|
|
571
|
+
const blockContent = {
|
|
572
|
+
block_type: blockType
|
|
573
|
+
};
|
|
574
|
+
// 设置列表属性
|
|
575
|
+
blockContent[propertyKey] = {
|
|
576
|
+
elements: [
|
|
577
|
+
{
|
|
578
|
+
text_run: {
|
|
579
|
+
content: text,
|
|
580
|
+
text_element_style: {}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
],
|
|
584
|
+
style: {
|
|
585
|
+
align: safeAlign,
|
|
586
|
+
folded: false
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
return blockContent;
|
|
590
|
+
}
|
|
591
|
+
// 创建列表块(有序或无序)
|
|
592
|
+
async createListBlock(documentId, parentBlockId, text, isOrdered = false, index = 0, align = 1) {
|
|
593
|
+
try {
|
|
594
|
+
const docId = this.extractDocIdFromUrl(documentId);
|
|
595
|
+
if (!docId) {
|
|
596
|
+
throw new Error(`无效的文档ID: ${documentId}`);
|
|
597
|
+
}
|
|
598
|
+
// 确保align值在合法范围内(1-3)
|
|
599
|
+
const safeAlign = (align === 1 || align === 2 || align === 3) ? align : 1;
|
|
600
|
+
const listType = isOrdered ? "有序" : "无序";
|
|
601
|
+
Logger.log(`开始创建${listType}列表块,文档ID: ${docId},父块ID: ${parentBlockId},对齐方式: ${safeAlign},插入位置: ${index}`);
|
|
602
|
+
// 创建列表块内容
|
|
603
|
+
const blockContent = this.createListBlockContent(text, isOrdered, safeAlign);
|
|
604
|
+
Logger.log(`列表块内容: ${JSON.stringify(blockContent, null, 2)}`);
|
|
605
|
+
return await this.createDocumentBlock(documentId, parentBlockId, blockContent, index);
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
this.wrapAndThrowError(`创建${isOrdered ? "有序" : "无序"}列表块失败`, error);
|
|
378
609
|
}
|
|
379
610
|
}
|
|
380
611
|
extractDocIdFromUrl(url) {
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 构建批量创建块的请求数据
|
|
3
|
+
* @param blocks 块内容数组
|
|
4
|
+
* @param index 插入位置索引
|
|
5
|
+
* @returns 请求数据对象
|
|
6
|
+
*/
|
|
7
|
+
export function buildCreateBlocksRequest(blocks, index = 0) {
|
|
8
|
+
return {
|
|
9
|
+
children: blocks,
|
|
10
|
+
index
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 创建文本块内容
|
|
15
|
+
* @param text 文本内容
|
|
16
|
+
* @param style 文本样式
|
|
17
|
+
* @param align 对齐方式:1左对齐,2居中,3右对齐
|
|
18
|
+
* @returns 文本块内容对象
|
|
19
|
+
*/
|
|
20
|
+
export function createTextBlockContent(textContents, align = 1) {
|
|
21
|
+
return {
|
|
22
|
+
block_type: 2, // 2表示文本块
|
|
23
|
+
text: {
|
|
24
|
+
elements: textContents.map(content => ({
|
|
25
|
+
text_run: {
|
|
26
|
+
content: content.text,
|
|
27
|
+
text_element_style: content.style || {}
|
|
28
|
+
}
|
|
29
|
+
})),
|
|
30
|
+
style: {
|
|
31
|
+
align: align // 1 居左,2 居中,3 居右
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 创建代码块内容
|
|
38
|
+
* @param code 代码内容
|
|
39
|
+
* @param language 语言类型代码
|
|
40
|
+
* @param wrap 是否自动换行
|
|
41
|
+
* @returns 代码块内容对象
|
|
42
|
+
*/
|
|
43
|
+
export function createCodeBlockContent(code, language = 0, wrap = false) {
|
|
44
|
+
return {
|
|
45
|
+
block_type: 14, // 14表示代码块
|
|
46
|
+
code: {
|
|
47
|
+
elements: [
|
|
48
|
+
{
|
|
49
|
+
text_run: {
|
|
50
|
+
content: code,
|
|
51
|
+
text_element_style: {
|
|
52
|
+
bold: false,
|
|
53
|
+
inline_code: false,
|
|
54
|
+
italic: false,
|
|
55
|
+
strikethrough: false,
|
|
56
|
+
underline: false
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
style: {
|
|
62
|
+
language: language,
|
|
63
|
+
wrap: wrap
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 创建标题块内容
|
|
70
|
+
* @param text 标题文本
|
|
71
|
+
* @param level 标题级别(1-9)
|
|
72
|
+
* @param align 对齐方式:1左对齐,2居中,3右对齐
|
|
73
|
+
* @returns 标题块内容对象
|
|
74
|
+
*/
|
|
75
|
+
export function createHeadingBlockContent(text, level = 1, align = 1) {
|
|
76
|
+
// 确保标题级别在有效范围内(1-9)
|
|
77
|
+
const safeLevel = Math.max(1, Math.min(9, level));
|
|
78
|
+
// 根据标题级别设置block_type和对应的属性名
|
|
79
|
+
// 飞书API中,一级标题的block_type为3,二级标题为4,以此类推
|
|
80
|
+
const blockType = 2 + safeLevel; // 一级标题为3,二级标题为4,以此类推
|
|
81
|
+
const headingKey = `heading${safeLevel}`; // heading1, heading2, ...
|
|
82
|
+
// 构建块内容
|
|
83
|
+
const blockContent = {
|
|
84
|
+
block_type: blockType
|
|
85
|
+
};
|
|
86
|
+
// 设置对应级别的标题属性
|
|
87
|
+
blockContent[headingKey] = {
|
|
88
|
+
elements: [
|
|
89
|
+
{
|
|
90
|
+
text_run: {
|
|
91
|
+
content: text,
|
|
92
|
+
text_element_style: {}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
style: {
|
|
97
|
+
align: align,
|
|
98
|
+
folded: false
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return blockContent;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 处理Markdown语法转换
|
|
105
|
+
* @param textContents 文本内容数组
|
|
106
|
+
* @returns 处理后的文本内容数组
|
|
107
|
+
*/
|
|
108
|
+
export function processMarkdownSyntax(textContents) {
|
|
109
|
+
return textContents.map(content => {
|
|
110
|
+
let { text, style = {} } = content;
|
|
111
|
+
// 创建一个新的style对象,避免修改原始对象
|
|
112
|
+
const newStyle = { ...style };
|
|
113
|
+
// 处理粗体 **text**
|
|
114
|
+
if (text.match(/\*\*([^*]+)\*\*/g)) {
|
|
115
|
+
text = text.replace(/\*\*([^*]+)\*\*/g, "$1");
|
|
116
|
+
newStyle.bold = true;
|
|
117
|
+
}
|
|
118
|
+
// 处理斜体 *text*
|
|
119
|
+
if (text.match(/(?<!\*)\*([^*]+)\*(?!\*)/g)) {
|
|
120
|
+
text = text.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, "$1");
|
|
121
|
+
newStyle.italic = true;
|
|
122
|
+
}
|
|
123
|
+
// 处理删除线 ~~text~~
|
|
124
|
+
if (text.match(/~~([^~]+)~~/g)) {
|
|
125
|
+
text = text.replace(/~~([^~]+)~~/g, "$1");
|
|
126
|
+
newStyle.strikethrough = true;
|
|
127
|
+
}
|
|
128
|
+
// 处理行内代码 `code`
|
|
129
|
+
if (text.match(/`([^`]+)`/g)) {
|
|
130
|
+
text = text.replace(/`([^`]+)`/g, "$1");
|
|
131
|
+
newStyle.inline_code = true;
|
|
132
|
+
}
|
|
133
|
+
return { text, style: newStyle };
|
|
134
|
+
});
|
|
135
|
+
}
|