@moxn/kb-migrate 0.4.16 → 0.4.17
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/targets/notion.js +33 -19
- package/package.json +1 -1
package/dist/targets/notion.js
CHANGED
|
@@ -188,41 +188,47 @@ async function uploadFileToNotion(client, url, filename, contentType) {
|
|
|
188
188
|
* Post-process martian output to reconstruct callout blocks.
|
|
189
189
|
*
|
|
190
190
|
* Callouts are stored as blockquotes with an emoji prefix (e.g., `> 💡 tip text`).
|
|
191
|
-
* Martian converts these to Notion `quote` blocks
|
|
192
|
-
*
|
|
191
|
+
* Martian converts these to Notion `quote` blocks with the actual text inside
|
|
192
|
+
* `children[].paragraph.rich_text` (not the top-level `rich_text`).
|
|
193
|
+
* This function detects the emoji prefix pattern in the first child paragraph
|
|
194
|
+
* and converts matching quotes to native Notion `callout` blocks.
|
|
193
195
|
*/
|
|
194
196
|
function reconstructCallouts(blocks) {
|
|
195
197
|
const emojiPrefixRe = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F?)\s/u;
|
|
198
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
196
199
|
return blocks.map((block) => {
|
|
197
200
|
if (block.type !== 'quote')
|
|
198
201
|
return block;
|
|
199
|
-
const
|
|
200
|
-
if (!
|
|
202
|
+
const children = block.quote?.children;
|
|
203
|
+
if (!children?.length)
|
|
201
204
|
return block;
|
|
202
|
-
|
|
205
|
+
// Find the first child paragraph with text
|
|
206
|
+
const firstChild = children[0];
|
|
207
|
+
if (firstChild.type !== 'paragraph' || !firstChild.paragraph?.rich_text?.length)
|
|
208
|
+
return block;
|
|
209
|
+
const firstSegment = firstChild.paragraph.rich_text[0];
|
|
203
210
|
if (firstSegment.type !== 'text' || !firstSegment.text?.content)
|
|
204
211
|
return block;
|
|
205
212
|
const match = firstSegment.text.content.match(emojiPrefixRe);
|
|
206
213
|
if (!match)
|
|
207
|
-
return block;
|
|
214
|
+
return block; // No emoji prefix — keep as regular quote
|
|
208
215
|
const emoji = match[1];
|
|
209
216
|
const strippedContent = firstSegment.text.content.slice(match[0].length);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
...
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const quoteBlock = block;
|
|
217
|
+
// Build the callout's rich_text from the first child paragraph (stripped of emoji)
|
|
218
|
+
const calloutRichText = [
|
|
219
|
+
{ ...firstSegment, text: { ...firstSegment.text, content: strippedContent } },
|
|
220
|
+
...firstChild.paragraph.rich_text.slice(1),
|
|
221
|
+
].filter((rt) => rt.text?.content);
|
|
222
|
+
// Remaining children become the callout's children
|
|
223
|
+
const remainingChildren = children.slice(1);
|
|
218
224
|
return {
|
|
219
225
|
object: 'block',
|
|
220
226
|
type: 'callout',
|
|
221
227
|
callout: {
|
|
222
|
-
rich_text:
|
|
228
|
+
rich_text: calloutRichText,
|
|
223
229
|
icon: { type: 'emoji', emoji },
|
|
224
230
|
color: 'default',
|
|
225
|
-
...(
|
|
231
|
+
...(remainingChildren.length > 0 ? { children: remainingChildren } : {}),
|
|
226
232
|
},
|
|
227
233
|
};
|
|
228
234
|
});
|
|
@@ -265,14 +271,22 @@ async function sectionsToNotionBlocks(sections, options) {
|
|
|
265
271
|
allReferences.push(...references);
|
|
266
272
|
}
|
|
267
273
|
text = stripInvalidLinks(text);
|
|
268
|
-
// Split on standalone --- dividers and emit native Notion divider blocks
|
|
269
|
-
|
|
274
|
+
// Split on standalone --- dividers and emit native Notion divider blocks.
|
|
275
|
+
// Pad with newlines so --- at start/end of text is also caught.
|
|
276
|
+
const padded = '\n' + text + '\n';
|
|
277
|
+
const rawParts = padded.split('\n---\n');
|
|
278
|
+
const parts = rawParts.map((p, idx) => {
|
|
279
|
+
if (idx === 0)
|
|
280
|
+
p = p.slice(1); // remove leading \n pad
|
|
281
|
+
if (idx === rawParts.length - 1)
|
|
282
|
+
p = p.slice(0, -1); // remove trailing \n pad
|
|
283
|
+
return p;
|
|
284
|
+
});
|
|
270
285
|
for (let i = 0; i < parts.length; i++) {
|
|
271
286
|
if (i > 0) {
|
|
272
287
|
flushText();
|
|
273
288
|
allBlocks.push({ object: 'block', type: 'divider', divider: {} });
|
|
274
289
|
}
|
|
275
|
-
// Handle --- at start (empty first part) or end (empty last part)
|
|
276
290
|
const part = parts[i];
|
|
277
291
|
if (part.trim()) {
|
|
278
292
|
pendingMarkdown.push(part);
|
package/package.json
CHANGED