feishu-docs-cli 0.1.0-beta.7 → 0.1.0-beta.8
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.
|
@@ -6,6 +6,12 @@
|
|
|
6
6
|
* table assembly with just 2 API calls:
|
|
7
7
|
* 1. Convert API: Markdown string -> block tree (server-side parsing)
|
|
8
8
|
* 2. Descendant API: Write entire block tree in one call (no 9-row table limit)
|
|
9
|
+
*
|
|
10
|
+
* Notes:
|
|
11
|
+
* - Descendant API accepts at most 1000 blocks per call; large content is
|
|
12
|
+
* automatically split into batches at top-level block boundaries.
|
|
13
|
+
* - Read-only fields returned by Convert API (parent_id, comment_ids,
|
|
14
|
+
* merge_info) are stripped before writing to avoid validation errors.
|
|
9
15
|
*/
|
|
10
16
|
import { AuthInfo, ConvertedBlocks, Block } from "../types/index.js";
|
|
11
17
|
/**
|
|
@@ -21,13 +27,24 @@ export declare function normalizeLangNames(markdown: string): string;
|
|
|
21
27
|
*/
|
|
22
28
|
export declare function convertMarkdown(authInfo: AuthInfo, markdown: string): Promise<ConvertedBlocks>;
|
|
23
29
|
/**
|
|
24
|
-
*
|
|
30
|
+
* Sanitize blocks for the Descendant API by removing read-only fields.
|
|
31
|
+
*
|
|
32
|
+
* Strips:
|
|
33
|
+
* - top-level read-only fields: parent_id, comment_ids
|
|
34
|
+
* - table.property.merge_info (read-only attribute)
|
|
35
|
+
*
|
|
25
36
|
* Returns a new array (immutable).
|
|
26
37
|
*/
|
|
27
|
-
export declare function
|
|
38
|
+
export declare function sanitizeBlocks(blocks: Block[]): Block[];
|
|
39
|
+
/**
|
|
40
|
+
* Split converted blocks into batches that each stay within
|
|
41
|
+
* MAX_BLOCKS_PER_CALL. Splits at top-level block boundaries so
|
|
42
|
+
* parent–child relationships are preserved within each batch.
|
|
43
|
+
*/
|
|
44
|
+
export declare function splitIntoBatches(converted: ConvertedBlocks): ConvertedBlocks[];
|
|
28
45
|
/**
|
|
29
46
|
* Write blocks to document via Descendant API.
|
|
30
|
-
*
|
|
47
|
+
* Automatically batches when block count exceeds 1000.
|
|
31
48
|
*
|
|
32
49
|
* @param {object} authInfo - Auth credentials
|
|
33
50
|
* @param {string} documentId - Target document ID
|
|
@@ -6,9 +6,17 @@
|
|
|
6
6
|
* table assembly with just 2 API calls:
|
|
7
7
|
* 1. Convert API: Markdown string -> block tree (server-side parsing)
|
|
8
8
|
* 2. Descendant API: Write entire block tree in one call (no 9-row table limit)
|
|
9
|
+
*
|
|
10
|
+
* Notes:
|
|
11
|
+
* - Descendant API accepts at most 1000 blocks per call; large content is
|
|
12
|
+
* automatically split into batches at top-level block boundaries.
|
|
13
|
+
* - Read-only fields returned by Convert API (parent_id, comment_ids,
|
|
14
|
+
* merge_info) are stripped before writing to avoid validation errors.
|
|
9
15
|
*/
|
|
10
16
|
import { fetchWithAuth } from "../client.js";
|
|
11
17
|
import { CliError } from "../utils/errors.js";
|
|
18
|
+
/** Maximum blocks the Descendant API accepts per call. */
|
|
19
|
+
const MAX_BLOCKS_PER_CALL = 1000;
|
|
12
20
|
/**
|
|
13
21
|
* Language aliases that Feishu Convert API does not recognize.
|
|
14
22
|
* Maps unrecognized names → recognized names so code blocks render correctly.
|
|
@@ -49,24 +57,113 @@ export async function convertMarkdown(authInfo, markdown) {
|
|
|
49
57
|
};
|
|
50
58
|
}
|
|
51
59
|
/**
|
|
52
|
-
*
|
|
60
|
+
* Read-only / server-generated fields that the Descendant API rejects.
|
|
61
|
+
* These are returned by the Convert API but must not be sent back.
|
|
62
|
+
*/
|
|
63
|
+
const READ_ONLY_BLOCK_FIELDS = ["parent_id", "comment_ids"];
|
|
64
|
+
/**
|
|
65
|
+
* Sanitize blocks for the Descendant API by removing read-only fields.
|
|
66
|
+
*
|
|
67
|
+
* Strips:
|
|
68
|
+
* - top-level read-only fields: parent_id, comment_ids
|
|
69
|
+
* - table.property.merge_info (read-only attribute)
|
|
70
|
+
*
|
|
53
71
|
* Returns a new array (immutable).
|
|
54
72
|
*/
|
|
55
|
-
export function
|
|
73
|
+
export function sanitizeBlocks(blocks) {
|
|
56
74
|
return blocks.map((block) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
let cleaned = block;
|
|
76
|
+
// Strip top-level read-only fields
|
|
77
|
+
for (const field of READ_ONLY_BLOCK_FIELDS) {
|
|
78
|
+
if (field in cleaned) {
|
|
79
|
+
const { [field]: _, ...rest } = cleaned;
|
|
80
|
+
cleaned = rest;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Strip table.property.merge_info
|
|
84
|
+
if (cleaned.table?.property?.merge_info) {
|
|
85
|
+
const { merge_info, ...restProperty } = cleaned.table.property;
|
|
86
|
+
cleaned = {
|
|
87
|
+
...cleaned,
|
|
88
|
+
table: { ...cleaned.table, property: restProperty },
|
|
62
89
|
};
|
|
63
90
|
}
|
|
64
|
-
return
|
|
91
|
+
return cleaned;
|
|
65
92
|
});
|
|
66
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Collect all descendant block IDs reachable from a set of top-level IDs.
|
|
96
|
+
* Traverses the children tree in the block array.
|
|
97
|
+
*/
|
|
98
|
+
function collectDescendantIds(topLevelIds, blockMap) {
|
|
99
|
+
const ids = new Set();
|
|
100
|
+
const queue = [...topLevelIds];
|
|
101
|
+
while (queue.length > 0) {
|
|
102
|
+
const id = queue.pop();
|
|
103
|
+
if (ids.has(id))
|
|
104
|
+
continue;
|
|
105
|
+
ids.add(id);
|
|
106
|
+
const block = blockMap.get(id);
|
|
107
|
+
if (block?.children) {
|
|
108
|
+
queue.push(...block.children);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return ids;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build a ConvertedBlocks batch from a subset of blocks.
|
|
115
|
+
* Filters blockIdToImageUrls to only include entries for blocks in this batch.
|
|
116
|
+
*/
|
|
117
|
+
function buildBatch(topIds, blockIds, allBlocks, source) {
|
|
118
|
+
const imageUrls = Object.fromEntries(Object.entries(source.blockIdToImageUrls).filter(([id]) => blockIds.has(id)));
|
|
119
|
+
return {
|
|
120
|
+
firstLevelBlockIds: topIds,
|
|
121
|
+
blocks: allBlocks.filter((b) => blockIds.has(b.block_id)),
|
|
122
|
+
blockIdToImageUrls: imageUrls,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Split converted blocks into batches that each stay within
|
|
127
|
+
* MAX_BLOCKS_PER_CALL. Splits at top-level block boundaries so
|
|
128
|
+
* parent–child relationships are preserved within each batch.
|
|
129
|
+
*/
|
|
130
|
+
export function splitIntoBatches(converted) {
|
|
131
|
+
const allBlocks = sanitizeBlocks(converted.blocks);
|
|
132
|
+
if (allBlocks.length <= MAX_BLOCKS_PER_CALL) {
|
|
133
|
+
return [{ ...converted, blocks: allBlocks }];
|
|
134
|
+
}
|
|
135
|
+
const blockMap = new Map(allBlocks.map((b) => [b.block_id, b]));
|
|
136
|
+
const batches = [];
|
|
137
|
+
let batchTopIds = [];
|
|
138
|
+
let batchBlockCount = 0;
|
|
139
|
+
for (const topId of converted.firstLevelBlockIds) {
|
|
140
|
+
const descendantIds = collectDescendantIds([topId], blockMap);
|
|
141
|
+
const subtreeSize = descendantIds.size;
|
|
142
|
+
// A single top-level subtree that exceeds the limit cannot be split further
|
|
143
|
+
if (subtreeSize > MAX_BLOCKS_PER_CALL) {
|
|
144
|
+
throw new CliError("API_ERROR", `单个顶层块的后代数量 (${subtreeSize}) 超过 Descendant API 限制 (${MAX_BLOCKS_PER_CALL}),无法拆分`);
|
|
145
|
+
}
|
|
146
|
+
// If adding this top-level block would exceed the limit, flush current batch
|
|
147
|
+
if (batchBlockCount > 0 &&
|
|
148
|
+
batchBlockCount + subtreeSize > MAX_BLOCKS_PER_CALL) {
|
|
149
|
+
const batchIds = collectDescendantIds(batchTopIds, blockMap);
|
|
150
|
+
batches.push(buildBatch(batchTopIds, batchIds, allBlocks, converted));
|
|
151
|
+
batchTopIds = [];
|
|
152
|
+
batchBlockCount = 0;
|
|
153
|
+
}
|
|
154
|
+
batchTopIds.push(topId);
|
|
155
|
+
batchBlockCount += subtreeSize;
|
|
156
|
+
}
|
|
157
|
+
// Flush remaining
|
|
158
|
+
if (batchTopIds.length > 0) {
|
|
159
|
+
const batchIds = collectDescendantIds(batchTopIds, blockMap);
|
|
160
|
+
batches.push(buildBatch(batchTopIds, batchIds, allBlocks, converted));
|
|
161
|
+
}
|
|
162
|
+
return batches;
|
|
163
|
+
}
|
|
67
164
|
/**
|
|
68
165
|
* Write blocks to document via Descendant API.
|
|
69
|
-
*
|
|
166
|
+
* Automatically batches when block count exceeds 1000.
|
|
70
167
|
*
|
|
71
168
|
* @param {object} authInfo - Auth credentials
|
|
72
169
|
* @param {string} documentId - Target document ID
|
|
@@ -77,20 +174,31 @@ export function stripMergeInfo(blocks) {
|
|
|
77
174
|
* @returns {number} Updated revision ID
|
|
78
175
|
*/
|
|
79
176
|
export async function writeDescendant(authInfo, documentId, parentBlockId, converted, revisionId, index = 0) {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
177
|
+
const batches = splitIntoBatches(converted);
|
|
178
|
+
if (batches.length > 1) {
|
|
179
|
+
process.stderr.write(`feishu-docs: info: 内容较大 (${converted.blocks.length} blocks),分 ${batches.length} 批写入\n`);
|
|
180
|
+
}
|
|
181
|
+
let rev = revisionId;
|
|
182
|
+
for (let i = 0; i < batches.length; i++) {
|
|
183
|
+
const batch = batches[i];
|
|
184
|
+
// First batch uses caller-specified index; subsequent batches append
|
|
185
|
+
const batchIndex = i === 0 ? index : -1;
|
|
186
|
+
const res = await fetchWithAuth(authInfo, `/open-apis/docx/v1/documents/${encodeURIComponent(documentId)}/blocks/${encodeURIComponent(parentBlockId)}/descendant`, {
|
|
187
|
+
method: "POST",
|
|
188
|
+
body: {
|
|
189
|
+
children_id: batch.firstLevelBlockIds,
|
|
190
|
+
descendants: batch.blocks,
|
|
191
|
+
index: batchIndex,
|
|
192
|
+
},
|
|
193
|
+
params: {
|
|
194
|
+
document_revision_id: rev,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
rev =
|
|
198
|
+
res?.data
|
|
199
|
+
?.document_revision_id ?? rev;
|
|
200
|
+
}
|
|
201
|
+
return rev;
|
|
94
202
|
}
|
|
95
203
|
/**
|
|
96
204
|
* High-level: Convert markdown and write to document in 2 API calls.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-convert.js","sourceRoot":"","sources":["../../src/services/markdown-convert.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"markdown-convert.js","sourceRoot":"","sources":["../../src/services/markdown-convert.ts"],"names":[],"mappings":"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"}
|