@md-lark-converter/core 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/dist/index.d.mts +177 -0
- package/dist/index.d.ts +177 -0
- package/dist/index.js +1565 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1517 -0
- package/dist/index.mjs.map +1 -0
- package/dist/node.d.mts +7 -0
- package/dist/node.d.ts +7 -0
- package/dist/node.js +101 -0
- package/dist/node.js.map +1 -0
- package/dist/node.mjs +64 -0
- package/dist/node.mjs.map +1 -0
- package/package.json +63 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1565 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
MarkdownToLarkConverter: () => MarkdownToLarkConverter,
|
|
34
|
+
TEST_CASES: () => TEST_CASES,
|
|
35
|
+
generateBlockHtml: () => generateBlockHtml,
|
|
36
|
+
generateBlockId: () => generateBlockId,
|
|
37
|
+
generateHtml: () => generateHtml,
|
|
38
|
+
generatePageId: () => generatePageId,
|
|
39
|
+
generateRecordId: () => generateRecordId,
|
|
40
|
+
larkToMarkdown: () => larkToMarkdown,
|
|
41
|
+
markdownToLark: () => markdownToLark,
|
|
42
|
+
parseMarkdown: () => parseMarkdown,
|
|
43
|
+
readClipboard: () => readClipboard,
|
|
44
|
+
writeToClipboard: () => writeToClipboard
|
|
45
|
+
});
|
|
46
|
+
module.exports = __toCommonJS(src_exports);
|
|
47
|
+
|
|
48
|
+
// src/utils/idGenerator.ts
|
|
49
|
+
var ID_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
50
|
+
function generateBlockId() {
|
|
51
|
+
let id = "";
|
|
52
|
+
for (let i = 0; i < 4; i++) {
|
|
53
|
+
for (let j = 0; j < 4; j++) {
|
|
54
|
+
id += ID_CHARS[Math.floor(Math.random() * ID_CHARS.length)];
|
|
55
|
+
}
|
|
56
|
+
if (i < 3) id += "_";
|
|
57
|
+
}
|
|
58
|
+
return `docx${id}`;
|
|
59
|
+
}
|
|
60
|
+
function generateRecordId() {
|
|
61
|
+
let id = "";
|
|
62
|
+
for (let i = 0; i < 4; i++) {
|
|
63
|
+
for (let j = 0; j < 4; j++) {
|
|
64
|
+
id += ID_CHARS[Math.floor(Math.random() * ID_CHARS.length)];
|
|
65
|
+
}
|
|
66
|
+
if (i < 3) id += "_";
|
|
67
|
+
}
|
|
68
|
+
return `doxcn${id}`;
|
|
69
|
+
}
|
|
70
|
+
function generatePageId() {
|
|
71
|
+
let id = "";
|
|
72
|
+
for (let i = 0; i < 4; i++) {
|
|
73
|
+
for (let j = 0; j < 4; j++) {
|
|
74
|
+
id += ID_CHARS[Math.floor(Math.random() * ID_CHARS.length)];
|
|
75
|
+
}
|
|
76
|
+
if (i < 3) id += "_";
|
|
77
|
+
}
|
|
78
|
+
return `Wqf${id}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/converter/markdownToLark.ts
|
|
82
|
+
var import_unified = require("unified");
|
|
83
|
+
var import_remark_parse = __toESM(require("remark-parse"));
|
|
84
|
+
var import_remark_math = __toESM(require("remark-math"));
|
|
85
|
+
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
86
|
+
var import_unist_util_visit = require("unist-util-visit");
|
|
87
|
+
var MarkdownToLarkConverter = class {
|
|
88
|
+
rootId;
|
|
89
|
+
authorId;
|
|
90
|
+
recordMap;
|
|
91
|
+
blockIds;
|
|
92
|
+
recordIds;
|
|
93
|
+
payloadMap;
|
|
94
|
+
apoolNextNum;
|
|
95
|
+
apoolNumToAttrib;
|
|
96
|
+
constructor() {
|
|
97
|
+
this.rootId = null;
|
|
98
|
+
this.authorId = "7092639913849389057";
|
|
99
|
+
this.recordMap = {};
|
|
100
|
+
this.blockIds = [];
|
|
101
|
+
this.recordIds = [];
|
|
102
|
+
this.payloadMap = {};
|
|
103
|
+
this.apoolNextNum = 0;
|
|
104
|
+
this.apoolNumToAttrib = {};
|
|
105
|
+
}
|
|
106
|
+
async convert(markdown) {
|
|
107
|
+
this.rootId = generatePageId();
|
|
108
|
+
this.recordMap = {};
|
|
109
|
+
this.blockIds = [];
|
|
110
|
+
this.recordIds = [];
|
|
111
|
+
this.payloadMap = {};
|
|
112
|
+
this.apoolNextNum = 0;
|
|
113
|
+
this.apoolNumToAttrib = {};
|
|
114
|
+
const normalizedMarkdown = this.normalizeMathBlocks(markdown);
|
|
115
|
+
const tree = await (0, import_unified.unified)().use(import_remark_parse.default).use(import_remark_gfm.default).use(import_remark_math.default).parse(normalizedMarkdown);
|
|
116
|
+
this.createPageBlock(this.rootId);
|
|
117
|
+
this.convertTree(tree);
|
|
118
|
+
return this.buildClipboardData();
|
|
119
|
+
}
|
|
120
|
+
normalizeMathBlocks(markdown) {
|
|
121
|
+
return markdown.replace(/\$\$([^\n]+?)\$\$/g, (_, content) => {
|
|
122
|
+
return `$$
|
|
123
|
+
${content.trim()}
|
|
124
|
+
$$`;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
createPageBlock(pageId) {
|
|
128
|
+
this.recordMap[pageId] = {
|
|
129
|
+
id: pageId,
|
|
130
|
+
snapshot: {
|
|
131
|
+
type: "page",
|
|
132
|
+
parent_id: "",
|
|
133
|
+
comments: null,
|
|
134
|
+
revisions: null,
|
|
135
|
+
locked: false,
|
|
136
|
+
hidden: false,
|
|
137
|
+
author: this.authorId,
|
|
138
|
+
children: [],
|
|
139
|
+
text: this.createTextData(""),
|
|
140
|
+
align: "",
|
|
141
|
+
page_style: {},
|
|
142
|
+
title: {
|
|
143
|
+
apool: { nextNum: 0, numToAttrib: {} },
|
|
144
|
+
initialAttributedTexts: {
|
|
145
|
+
attribs: {},
|
|
146
|
+
text: { "0": "\u65E0\u6807\u9898" }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
convertTree(tree) {
|
|
153
|
+
const topLevelRecordIds = [];
|
|
154
|
+
(0, import_unist_util_visit.visit)(tree, (node, index, parent) => {
|
|
155
|
+
if (parent?.type === "listItem") {
|
|
156
|
+
return import_unist_util_visit.SKIP;
|
|
157
|
+
}
|
|
158
|
+
if (node.type === "heading") {
|
|
159
|
+
const recordId = generateRecordId();
|
|
160
|
+
this.recordMap[recordId] = this.createHeadingBlock(recordId, node);
|
|
161
|
+
this.recordIds.push(recordId);
|
|
162
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
163
|
+
topLevelRecordIds.push(recordId);
|
|
164
|
+
} else if (node.type === "paragraph") {
|
|
165
|
+
const recordId = generateRecordId();
|
|
166
|
+
this.recordMap[recordId] = this.createTextBlock(recordId, node);
|
|
167
|
+
this.recordIds.push(recordId);
|
|
168
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
169
|
+
topLevelRecordIds.push(recordId);
|
|
170
|
+
} else if (node.type === "blockquote") {
|
|
171
|
+
const recordId = generateRecordId();
|
|
172
|
+
this.recordMap[recordId] = this.createQuoteBlock(recordId, node);
|
|
173
|
+
this.recordIds.push(recordId);
|
|
174
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
175
|
+
topLevelRecordIds.push(recordId);
|
|
176
|
+
return import_unist_util_visit.SKIP;
|
|
177
|
+
} else if (node.type === "code") {
|
|
178
|
+
const recordId = generateRecordId();
|
|
179
|
+
const codeNode = node;
|
|
180
|
+
if (codeNode.lang && codeNode.lang.toLowerCase() === "mermaid") {
|
|
181
|
+
this.recordMap[recordId] = this.createMermaidBlock(recordId, codeNode.value);
|
|
182
|
+
} else {
|
|
183
|
+
this.recordMap[recordId] = this.createCodeBlock(recordId, codeNode.value, codeNode.lang ?? void 0);
|
|
184
|
+
}
|
|
185
|
+
this.recordIds.push(recordId);
|
|
186
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
187
|
+
topLevelRecordIds.push(recordId);
|
|
188
|
+
} else if (node.type === "thematicBreak") {
|
|
189
|
+
const recordId = generateRecordId();
|
|
190
|
+
this.recordMap[recordId] = this.createDividerBlock(recordId);
|
|
191
|
+
this.recordIds.push(recordId);
|
|
192
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
193
|
+
topLevelRecordIds.push(recordId);
|
|
194
|
+
} else if (node.type === "math") {
|
|
195
|
+
const mathNode = node;
|
|
196
|
+
const recordId = generateRecordId();
|
|
197
|
+
const equation = mathNode.value ?? "";
|
|
198
|
+
this.recordMap[recordId] = this.createEquationParagraphBlock(recordId, equation);
|
|
199
|
+
this.recordIds.push(recordId);
|
|
200
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
201
|
+
topLevelRecordIds.push(recordId);
|
|
202
|
+
} else if (node.type === "table") {
|
|
203
|
+
const tableRecordIds = this.convertTable(node);
|
|
204
|
+
topLevelRecordIds.push(tableRecordIds.tableId);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
const processedLists = /* @__PURE__ */ new Set();
|
|
208
|
+
(0, import_unist_util_visit.visit)(tree, "list", (node, index, parent) => {
|
|
209
|
+
if (processedLists.has(node)) {
|
|
210
|
+
return import_unist_util_visit.SKIP;
|
|
211
|
+
}
|
|
212
|
+
processedLists.add(node);
|
|
213
|
+
if (parent?.type === "listItem") {
|
|
214
|
+
return import_unist_util_visit.SKIP;
|
|
215
|
+
}
|
|
216
|
+
const listRecordIds = this.convertList(node);
|
|
217
|
+
topLevelRecordIds.push(...listRecordIds);
|
|
218
|
+
});
|
|
219
|
+
if (this.rootId && this.recordMap[this.rootId]) {
|
|
220
|
+
this.recordMap[this.rootId].snapshot.children = topLevelRecordIds;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
convertList(listNode) {
|
|
224
|
+
const ordered = listNode.ordered || false;
|
|
225
|
+
return this.convertListItems(listNode.children, ordered, null, 0, true);
|
|
226
|
+
}
|
|
227
|
+
convertListItems(items, ordered, parentId = null, level = 0, isTopLevel = false) {
|
|
228
|
+
const childRecordIds = [];
|
|
229
|
+
const topLevelIds = [];
|
|
230
|
+
let index = 1;
|
|
231
|
+
for (const item of items) {
|
|
232
|
+
const recordId = generateRecordId();
|
|
233
|
+
const blockId = this.blockIds.length + 1;
|
|
234
|
+
let blockType = ordered ? "ordered" : "bullet";
|
|
235
|
+
const isTaskItem = item.checked !== void 0 && item.checked !== null;
|
|
236
|
+
if (isTaskItem) {
|
|
237
|
+
blockType = "todo";
|
|
238
|
+
}
|
|
239
|
+
const listContent = item.children;
|
|
240
|
+
const segments = listContent.length > 0 && listContent[0].type === "paragraph" ? this.parseInlineContent(listContent[0].children) : this.parseInlineContent(listContent);
|
|
241
|
+
if (isTopLevel && level === 0) {
|
|
242
|
+
this.recordIds.push(recordId);
|
|
243
|
+
}
|
|
244
|
+
const snapshot = {
|
|
245
|
+
type: blockType,
|
|
246
|
+
parent_id: parentId || this.rootId,
|
|
247
|
+
comments: [],
|
|
248
|
+
revisions: [],
|
|
249
|
+
locked: false,
|
|
250
|
+
hidden: false,
|
|
251
|
+
author: this.authorId,
|
|
252
|
+
children: [],
|
|
253
|
+
text: ordered ? this.createListItemTextData(segments) : this.createTextData(segments),
|
|
254
|
+
align: "",
|
|
255
|
+
folded: false
|
|
256
|
+
};
|
|
257
|
+
if (isTaskItem) {
|
|
258
|
+
snapshot.done = item.checked || false;
|
|
259
|
+
}
|
|
260
|
+
if (ordered) {
|
|
261
|
+
snapshot.level = level + 1;
|
|
262
|
+
snapshot.seq = index === 1 ? "1" : "auto";
|
|
263
|
+
index++;
|
|
264
|
+
} else {
|
|
265
|
+
snapshot.level = level + 1;
|
|
266
|
+
}
|
|
267
|
+
for (const child of item.children) {
|
|
268
|
+
if (child.type === "list") {
|
|
269
|
+
const nestedChildIds = this.convertListItems(
|
|
270
|
+
child.children,
|
|
271
|
+
child.ordered || false,
|
|
272
|
+
recordId,
|
|
273
|
+
level + 1,
|
|
274
|
+
false
|
|
275
|
+
);
|
|
276
|
+
snapshot.children.push(...nestedChildIds);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
this.recordMap[recordId] = {
|
|
280
|
+
id: recordId,
|
|
281
|
+
snapshot
|
|
282
|
+
};
|
|
283
|
+
this.blockIds.push(blockId);
|
|
284
|
+
childRecordIds.push(recordId);
|
|
285
|
+
if (isTopLevel && level === 0) {
|
|
286
|
+
topLevelIds.push(recordId);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return isTopLevel ? topLevelIds : childRecordIds;
|
|
290
|
+
}
|
|
291
|
+
parseInlineContent(children) {
|
|
292
|
+
const segments = [];
|
|
293
|
+
for (const child of children) {
|
|
294
|
+
if (child.type === "text") {
|
|
295
|
+
segments.push({ text: child.value });
|
|
296
|
+
} else if (child.type === "strong") {
|
|
297
|
+
const text = this.extractTextContent(child);
|
|
298
|
+
segments.push({ text, bold: true });
|
|
299
|
+
} else if (child.type === "emphasis") {
|
|
300
|
+
const text = this.extractTextContent(child);
|
|
301
|
+
segments.push({ text, italic: true });
|
|
302
|
+
} else if (child.type === "delete") {
|
|
303
|
+
const text = this.extractTextContent(child);
|
|
304
|
+
segments.push({ text, strikethrough: true });
|
|
305
|
+
} else if (child.type === "inlineCode") {
|
|
306
|
+
segments.push({ text: child.value });
|
|
307
|
+
} else if (child.type === "link") {
|
|
308
|
+
const linkNode = child;
|
|
309
|
+
const text = this.extractTextContent(linkNode);
|
|
310
|
+
segments.push({ text, linkUrl: linkNode.url });
|
|
311
|
+
} else if (child.type === "image") {
|
|
312
|
+
segments.push({ text: " [markdown-to-lark \u6682\u65E0\u6CD5\u652F\u6301\u56FE\u7247\u8F6C\u6362] " });
|
|
313
|
+
} else if (child.type === "inlineMath") {
|
|
314
|
+
const mathNode = child;
|
|
315
|
+
segments.push({ text: "E", equation: mathNode.value ?? "" });
|
|
316
|
+
} else if (child.type === "break") {
|
|
317
|
+
segments.push({ text: "\n" });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return segments;
|
|
321
|
+
}
|
|
322
|
+
extractTextContent(node) {
|
|
323
|
+
let text = "";
|
|
324
|
+
if (node.type === "text") {
|
|
325
|
+
text = node.value;
|
|
326
|
+
} else if (node.children) {
|
|
327
|
+
for (const child of node.children) {
|
|
328
|
+
text += this.extractTextContent(child);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return text;
|
|
332
|
+
}
|
|
333
|
+
createHeadingBlock(recordId, node) {
|
|
334
|
+
const depth = node.depth;
|
|
335
|
+
const segments = this.parseInlineContent(node.children);
|
|
336
|
+
return {
|
|
337
|
+
id: recordId,
|
|
338
|
+
snapshot: {
|
|
339
|
+
type: `heading${depth}`,
|
|
340
|
+
parent_id: this.rootId,
|
|
341
|
+
comments: [],
|
|
342
|
+
revisions: [],
|
|
343
|
+
locked: false,
|
|
344
|
+
hidden: false,
|
|
345
|
+
author: this.authorId,
|
|
346
|
+
children: [],
|
|
347
|
+
text: this.createTextData(segments),
|
|
348
|
+
level: depth,
|
|
349
|
+
folded: false
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
createTextBlock(recordId, node) {
|
|
354
|
+
const segments = this.parseInlineContent(node.children);
|
|
355
|
+
return {
|
|
356
|
+
id: recordId,
|
|
357
|
+
snapshot: {
|
|
358
|
+
type: "text",
|
|
359
|
+
parent_id: this.rootId,
|
|
360
|
+
comments: [],
|
|
361
|
+
revisions: [],
|
|
362
|
+
locked: false,
|
|
363
|
+
hidden: false,
|
|
364
|
+
author: this.authorId,
|
|
365
|
+
children: [],
|
|
366
|
+
text: this.createTextData(segments),
|
|
367
|
+
align: "",
|
|
368
|
+
folded: false
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
createQuoteBlock(recordId, node) {
|
|
373
|
+
const flattenedContent = this.flattenNestedBlockquotes(node.children);
|
|
374
|
+
const segments = this.parseInlineContent(flattenedContent);
|
|
375
|
+
return {
|
|
376
|
+
id: recordId,
|
|
377
|
+
snapshot: {
|
|
378
|
+
type: "quote",
|
|
379
|
+
parent_id: this.rootId,
|
|
380
|
+
comments: [],
|
|
381
|
+
revisions: [],
|
|
382
|
+
locked: false,
|
|
383
|
+
hidden: false,
|
|
384
|
+
author: this.authorId,
|
|
385
|
+
children: [],
|
|
386
|
+
text: this.createTextData(segments),
|
|
387
|
+
folded: false
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
flattenNestedBlockquotes(children) {
|
|
392
|
+
const result = [];
|
|
393
|
+
for (let i = 0; i < children.length; i++) {
|
|
394
|
+
const child = children[i];
|
|
395
|
+
if (child.type === "blockquote") {
|
|
396
|
+
const nestedContent = this.flattenNestedBlockquotes(child.children);
|
|
397
|
+
if (result.length > 0) {
|
|
398
|
+
result.push({ type: "text", value: "\n\n" });
|
|
399
|
+
}
|
|
400
|
+
result.push(...nestedContent);
|
|
401
|
+
} else if (child.type === "paragraph") {
|
|
402
|
+
if (result.length > 0) {
|
|
403
|
+
result.push({ type: "text", value: "\n\n" });
|
|
404
|
+
}
|
|
405
|
+
result.push(...child.children);
|
|
406
|
+
} else {
|
|
407
|
+
result.push(child);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return result;
|
|
411
|
+
}
|
|
412
|
+
createEquationBlock(recordId, equation) {
|
|
413
|
+
const segments = [{ text: "E", equation }];
|
|
414
|
+
return {
|
|
415
|
+
id: recordId,
|
|
416
|
+
snapshot: {
|
|
417
|
+
type: "equation",
|
|
418
|
+
parent_id: this.rootId,
|
|
419
|
+
comments: [],
|
|
420
|
+
revisions: [],
|
|
421
|
+
locked: false,
|
|
422
|
+
hidden: false,
|
|
423
|
+
author: this.authorId,
|
|
424
|
+
children: [],
|
|
425
|
+
elements: [{
|
|
426
|
+
equation: {
|
|
427
|
+
latex: equation
|
|
428
|
+
}
|
|
429
|
+
}],
|
|
430
|
+
text: this.createTextData(segments),
|
|
431
|
+
folded: false
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
createEquationParagraphBlock(recordId, equation) {
|
|
436
|
+
const segments = [{ text: "E", equation: equation + "_display" }];
|
|
437
|
+
return {
|
|
438
|
+
id: recordId,
|
|
439
|
+
snapshot: {
|
|
440
|
+
type: "text",
|
|
441
|
+
parent_id: this.rootId,
|
|
442
|
+
comments: [],
|
|
443
|
+
revisions: [],
|
|
444
|
+
locked: false,
|
|
445
|
+
hidden: false,
|
|
446
|
+
author: this.authorId,
|
|
447
|
+
children: [],
|
|
448
|
+
text: this.createTextData(segments),
|
|
449
|
+
align: "",
|
|
450
|
+
folded: false
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
createCodeBlock(recordId, code, lang) {
|
|
455
|
+
return {
|
|
456
|
+
id: recordId,
|
|
457
|
+
snapshot: {
|
|
458
|
+
type: "code",
|
|
459
|
+
parent_id: this.rootId,
|
|
460
|
+
comments: [],
|
|
461
|
+
revisions: [],
|
|
462
|
+
locked: false,
|
|
463
|
+
hidden: false,
|
|
464
|
+
author: this.authorId,
|
|
465
|
+
children: [],
|
|
466
|
+
language: lang || "plaintext",
|
|
467
|
+
code,
|
|
468
|
+
text: this.createTextData(code),
|
|
469
|
+
is_language_picked: true,
|
|
470
|
+
caption: {
|
|
471
|
+
text: {
|
|
472
|
+
initialAttributedTexts: {
|
|
473
|
+
text: { "0": "\n" },
|
|
474
|
+
attribs: { "0": "|1+1" }
|
|
475
|
+
},
|
|
476
|
+
apool: { numToAttrib: {}, nextNum: 0 }
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
wrap: false,
|
|
480
|
+
folded: false
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
createDividerBlock(recordId) {
|
|
485
|
+
return {
|
|
486
|
+
id: recordId,
|
|
487
|
+
snapshot: {
|
|
488
|
+
type: "divider",
|
|
489
|
+
parent_id: this.rootId,
|
|
490
|
+
comments: [],
|
|
491
|
+
revisions: [],
|
|
492
|
+
locked: false,
|
|
493
|
+
hidden: false,
|
|
494
|
+
author: this.authorId,
|
|
495
|
+
folded: false
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
createMermaidBlock(recordId, code) {
|
|
500
|
+
const blockId = generateBlockId();
|
|
501
|
+
return {
|
|
502
|
+
id: recordId,
|
|
503
|
+
snapshot: {
|
|
504
|
+
type: "isv",
|
|
505
|
+
parent_id: this.rootId,
|
|
506
|
+
comments: null,
|
|
507
|
+
revisions: null,
|
|
508
|
+
locked: false,
|
|
509
|
+
hidden: false,
|
|
510
|
+
author: this.authorId,
|
|
511
|
+
children: [],
|
|
512
|
+
data: {
|
|
513
|
+
data: code,
|
|
514
|
+
theme: "default",
|
|
515
|
+
view: "codeChart"
|
|
516
|
+
},
|
|
517
|
+
app_block_id: "",
|
|
518
|
+
block_type_id: "blk_631fefbbae02400430b8f9f4",
|
|
519
|
+
manifest: {
|
|
520
|
+
view_type: "block_h5",
|
|
521
|
+
app_version: "0.0.112"
|
|
522
|
+
},
|
|
523
|
+
comment_details: {},
|
|
524
|
+
interaction_data_token: this.generateRandomId()
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
createTextData(segments) {
|
|
529
|
+
if (typeof segments === "string") {
|
|
530
|
+
segments = [{ text: segments }];
|
|
531
|
+
}
|
|
532
|
+
if (!segments || segments.length === 0) {
|
|
533
|
+
return {
|
|
534
|
+
apool: { nextNum: 0, numToAttrib: {} },
|
|
535
|
+
initialAttributedTexts: {
|
|
536
|
+
attribs: "",
|
|
537
|
+
text: { "0": "" },
|
|
538
|
+
rows: {},
|
|
539
|
+
cols: {}
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
const apoolNumToAttrib = {
|
|
544
|
+
"0": ["author", this.authorId]
|
|
545
|
+
};
|
|
546
|
+
const attribToNum = {
|
|
547
|
+
[`author,${this.authorId}`]: 0
|
|
548
|
+
};
|
|
549
|
+
let apoolNextNum = 1;
|
|
550
|
+
const attribParts = [];
|
|
551
|
+
const textParts = [];
|
|
552
|
+
for (const segment of segments) {
|
|
553
|
+
const text = segment.text || "";
|
|
554
|
+
const length = text.length;
|
|
555
|
+
if (length === 0) continue;
|
|
556
|
+
textParts.push(text);
|
|
557
|
+
const activeAttrs = ["0"];
|
|
558
|
+
if (segment.linkUrl) {
|
|
559
|
+
const linkAttrNum = apoolNextNum.toString();
|
|
560
|
+
apoolNextNum++;
|
|
561
|
+
const encodedUrl = encodeURIComponent(segment.linkUrl);
|
|
562
|
+
apoolNumToAttrib[linkAttrNum] = ["link", encodedUrl];
|
|
563
|
+
attribToNum[`link,${encodedUrl}`] = parseInt(linkAttrNum);
|
|
564
|
+
activeAttrs.push(linkAttrNum);
|
|
565
|
+
}
|
|
566
|
+
if (segment.bold) {
|
|
567
|
+
const boldAttrKey = "bold,true";
|
|
568
|
+
let boldAttrNum = attribToNum[boldAttrKey];
|
|
569
|
+
if (boldAttrNum === void 0) {
|
|
570
|
+
boldAttrNum = apoolNextNum;
|
|
571
|
+
apoolNextNum++;
|
|
572
|
+
apoolNumToAttrib[boldAttrNum.toString()] = ["bold", "true"];
|
|
573
|
+
attribToNum[boldAttrKey] = boldAttrNum;
|
|
574
|
+
}
|
|
575
|
+
activeAttrs.push(boldAttrNum.toString());
|
|
576
|
+
}
|
|
577
|
+
if (segment.italic) {
|
|
578
|
+
const italicAttrKey = "italic,true";
|
|
579
|
+
let italicAttrNum = attribToNum[italicAttrKey];
|
|
580
|
+
if (italicAttrNum === void 0) {
|
|
581
|
+
italicAttrNum = apoolNextNum;
|
|
582
|
+
apoolNextNum++;
|
|
583
|
+
apoolNumToAttrib[italicAttrNum.toString()] = ["italic", "true"];
|
|
584
|
+
attribToNum[italicAttrKey] = italicAttrNum;
|
|
585
|
+
}
|
|
586
|
+
activeAttrs.push(italicAttrNum.toString());
|
|
587
|
+
}
|
|
588
|
+
if (segment.underline) {
|
|
589
|
+
const underlineAttrKey = "underline,true";
|
|
590
|
+
let underlineAttrNum = attribToNum[underlineAttrKey];
|
|
591
|
+
if (underlineAttrNum === void 0) {
|
|
592
|
+
underlineAttrNum = apoolNextNum;
|
|
593
|
+
apoolNextNum++;
|
|
594
|
+
apoolNumToAttrib[underlineAttrNum.toString()] = ["underline", "true"];
|
|
595
|
+
attribToNum[underlineAttrKey] = underlineAttrNum;
|
|
596
|
+
}
|
|
597
|
+
activeAttrs.push(underlineAttrNum.toString());
|
|
598
|
+
}
|
|
599
|
+
if (segment.strikethrough) {
|
|
600
|
+
const strikeAttrKey = "strikethrough,true";
|
|
601
|
+
let strikeAttrNum = attribToNum[strikeAttrKey];
|
|
602
|
+
if (strikeAttrNum === void 0) {
|
|
603
|
+
strikeAttrNum = apoolNextNum;
|
|
604
|
+
apoolNextNum++;
|
|
605
|
+
apoolNumToAttrib[strikeAttrNum.toString()] = ["strikethrough", "true"];
|
|
606
|
+
attribToNum[strikeAttrKey] = strikeAttrNum;
|
|
607
|
+
}
|
|
608
|
+
activeAttrs.push(strikeAttrNum.toString());
|
|
609
|
+
}
|
|
610
|
+
if (segment.equation) {
|
|
611
|
+
const eqAttrNum = apoolNextNum.toString();
|
|
612
|
+
apoolNextNum++;
|
|
613
|
+
apoolNumToAttrib[eqAttrNum] = ["equation", segment.equation];
|
|
614
|
+
attribToNum[`equation,${segment.equation}`] = parseInt(eqAttrNum);
|
|
615
|
+
activeAttrs.push(eqAttrNum);
|
|
616
|
+
}
|
|
617
|
+
const attrsPart = activeAttrs.join("*");
|
|
618
|
+
attribParts.push(`*${attrsPart}+${length}`);
|
|
619
|
+
}
|
|
620
|
+
const fullText = textParts.join("");
|
|
621
|
+
const attribsStr = attribParts.join("");
|
|
622
|
+
return {
|
|
623
|
+
apool: {
|
|
624
|
+
nextNum: apoolNextNum,
|
|
625
|
+
numToAttrib: apoolNumToAttrib,
|
|
626
|
+
attribToNum
|
|
627
|
+
},
|
|
628
|
+
initialAttributedTexts: {
|
|
629
|
+
attribs: { "0": attribsStr },
|
|
630
|
+
text: { "0": fullText },
|
|
631
|
+
rows: {},
|
|
632
|
+
cols: {}
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
createListItemTextData(segments) {
|
|
637
|
+
if (!segments || segments.length === 0) {
|
|
638
|
+
return {
|
|
639
|
+
apool: { nextNum: 0, numToAttrib: {} },
|
|
640
|
+
initialAttributedTexts: {
|
|
641
|
+
attribs: "",
|
|
642
|
+
text: { "0": "" },
|
|
643
|
+
rows: {},
|
|
644
|
+
cols: {}
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
const apoolNumToAttrib = {
|
|
649
|
+
"0": ["author", this.authorId]
|
|
650
|
+
};
|
|
651
|
+
const attribToNum = {
|
|
652
|
+
[`author,${this.authorId}`]: 0
|
|
653
|
+
};
|
|
654
|
+
let apoolNextNum = 1;
|
|
655
|
+
const attribParts = [];
|
|
656
|
+
const textParts = [];
|
|
657
|
+
for (const segment of segments) {
|
|
658
|
+
const text = segment.text || "";
|
|
659
|
+
const length = text.length;
|
|
660
|
+
if (length === 0) continue;
|
|
661
|
+
textParts.push(text);
|
|
662
|
+
const activeAttrs = ["0"];
|
|
663
|
+
if (segment.linkUrl) {
|
|
664
|
+
const linkAttrNum = apoolNextNum.toString();
|
|
665
|
+
apoolNextNum++;
|
|
666
|
+
const encodedUrl = encodeURIComponent(segment.linkUrl);
|
|
667
|
+
apoolNumToAttrib[linkAttrNum] = ["link", encodedUrl];
|
|
668
|
+
attribToNum[`link,${encodedUrl}`] = parseInt(linkAttrNum);
|
|
669
|
+
activeAttrs.push(linkAttrNum);
|
|
670
|
+
}
|
|
671
|
+
if (segment.bold) {
|
|
672
|
+
const boldAttrKey = "bold,true";
|
|
673
|
+
let boldAttrNum = attribToNum[boldAttrKey];
|
|
674
|
+
if (boldAttrNum === void 0) {
|
|
675
|
+
boldAttrNum = apoolNextNum;
|
|
676
|
+
apoolNextNum++;
|
|
677
|
+
apoolNumToAttrib[boldAttrNum.toString()] = ["bold", "true"];
|
|
678
|
+
attribToNum[boldAttrKey] = boldAttrNum;
|
|
679
|
+
}
|
|
680
|
+
activeAttrs.push(boldAttrNum.toString());
|
|
681
|
+
}
|
|
682
|
+
if (segment.italic) {
|
|
683
|
+
const italicAttrKey = "italic,true";
|
|
684
|
+
let italicAttrNum = attribToNum[italicAttrKey];
|
|
685
|
+
if (italicAttrNum === void 0) {
|
|
686
|
+
italicAttrNum = apoolNextNum;
|
|
687
|
+
apoolNextNum++;
|
|
688
|
+
apoolNumToAttrib[italicAttrNum.toString()] = ["italic", "true"];
|
|
689
|
+
attribToNum[italicAttrKey] = italicAttrNum;
|
|
690
|
+
}
|
|
691
|
+
activeAttrs.push(italicAttrNum.toString());
|
|
692
|
+
}
|
|
693
|
+
if (segment.underline) {
|
|
694
|
+
const underlineAttrKey = "underline,true";
|
|
695
|
+
let underlineAttrNum = attribToNum[underlineAttrKey];
|
|
696
|
+
if (underlineAttrNum === void 0) {
|
|
697
|
+
underlineAttrNum = apoolNextNum;
|
|
698
|
+
apoolNextNum++;
|
|
699
|
+
apoolNumToAttrib[underlineAttrNum.toString()] = ["underline", "true"];
|
|
700
|
+
attribToNum[underlineAttrKey] = underlineAttrNum;
|
|
701
|
+
}
|
|
702
|
+
activeAttrs.push(underlineAttrNum.toString());
|
|
703
|
+
}
|
|
704
|
+
if (segment.strikethrough) {
|
|
705
|
+
const strikeAttrKey = "strikethrough,true";
|
|
706
|
+
let strikeAttrNum = attribToNum[strikeAttrKey];
|
|
707
|
+
if (strikeAttrNum === void 0) {
|
|
708
|
+
strikeAttrNum = apoolNextNum;
|
|
709
|
+
apoolNextNum++;
|
|
710
|
+
apoolNumToAttrib[strikeAttrNum.toString()] = ["strikethrough", "true"];
|
|
711
|
+
attribToNum[strikeAttrKey] = strikeAttrNum;
|
|
712
|
+
}
|
|
713
|
+
activeAttrs.push(strikeAttrNum.toString());
|
|
714
|
+
}
|
|
715
|
+
if (segment.equation) {
|
|
716
|
+
const eqAttrNum = apoolNextNum.toString();
|
|
717
|
+
apoolNextNum++;
|
|
718
|
+
apoolNumToAttrib[eqAttrNum] = ["equation", segment.equation];
|
|
719
|
+
attribToNum[`equation,${segment.equation}`] = parseInt(eqAttrNum);
|
|
720
|
+
activeAttrs.push(eqAttrNum);
|
|
721
|
+
}
|
|
722
|
+
const attrsPart = activeAttrs.join("*");
|
|
723
|
+
attribParts.push(`*${attrsPart}+${length}`);
|
|
724
|
+
}
|
|
725
|
+
const fullText = textParts.join("");
|
|
726
|
+
const attribsStr = attribParts.join("");
|
|
727
|
+
return {
|
|
728
|
+
apool: {
|
|
729
|
+
nextNum: apoolNextNum,
|
|
730
|
+
numToAttrib: apoolNumToAttrib,
|
|
731
|
+
attribToNum
|
|
732
|
+
},
|
|
733
|
+
initialAttributedTexts: {
|
|
734
|
+
attribs: { "0": attribsStr },
|
|
735
|
+
text: { "0": fullText },
|
|
736
|
+
rows: {},
|
|
737
|
+
cols: {}
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
buildClipboardData() {
|
|
742
|
+
const data = {
|
|
743
|
+
isCut: false,
|
|
744
|
+
rootId: this.rootId,
|
|
745
|
+
parentId: this.rootId,
|
|
746
|
+
blockIds: this.blockIds,
|
|
747
|
+
recordIds: this.recordIds,
|
|
748
|
+
recordMap: this.recordMap,
|
|
749
|
+
payloadMap: {},
|
|
750
|
+
selection: [],
|
|
751
|
+
extra: {
|
|
752
|
+
channel: "saas",
|
|
753
|
+
pasteRandomId: this.generateRandomId(),
|
|
754
|
+
mention_page_title: {},
|
|
755
|
+
external_mention_url: {},
|
|
756
|
+
isEqualBlockSelection: true
|
|
757
|
+
},
|
|
758
|
+
isKeepQuoteContainer: false,
|
|
759
|
+
pasteFlag: this.generateRandomId()
|
|
760
|
+
};
|
|
761
|
+
return data;
|
|
762
|
+
}
|
|
763
|
+
generateRandomId() {
|
|
764
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
765
|
+
const r = Math.random() * 16 | 0;
|
|
766
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
767
|
+
return v.toString(16);
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
convertTable(tableNode) {
|
|
771
|
+
const tableRecordId = generateRecordId();
|
|
772
|
+
const children = tableNode.children;
|
|
773
|
+
if (!children || children.length === 0) {
|
|
774
|
+
return { tableId: tableRecordId };
|
|
775
|
+
}
|
|
776
|
+
const alignments = tableNode.align || [];
|
|
777
|
+
const rows = children;
|
|
778
|
+
const columnIds = [];
|
|
779
|
+
const rowIds = [];
|
|
780
|
+
const columnSet = {};
|
|
781
|
+
const cellSet = {};
|
|
782
|
+
const tableCellIds = [];
|
|
783
|
+
const numCols = alignments.length || rows[0]?.children?.length || 0;
|
|
784
|
+
const numRows = rows.length;
|
|
785
|
+
for (let i = 0; i < numCols; i++) {
|
|
786
|
+
const colId = `col${this.generateRandomId().replace(/-/g, "")}`;
|
|
787
|
+
columnIds.push(colId);
|
|
788
|
+
columnSet[colId] = { column_width: 200 };
|
|
789
|
+
}
|
|
790
|
+
for (let i = 0; i < numRows; i++) {
|
|
791
|
+
const rowId = `row${this.generateRandomId().replace(/-/g, "")}`;
|
|
792
|
+
rowIds.push(rowId);
|
|
793
|
+
}
|
|
794
|
+
const processRow = (rowIndex, rowCells) => {
|
|
795
|
+
const rowId = rowIds[rowIndex];
|
|
796
|
+
for (let colIndex = 0; colIndex < rowCells.length && colIndex < numCols; colIndex++) {
|
|
797
|
+
const colId = columnIds[colIndex];
|
|
798
|
+
const cellNode = rowCells[colIndex];
|
|
799
|
+
const cellRecordId = generateRecordId();
|
|
800
|
+
const cellTextSegments = this.parseInlineContent(cellNode.children || []);
|
|
801
|
+
const align = alignments[colIndex] || "left";
|
|
802
|
+
this.recordMap[cellRecordId] = {
|
|
803
|
+
id: cellRecordId,
|
|
804
|
+
snapshot: {
|
|
805
|
+
type: "table_cell",
|
|
806
|
+
parent_id: tableRecordId,
|
|
807
|
+
comments: [],
|
|
808
|
+
revisions: [],
|
|
809
|
+
locked: false,
|
|
810
|
+
hidden: false,
|
|
811
|
+
author: this.authorId,
|
|
812
|
+
children: [],
|
|
813
|
+
text: this.createTextData(cellTextSegments)
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
const textRecordId = generateRecordId();
|
|
817
|
+
this.recordMap[textRecordId] = {
|
|
818
|
+
id: textRecordId,
|
|
819
|
+
snapshot: {
|
|
820
|
+
type: "text",
|
|
821
|
+
parent_id: cellRecordId,
|
|
822
|
+
comments: [],
|
|
823
|
+
revisions: [],
|
|
824
|
+
locked: false,
|
|
825
|
+
hidden: false,
|
|
826
|
+
author: this.authorId,
|
|
827
|
+
children: [],
|
|
828
|
+
text: this.createTextData(cellTextSegments),
|
|
829
|
+
folded: false,
|
|
830
|
+
align
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
this.recordMap[cellRecordId].snapshot.children.push(textRecordId);
|
|
834
|
+
const cellKey = `${rowId}${colId}`;
|
|
835
|
+
cellSet[cellKey] = {
|
|
836
|
+
block_id: cellRecordId,
|
|
837
|
+
merge_info: { row_span: 1, col_span: 1 }
|
|
838
|
+
};
|
|
839
|
+
tableCellIds.push(cellRecordId);
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
for (let i = 0; i < rows.length; i++) {
|
|
843
|
+
processRow(i, rows[i].children);
|
|
844
|
+
}
|
|
845
|
+
this.recordMap[tableRecordId] = {
|
|
846
|
+
id: tableRecordId,
|
|
847
|
+
snapshot: {
|
|
848
|
+
type: "table",
|
|
849
|
+
parent_id: this.rootId,
|
|
850
|
+
comments: [],
|
|
851
|
+
revisions: [],
|
|
852
|
+
locked: false,
|
|
853
|
+
hidden: false,
|
|
854
|
+
author: this.authorId,
|
|
855
|
+
children: tableCellIds,
|
|
856
|
+
columns_id: columnIds,
|
|
857
|
+
rows_id: rowIds,
|
|
858
|
+
column_set: columnSet,
|
|
859
|
+
cell_set: cellSet
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
this.recordIds.push(tableRecordId);
|
|
863
|
+
this.blockIds.push(this.blockIds.length + 1);
|
|
864
|
+
return { tableId: tableRecordId };
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
// src/parser/markdownParser.ts
|
|
869
|
+
var import_marked = require("marked");
|
|
870
|
+
function parseMarkdown(markdown) {
|
|
871
|
+
const tokens = import_marked.marked.lexer(markdown);
|
|
872
|
+
return convertTokens(tokens);
|
|
873
|
+
}
|
|
874
|
+
function convertTokens(tokens, parentType = null) {
|
|
875
|
+
const blocks = [];
|
|
876
|
+
for (const token of tokens) {
|
|
877
|
+
const block = convertToken(token, parentType);
|
|
878
|
+
if (Array.isArray(block)) {
|
|
879
|
+
blocks.push(...block);
|
|
880
|
+
} else if (block) {
|
|
881
|
+
blocks.push(block);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
return blocks;
|
|
885
|
+
}
|
|
886
|
+
function convertToken(token, parentType) {
|
|
887
|
+
const { type, raw, text, depth, items, code, lang } = token;
|
|
888
|
+
switch (type) {
|
|
889
|
+
case "heading":
|
|
890
|
+
return {
|
|
891
|
+
type: `heading${depth}`,
|
|
892
|
+
text: parseInlineText(text)
|
|
893
|
+
};
|
|
894
|
+
case "paragraph":
|
|
895
|
+
return {
|
|
896
|
+
type: "text",
|
|
897
|
+
text: parseInlineText(text)
|
|
898
|
+
};
|
|
899
|
+
case "blockquote":
|
|
900
|
+
return {
|
|
901
|
+
type: "quote",
|
|
902
|
+
text: parseInlineText(text)
|
|
903
|
+
};
|
|
904
|
+
case "list":
|
|
905
|
+
return {
|
|
906
|
+
type: "list",
|
|
907
|
+
ordered: token.ordered,
|
|
908
|
+
items: items.map((item) => ({
|
|
909
|
+
text: parseInlineText(item.text),
|
|
910
|
+
task: item.checked !== void 0,
|
|
911
|
+
checked: item.checked
|
|
912
|
+
}))
|
|
913
|
+
};
|
|
914
|
+
case "code":
|
|
915
|
+
return {
|
|
916
|
+
type: "code",
|
|
917
|
+
language: lang || "plaintext",
|
|
918
|
+
text: code
|
|
919
|
+
};
|
|
920
|
+
case "hr":
|
|
921
|
+
return {
|
|
922
|
+
type: "divider"
|
|
923
|
+
};
|
|
924
|
+
case "space":
|
|
925
|
+
return null;
|
|
926
|
+
default:
|
|
927
|
+
return null;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function parseInlineText(text) {
|
|
931
|
+
if (!text) return "";
|
|
932
|
+
const inlineTokens = import_marked.marked.lexerInline(text);
|
|
933
|
+
return convertInlineTokens(inlineTokens);
|
|
934
|
+
}
|
|
935
|
+
function convertInlineTokens(tokens) {
|
|
936
|
+
let result = "";
|
|
937
|
+
for (const token of tokens) {
|
|
938
|
+
switch (token.type) {
|
|
939
|
+
case "text":
|
|
940
|
+
result += token.raw;
|
|
941
|
+
break;
|
|
942
|
+
case "strong":
|
|
943
|
+
result += `**${token.text}**`;
|
|
944
|
+
break;
|
|
945
|
+
case "em":
|
|
946
|
+
result += `*${token.text}*`;
|
|
947
|
+
break;
|
|
948
|
+
case "del":
|
|
949
|
+
result += `~~${token.text}~~`;
|
|
950
|
+
break;
|
|
951
|
+
case "codespan":
|
|
952
|
+
result += `\`${token.text}\``;
|
|
953
|
+
break;
|
|
954
|
+
case "link":
|
|
955
|
+
result += `[$(token as any).text}](${token.href})`;
|
|
956
|
+
break;
|
|
957
|
+
case "image":
|
|
958
|
+
result += ``;
|
|
959
|
+
break;
|
|
960
|
+
default:
|
|
961
|
+
result += token.raw || "";
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
return result;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// src/clipboard/browserClipboard.ts
|
|
968
|
+
async function writeToClipboard(html, jsonData) {
|
|
969
|
+
try {
|
|
970
|
+
const plainText = extractPlainTextFromData(jsonData);
|
|
971
|
+
const clipboardItem = new ClipboardItem({
|
|
972
|
+
"text/html": new Blob([html], { type: "text/html" }),
|
|
973
|
+
"text/plain": new Blob([plainText], { type: "text/plain" })
|
|
974
|
+
});
|
|
975
|
+
await navigator.clipboard.write([clipboardItem]);
|
|
976
|
+
return true;
|
|
977
|
+
} catch (error) {
|
|
978
|
+
console.error("Failed to write to clipboard:", error);
|
|
979
|
+
throw new Error(`\u5199\u5165\u526A\u8D34\u677F\u5931\u8D25: ${error.message}`);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
function extractPlainTextFromData(data) {
|
|
983
|
+
let text = "";
|
|
984
|
+
for (const recordId of data.recordIds) {
|
|
985
|
+
const record = data.recordMap[recordId];
|
|
986
|
+
if (!record) continue;
|
|
987
|
+
const snapshot = record.snapshot;
|
|
988
|
+
const type = snapshot.type;
|
|
989
|
+
if (type === "isv") {
|
|
990
|
+
text += "[Mermaid \u56FE\u8868]\n";
|
|
991
|
+
} else if (type === "code") {
|
|
992
|
+
text += `\`\`\`${snapshot.language || "text"}
|
|
993
|
+
${snapshot.code}
|
|
994
|
+
\`\`\`
|
|
995
|
+
`;
|
|
996
|
+
} else if (type === "divider") {
|
|
997
|
+
text += "---\n";
|
|
998
|
+
} else if (type.startsWith("heading")) {
|
|
999
|
+
const level = parseInt(type.replace("heading", ""));
|
|
1000
|
+
text += `${"#".repeat(level)} ${getTextContent(snapshot.text)}
|
|
1001
|
+
|
|
1002
|
+
`;
|
|
1003
|
+
} else if (type === "text" || type === "quote") {
|
|
1004
|
+
text += `${getTextContent(snapshot.text)}
|
|
1005
|
+
|
|
1006
|
+
`;
|
|
1007
|
+
} else if (type === "bullet" || type === "ordered" || type === "todo") {
|
|
1008
|
+
const marker = type === "bullet" ? "-" : type === "ordered" ? "1." : snapshot.checked ? "- [x]" : "- [ ]";
|
|
1009
|
+
text += `${marker} ${getTextContent(snapshot.text)}
|
|
1010
|
+
`;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
return text.trim();
|
|
1014
|
+
}
|
|
1015
|
+
function getTextContent(textData) {
|
|
1016
|
+
if (!textData || !textData.initialAttributedTexts) {
|
|
1017
|
+
return "";
|
|
1018
|
+
}
|
|
1019
|
+
const texts = textData.initialAttributedTexts.text;
|
|
1020
|
+
return Object.values(texts).join("");
|
|
1021
|
+
}
|
|
1022
|
+
async function readClipboard() {
|
|
1023
|
+
try {
|
|
1024
|
+
const clipboardItems = await navigator.clipboard.read();
|
|
1025
|
+
const results = {};
|
|
1026
|
+
for (const item of clipboardItems) {
|
|
1027
|
+
for (const type of item.types) {
|
|
1028
|
+
const blob = await item.getType(type);
|
|
1029
|
+
if (type.startsWith("text/")) {
|
|
1030
|
+
const text = await blob.text();
|
|
1031
|
+
results[type] = text;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
return results;
|
|
1036
|
+
} catch (error) {
|
|
1037
|
+
console.error("Failed to read clipboard:", error);
|
|
1038
|
+
throw new Error(`\u8BFB\u53D6\u526A\u8D34\u677F\u5931\u8D25: ${error.message}`);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// src/htmlGenerator.ts
|
|
1043
|
+
function generateHtml(data) {
|
|
1044
|
+
if (!data || !data.recordIds || !data.recordMap) {
|
|
1045
|
+
console.error("Invalid data structure:", data);
|
|
1046
|
+
return "";
|
|
1047
|
+
}
|
|
1048
|
+
const jsonStr = JSON.stringify(data);
|
|
1049
|
+
const encodedJson = jsonStr.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
1050
|
+
let html = `<meta charset="utf-8"><div data-page-id="${data.rootId}" data-lark-html-role="root" data-docx-has-block-data="true">`;
|
|
1051
|
+
for (const recordId of data.recordIds) {
|
|
1052
|
+
const record = data.recordMap[recordId];
|
|
1053
|
+
if (!record) continue;
|
|
1054
|
+
const snapshot = record.snapshot;
|
|
1055
|
+
const blockHtml = generateBlockHtml(snapshot, recordId);
|
|
1056
|
+
html += blockHtml;
|
|
1057
|
+
}
|
|
1058
|
+
html += `</div><span data-lark-record-data="${encodedJson}" data-lark-record-format="docx/record" class="lark-record-clipboard"></span>`;
|
|
1059
|
+
return html;
|
|
1060
|
+
}
|
|
1061
|
+
function generateBlockHtml(snapshot, recordId) {
|
|
1062
|
+
const { type, text, code, language, level, data, checked, children } = snapshot;
|
|
1063
|
+
switch (type) {
|
|
1064
|
+
case "page":
|
|
1065
|
+
return "";
|
|
1066
|
+
case "isv":
|
|
1067
|
+
const mermaidCode = data && data.data ? data.data : "";
|
|
1068
|
+
return `<div class="ace-line old-record-id-${recordId}">
|
|
1069
|
+
<span class="block-paste-placeholder">${mermaidCode || "\u6682\u65F6\u65E0\u6CD5\u5728\u98DE\u4E66\u6587\u6863\u5916\u5C55\u793A\u6B64\u5185\u5BB9"}</span>
|
|
1070
|
+
</div>`;
|
|
1071
|
+
case "heading1":
|
|
1072
|
+
const text1 = getTextContent2(text);
|
|
1073
|
+
return `<h1 class="heading-1 ace-line old-record-id-${recordId}">${escapeHtml(text1)}</h1>`;
|
|
1074
|
+
case "heading2":
|
|
1075
|
+
const text2 = getTextContent2(text);
|
|
1076
|
+
return `<h2 class="heading-2 ace-line old-record-id-${recordId}">${escapeHtml(text2)}</h2>`;
|
|
1077
|
+
case "heading3":
|
|
1078
|
+
const text3 = getTextContent2(text);
|
|
1079
|
+
return `<h3 class="heading-3 ace-line old-record-id-${recordId}">${escapeHtml(text3)}</h3>`;
|
|
1080
|
+
case "heading4":
|
|
1081
|
+
const text4 = getTextContent2(text);
|
|
1082
|
+
return `<h4 class="heading-4 ace-line old-record-id-${recordId}">${escapeHtml(text4)}</h4>`;
|
|
1083
|
+
case "heading5":
|
|
1084
|
+
const text5 = getTextContent2(text);
|
|
1085
|
+
return `<h5 class="heading-5 ace-line old-record-id-${recordId}">${escapeHtml(text5)}</h5>`;
|
|
1086
|
+
case "heading6":
|
|
1087
|
+
const text6 = getTextContent2(text);
|
|
1088
|
+
return `<h6 class="heading-6 ace-line old-record-id-${recordId}">${escapeHtml(text6)}</h6>`;
|
|
1089
|
+
case "text":
|
|
1090
|
+
const textContent = getTextContent2(text);
|
|
1091
|
+
return `<div class="ace-line old-record-id-${recordId}">${escapeHtml(textContent)}</div>`;
|
|
1092
|
+
case "quote":
|
|
1093
|
+
const quoteText = getTextContent2(text);
|
|
1094
|
+
return `<blockquote class="ace-line old-record-id-${recordId}">${escapeHtml(quoteText)}</blockquote>`;
|
|
1095
|
+
case "code":
|
|
1096
|
+
const codeContent = code || getTextContent2(text) || "";
|
|
1097
|
+
const escapedCode = escapeHtml(codeContent);
|
|
1098
|
+
return `<pre style="white-space:pre;" class="ace-line old-record-id-${recordId}"><code class="language-${language || "plaintext"}" data-lark-language="${language || "plaintext"}" data-wrap="false"><div>${escapedCode}</div></code></pre>`;
|
|
1099
|
+
case "divider":
|
|
1100
|
+
return `<div data-type="divider" class="old-record-id-${recordId}"><hr></div>`;
|
|
1101
|
+
case "bullet":
|
|
1102
|
+
const bulletText = getTextContent2(text);
|
|
1103
|
+
return `<ul class="list-bullet1"><li class="ace-line old-record-id-${recordId}" data-list="bullet"><div>${escapeHtml(bulletText)}</div></li></ul>`;
|
|
1104
|
+
case "ordered":
|
|
1105
|
+
const orderedText = getTextContent2(text);
|
|
1106
|
+
return `<ol class="list-number1"><li class="ace-line old-record-id-${recordId}" data-list="number"><div>${escapeHtml(orderedText)}</div></li></ol>`;
|
|
1107
|
+
case "todo":
|
|
1108
|
+
const todoText = getTextContent2(text);
|
|
1109
|
+
const isChecked = snapshot.done || false;
|
|
1110
|
+
const listClass = isChecked ? "list-done1" : "list-check";
|
|
1111
|
+
return `<ul class="${listClass}"><li class="ace-line old-record-id-${recordId}" data-list="${isChecked ? "done" : "check"}"><div>${escapeHtml(todoText)}</div></li></ul>`;
|
|
1112
|
+
case "image":
|
|
1113
|
+
return `<div class="ace-line old-record-id-${recordId}">[markdown-to-lark \u6682\u65E0\u6CD5\u652F\u6301\u56FE\u7247\u8F6C\u6362]</div>`;
|
|
1114
|
+
default:
|
|
1115
|
+
return "";
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
function getTextContent2(textData) {
|
|
1119
|
+
if (!textData || !textData.initialAttributedTexts) {
|
|
1120
|
+
return "";
|
|
1121
|
+
}
|
|
1122
|
+
const texts = textData.initialAttributedTexts.text;
|
|
1123
|
+
if (!texts) return "";
|
|
1124
|
+
return Object.values(texts).join("");
|
|
1125
|
+
}
|
|
1126
|
+
function escapeHtml(text) {
|
|
1127
|
+
if (typeof text !== "string" || !text) return "";
|
|
1128
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// src/index.ts
|
|
1132
|
+
async function markdownToLark(markdown) {
|
|
1133
|
+
const converter = new MarkdownToLarkConverter();
|
|
1134
|
+
return converter.convert(markdown);
|
|
1135
|
+
}
|
|
1136
|
+
function larkToMarkdown(data) {
|
|
1137
|
+
if (!data || !data.recordMap) {
|
|
1138
|
+
return "";
|
|
1139
|
+
}
|
|
1140
|
+
const result = [];
|
|
1141
|
+
let lastType = "";
|
|
1142
|
+
function processRecord(recordId, depth = 0) {
|
|
1143
|
+
const record = data.recordMap[recordId];
|
|
1144
|
+
if (!record || !record.snapshot) return;
|
|
1145
|
+
const snapshot = record.snapshot;
|
|
1146
|
+
if (snapshot.type === "page") {
|
|
1147
|
+
if (snapshot.children && snapshot.children.length > 0) {
|
|
1148
|
+
for (const childId of snapshot.children) {
|
|
1149
|
+
processRecord(childId);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
const isList = ["bullet", "ordered", "todo"].includes(snapshot.type);
|
|
1155
|
+
if (result.length > 0) {
|
|
1156
|
+
if (lastType !== snapshot.type && lastType !== "list" && !isList) {
|
|
1157
|
+
result.push("");
|
|
1158
|
+
} else if (lastType === "text" && snapshot.type === "text") {
|
|
1159
|
+
result.push("");
|
|
1160
|
+
} else if (lastType === "list" && !isList) {
|
|
1161
|
+
result.push("");
|
|
1162
|
+
} else if (!isList && lastType !== "list" && !isList) {
|
|
1163
|
+
result.push("");
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
switch (snapshot.type) {
|
|
1167
|
+
case "heading1":
|
|
1168
|
+
case "heading2":
|
|
1169
|
+
case "heading3":
|
|
1170
|
+
case "heading4":
|
|
1171
|
+
case "heading5":
|
|
1172
|
+
case "heading6": {
|
|
1173
|
+
const level = parseInt(snapshot.type.replace("heading", ""));
|
|
1174
|
+
const headingText = getTextContent3(snapshot.text);
|
|
1175
|
+
result.push(`${"#".repeat(level)} ${headingText}`);
|
|
1176
|
+
break;
|
|
1177
|
+
}
|
|
1178
|
+
case "text": {
|
|
1179
|
+
const textContent = getTextContent3(snapshot.text);
|
|
1180
|
+
if (textContent.trim()) {
|
|
1181
|
+
result.push(textContent);
|
|
1182
|
+
}
|
|
1183
|
+
break;
|
|
1184
|
+
}
|
|
1185
|
+
case "quote": {
|
|
1186
|
+
const quoteText = getTextContent3(snapshot.text);
|
|
1187
|
+
result.push(`> ${quoteText}`);
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
case "bullet": {
|
|
1191
|
+
const bulletText = getTextContent3(snapshot.text);
|
|
1192
|
+
const level = snapshot.level || 1;
|
|
1193
|
+
const indent = " ".repeat(level - 1);
|
|
1194
|
+
result.push(`${indent}- ${bulletText}`);
|
|
1195
|
+
break;
|
|
1196
|
+
}
|
|
1197
|
+
case "ordered": {
|
|
1198
|
+
const orderedText = getTextContent3(snapshot.text);
|
|
1199
|
+
const level = snapshot.level || 1;
|
|
1200
|
+
const indent = " ".repeat(level - 1);
|
|
1201
|
+
result.push(`${indent}1. ${orderedText}`);
|
|
1202
|
+
break;
|
|
1203
|
+
}
|
|
1204
|
+
case "todo": {
|
|
1205
|
+
const todoText = getTextContent3(snapshot.text);
|
|
1206
|
+
const isChecked = snapshot.done || false;
|
|
1207
|
+
const level = snapshot.level || 1;
|
|
1208
|
+
const indent = " ".repeat(level - 1);
|
|
1209
|
+
result.push(`${indent}- [${isChecked ? "x" : " "}] ${todoText}`);
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
case "code": {
|
|
1213
|
+
const language = snapshot.language || "";
|
|
1214
|
+
const code = snapshot.code || getTextContent3(snapshot.text) || "";
|
|
1215
|
+
result.push(`\`\`\`${language}`);
|
|
1216
|
+
result.push(code);
|
|
1217
|
+
result.push(`\`\`\``);
|
|
1218
|
+
break;
|
|
1219
|
+
}
|
|
1220
|
+
case "divider": {
|
|
1221
|
+
result.push("---");
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1224
|
+
case "isv": {
|
|
1225
|
+
const mermaidCode = snapshot.data?.data || "";
|
|
1226
|
+
result.push(`\`\`\`mermaid`);
|
|
1227
|
+
result.push(mermaidCode);
|
|
1228
|
+
result.push(`\`\`\``);
|
|
1229
|
+
break;
|
|
1230
|
+
}
|
|
1231
|
+
case "equation": {
|
|
1232
|
+
result.push(`$$${getTextContent3(snapshot.text)}$$`);
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
case "image": {
|
|
1236
|
+
result.push("[lark-to-markdown \u6682\u65E0\u6CD5\u652F\u6301\u56FE\u7247\u8F6C\u6362]");
|
|
1237
|
+
break;
|
|
1238
|
+
}
|
|
1239
|
+
case "table": {
|
|
1240
|
+
const tableMarkdown = convertTableToMarkdown(recordId, data.recordMap);
|
|
1241
|
+
result.push(tableMarkdown);
|
|
1242
|
+
break;
|
|
1243
|
+
}
|
|
1244
|
+
case "table_cell": {
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
default:
|
|
1248
|
+
break;
|
|
1249
|
+
}
|
|
1250
|
+
lastType = isList ? "list" : snapshot.type;
|
|
1251
|
+
if (snapshot.children && snapshot.children.length > 0) {
|
|
1252
|
+
for (const childId of snapshot.children) {
|
|
1253
|
+
processRecord(childId);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
if (data.rootId) {
|
|
1258
|
+
processRecord(data.rootId);
|
|
1259
|
+
}
|
|
1260
|
+
return result.join("\n").trim();
|
|
1261
|
+
}
|
|
1262
|
+
function getTextContent3(textData) {
|
|
1263
|
+
if (!textData || !textData.initialAttributedTexts) {
|
|
1264
|
+
return "";
|
|
1265
|
+
}
|
|
1266
|
+
const texts = textData.initialAttributedTexts.text;
|
|
1267
|
+
const attribs = textData.initialAttributedTexts.attribs;
|
|
1268
|
+
if (!texts) return "";
|
|
1269
|
+
if (!attribs || typeof attribs === "string" && attribs === "" || !textData.apool || !textData.apool.numToAttrib) {
|
|
1270
|
+
const content = Object.values(texts).join("");
|
|
1271
|
+
const placeholders = [];
|
|
1272
|
+
let result = content.replace(
|
|
1273
|
+
/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
1274
|
+
(match, text, url) => {
|
|
1275
|
+
placeholders.push(match);
|
|
1276
|
+
return `__LINK_PLACEHOLDER_${placeholders.length - 1}__`;
|
|
1277
|
+
}
|
|
1278
|
+
);
|
|
1279
|
+
result = result.replace(
|
|
1280
|
+
/(https?:\/\/[^\s<>"{}|\\^`\[\]]+)/g,
|
|
1281
|
+
"[$1]($1)"
|
|
1282
|
+
);
|
|
1283
|
+
result = result.replace(
|
|
1284
|
+
/__LINK_PLACEHOLDER_(\d+)__/g,
|
|
1285
|
+
(_, index) => placeholders[parseInt(index)]
|
|
1286
|
+
);
|
|
1287
|
+
return result;
|
|
1288
|
+
}
|
|
1289
|
+
let attribsStr = "";
|
|
1290
|
+
if (typeof attribs === "string") {
|
|
1291
|
+
attribsStr = attribs;
|
|
1292
|
+
} else if (attribs && typeof attribs === "object") {
|
|
1293
|
+
const values = Object.values(attribs);
|
|
1294
|
+
if (values.length > 0 && typeof values[0] === "string") {
|
|
1295
|
+
attribsStr = values[0];
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return parseAttributedText(texts, attribsStr, textData.apool.numToAttrib);
|
|
1299
|
+
}
|
|
1300
|
+
function convertTableToMarkdown(tableRecordId, recordMap) {
|
|
1301
|
+
const tableRecord = recordMap[tableRecordId];
|
|
1302
|
+
if (!tableRecord || !tableRecord.snapshot) {
|
|
1303
|
+
return "";
|
|
1304
|
+
}
|
|
1305
|
+
const snapshot = tableRecord.snapshot;
|
|
1306
|
+
const { columns_id, rows_id, cell_set } = snapshot;
|
|
1307
|
+
if (!columns_id || !rows_id || !cell_set) {
|
|
1308
|
+
return "";
|
|
1309
|
+
}
|
|
1310
|
+
const rows = [];
|
|
1311
|
+
for (const rowId of rows_id) {
|
|
1312
|
+
const row = [];
|
|
1313
|
+
for (const colId of columns_id) {
|
|
1314
|
+
const cellKey = `${rowId}${colId}`;
|
|
1315
|
+
const cell = cell_set[cellKey];
|
|
1316
|
+
if (cell && cell.block_id) {
|
|
1317
|
+
const cellRecord = recordMap[cell.block_id];
|
|
1318
|
+
if (cellRecord && cellRecord.snapshot) {
|
|
1319
|
+
const cellSnapshot = cellRecord.snapshot;
|
|
1320
|
+
const childId = cellSnapshot.children && cellSnapshot.children.length > 0 ? cellSnapshot.children[0] : null;
|
|
1321
|
+
if (childId) {
|
|
1322
|
+
const textRecord = recordMap[childId];
|
|
1323
|
+
if (textRecord && textRecord.snapshot) {
|
|
1324
|
+
const cellText = getTextContent3(textRecord.snapshot.text);
|
|
1325
|
+
row.push(cellText);
|
|
1326
|
+
} else {
|
|
1327
|
+
row.push("");
|
|
1328
|
+
}
|
|
1329
|
+
} else {
|
|
1330
|
+
row.push("");
|
|
1331
|
+
}
|
|
1332
|
+
} else {
|
|
1333
|
+
row.push("");
|
|
1334
|
+
}
|
|
1335
|
+
} else {
|
|
1336
|
+
row.push("");
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
rows.push(row);
|
|
1340
|
+
}
|
|
1341
|
+
if (rows.length === 0) {
|
|
1342
|
+
return "";
|
|
1343
|
+
}
|
|
1344
|
+
const colCount = columns_id.length;
|
|
1345
|
+
const alignments = [];
|
|
1346
|
+
for (const colId of columns_id) {
|
|
1347
|
+
const cellKey = `${rows_id[0]}${colId}`;
|
|
1348
|
+
const cell = cell_set[cellKey];
|
|
1349
|
+
if (cell && cell.block_id) {
|
|
1350
|
+
const cellRecord = recordMap[cell.block_id];
|
|
1351
|
+
if (cellRecord && cellRecord.snapshot) {
|
|
1352
|
+
const cellSnapshot = cellRecord.snapshot;
|
|
1353
|
+
const childId = cellSnapshot.children && cellSnapshot.children.length > 0 ? cellSnapshot.children[0] : null;
|
|
1354
|
+
if (childId) {
|
|
1355
|
+
const textRecord = recordMap[childId];
|
|
1356
|
+
if (textRecord && textRecord.snapshot && textRecord.snapshot.align) {
|
|
1357
|
+
const align = textRecord.snapshot.align;
|
|
1358
|
+
alignments.push(align);
|
|
1359
|
+
} else {
|
|
1360
|
+
alignments.push("left");
|
|
1361
|
+
}
|
|
1362
|
+
} else {
|
|
1363
|
+
alignments.push("left");
|
|
1364
|
+
}
|
|
1365
|
+
} else {
|
|
1366
|
+
alignments.push("left");
|
|
1367
|
+
}
|
|
1368
|
+
} else {
|
|
1369
|
+
alignments.push("left");
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
const separatorRow = alignments.map((align) => {
|
|
1373
|
+
switch (align) {
|
|
1374
|
+
case "center":
|
|
1375
|
+
return ":--:";
|
|
1376
|
+
case "right":
|
|
1377
|
+
return "---:";
|
|
1378
|
+
case "left":
|
|
1379
|
+
default:
|
|
1380
|
+
return ":---";
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
const markdownRows = [];
|
|
1384
|
+
for (let i = 0; i < rows.length; i++) {
|
|
1385
|
+
const row = rows[i];
|
|
1386
|
+
const formattedRow = row.map((cell) => {
|
|
1387
|
+
return cell.includes("|") ? `"${cell.replace(/"/g, '""')}"` : cell;
|
|
1388
|
+
}).join(" | ");
|
|
1389
|
+
markdownRows.push(`| ${formattedRow} |`);
|
|
1390
|
+
if (i === 0) {
|
|
1391
|
+
markdownRows.push(`| ${separatorRow.join(" | ")} |`);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
return markdownRows.join("\n");
|
|
1395
|
+
}
|
|
1396
|
+
function parseAttributedText(texts, attribsStr, numToAttrib) {
|
|
1397
|
+
let content = Object.values(texts).join("");
|
|
1398
|
+
const segments = [];
|
|
1399
|
+
let pos = 0;
|
|
1400
|
+
while (pos < attribsStr.length) {
|
|
1401
|
+
if (attribsStr[pos] === "*") {
|
|
1402
|
+
pos++;
|
|
1403
|
+
const attrNums = [];
|
|
1404
|
+
while (pos < attribsStr.length && /[0-9]/.test(attribsStr[pos])) {
|
|
1405
|
+
let numStr = "";
|
|
1406
|
+
while (pos < attribsStr.length && /[0-9]/.test(attribsStr[pos])) {
|
|
1407
|
+
numStr += attribsStr[pos];
|
|
1408
|
+
pos++;
|
|
1409
|
+
}
|
|
1410
|
+
attrNums.push(numStr);
|
|
1411
|
+
if (pos < attribsStr.length && attribsStr[pos] === "*") {
|
|
1412
|
+
pos++;
|
|
1413
|
+
} else {
|
|
1414
|
+
break;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
if (pos >= attribsStr.length || attribsStr[pos] !== "+") break;
|
|
1418
|
+
pos++;
|
|
1419
|
+
let lengthStr = "";
|
|
1420
|
+
while (pos < attribsStr.length) {
|
|
1421
|
+
const char = attribsStr[pos];
|
|
1422
|
+
if (/[0-9]/.test(char)) {
|
|
1423
|
+
lengthStr += char;
|
|
1424
|
+
pos++;
|
|
1425
|
+
} else {
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
if (!lengthStr) {
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
const length = parseInt(lengthStr, 10) || 0;
|
|
1433
|
+
const text = content.substring(0, length);
|
|
1434
|
+
content = content.substring(length);
|
|
1435
|
+
const attrs = {};
|
|
1436
|
+
for (const num of attrNums) {
|
|
1437
|
+
const attrValue = numToAttrib[num];
|
|
1438
|
+
if (attrValue && Array.isArray(attrValue) && attrValue.length >= 2) {
|
|
1439
|
+
attrs[String(attrValue[0])] = attrValue[1];
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
if (text) {
|
|
1443
|
+
segments.push({ text, attrs });
|
|
1444
|
+
}
|
|
1445
|
+
} else {
|
|
1446
|
+
pos++;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
if (content) {
|
|
1450
|
+
segments.push({ text: content, attrs: {} });
|
|
1451
|
+
}
|
|
1452
|
+
let result = "";
|
|
1453
|
+
for (const segment of segments) {
|
|
1454
|
+
const { text, attrs } = segment;
|
|
1455
|
+
if (attrs.link) {
|
|
1456
|
+
const url = decodeURIComponent(String(attrs.link));
|
|
1457
|
+
result += `[${text}](${url})`;
|
|
1458
|
+
} else if (attrs.equation) {
|
|
1459
|
+
const equation = String(attrs.equation).trim();
|
|
1460
|
+
const isDisplay = equation.endsWith("_display");
|
|
1461
|
+
const cleanEquation = isDisplay ? equation.slice(0, -8) : equation;
|
|
1462
|
+
result += isDisplay ? `$$${cleanEquation}$$` : `$${cleanEquation}$`;
|
|
1463
|
+
} else {
|
|
1464
|
+
let formattedText = text;
|
|
1465
|
+
if (attrs.strikethrough === "true") {
|
|
1466
|
+
formattedText = `~~${formattedText}~~`;
|
|
1467
|
+
}
|
|
1468
|
+
if (attrs.bold === "true") {
|
|
1469
|
+
formattedText = `**${formattedText}**`;
|
|
1470
|
+
}
|
|
1471
|
+
if (attrs.italic === "true") {
|
|
1472
|
+
formattedText = `*${formattedText}*`;
|
|
1473
|
+
}
|
|
1474
|
+
result += formattedText;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
return result;
|
|
1478
|
+
}
|
|
1479
|
+
var TEST_CASES = {
|
|
1480
|
+
heading: `# \u4E00\u7EA7\u6807\u9898
|
|
1481
|
+
## \u4E8C\u7EA7\u6807\u9898
|
|
1482
|
+
### \u4E09\u7EA7\u6807\u9898
|
|
1483
|
+
`,
|
|
1484
|
+
paragraph: `\u8FD9\u662F\u666E\u901A\u6587\u672C\u6BB5\u843D\u3002
|
|
1485
|
+
|
|
1486
|
+
\u8FD9\u662F\u7B2C\u4E8C\u6BB5\u3002`,
|
|
1487
|
+
list: `- \u9879\u76EE 1
|
|
1488
|
+
- \u9879\u76EE 2
|
|
1489
|
+
- \u9879\u76EE 3
|
|
1490
|
+
`,
|
|
1491
|
+
ordered: `1. \u7B2C\u4E00\u9879
|
|
1492
|
+
2. \u7B2C\u4E8C\u9879
|
|
1493
|
+
3. \u7B2C\u4E09\u9879
|
|
1494
|
+
`,
|
|
1495
|
+
todo: `- [ ] \u672A\u5B8C\u6210\u4EFB\u52A1
|
|
1496
|
+
- [x] \u5DF2\u5B8C\u6210\u4EFB\u52A1
|
|
1497
|
+
`,
|
|
1498
|
+
quote: `> \u8FD9\u662F\u4E00\u6BB5\u5F15\u7528\u6587\u672C\u3002
|
|
1499
|
+
|
|
1500
|
+
> \u591A\u884C\u5F15\u7528\u3002`,
|
|
1501
|
+
code: `\`\`\`javascript
|
|
1502
|
+
function hello() {
|
|
1503
|
+
console.log('Hello');
|
|
1504
|
+
}
|
|
1505
|
+
\`\`\``,
|
|
1506
|
+
divider: `---
|
|
1507
|
+
`,
|
|
1508
|
+
link: `\u8FD9\u662F\u4E00\u4E2A [\u94FE\u63A5](https://feishu.cn)\u3002
|
|
1509
|
+
`,
|
|
1510
|
+
image: `
|
|
1511
|
+
`,
|
|
1512
|
+
mermaid: `\`\`\`mermaid
|
|
1513
|
+
graph TD
|
|
1514
|
+
A[\u5F00\u59CB] --> B[\u7ED3\u675F]
|
|
1515
|
+
\`\`\``,
|
|
1516
|
+
nested: `- \u4E00\u7EA7\u9879\u76EE
|
|
1517
|
+
- \u4E8C\u7EA7\u9879\u76EE
|
|
1518
|
+
- \u4E09\u7EA7\u9879\u76EE
|
|
1519
|
+
`,
|
|
1520
|
+
mixed: `# \u6807\u9898
|
|
1521
|
+
|
|
1522
|
+
\u8FD9\u662F\u6BB5\u843D\uFF0C\u5305\u542B**\u7C97\u4F53**\u548C*\u659C\u4F53*\u3002
|
|
1523
|
+
|
|
1524
|
+
- \u5217\u8868\u9879
|
|
1525
|
+
- \u53E6\u4E00\u9879
|
|
1526
|
+
|
|
1527
|
+
\`\`\`\u4EE3\u7801\`\`\``,
|
|
1528
|
+
complex: `# \u5B8C\u6574\u6587\u6863
|
|
1529
|
+
|
|
1530
|
+
## \u7AE0\u8282
|
|
1531
|
+
|
|
1532
|
+
\u8FD9\u662F\u6BB5\u843D\u3002
|
|
1533
|
+
|
|
1534
|
+
- \u5217\u8868\u9879 1
|
|
1535
|
+
- \u5217\u8868\u9879 2
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
> \u5F15\u7528\u5757
|
|
1539
|
+
|
|
1540
|
+
\`\`\`javascript
|
|
1541
|
+
const a = 1;
|
|
1542
|
+
\`\`\`
|
|
1543
|
+
|
|
1544
|
+
---
|
|
1545
|
+
|
|
1546
|
+
## \u4E0B\u4E00\u4E2A\u7AE0\u8282
|
|
1547
|
+
|
|
1548
|
+
\u5185\u5BB9\u3002`
|
|
1549
|
+
};
|
|
1550
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1551
|
+
0 && (module.exports = {
|
|
1552
|
+
MarkdownToLarkConverter,
|
|
1553
|
+
TEST_CASES,
|
|
1554
|
+
generateBlockHtml,
|
|
1555
|
+
generateBlockId,
|
|
1556
|
+
generateHtml,
|
|
1557
|
+
generatePageId,
|
|
1558
|
+
generateRecordId,
|
|
1559
|
+
larkToMarkdown,
|
|
1560
|
+
markdownToLark,
|
|
1561
|
+
parseMarkdown,
|
|
1562
|
+
readClipboard,
|
|
1563
|
+
writeToClipboard
|
|
1564
|
+
});
|
|
1565
|
+
//# sourceMappingURL=index.js.map
|