@atikk-co-jp/notion-mcp-server 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +1 -0
- package/README.md +20 -2
- package/dist/src/converters/__tests__/block-to-markdown.test.js +482 -111
- package/dist/src/converters/__tests__/markdown-to-blocks.test.js +116 -13
- package/dist/src/converters/__tests__/page-to-markdown.test.js +83 -70
- package/dist/src/converters/__tests__/rich-text-to-markdown.test.js +23 -26
- package/dist/src/converters/block-to-markdown.d.ts +4 -13
- package/dist/src/converters/block-to-markdown.d.ts.map +1 -1
- package/dist/src/converters/block-to-markdown.js +117 -120
- package/dist/src/converters/index.d.ts +3 -3
- package/dist/src/converters/index.d.ts.map +1 -1
- package/dist/src/converters/index.js +1 -1
- package/dist/src/converters/markdown-to-blocks.d.ts +21 -7
- package/dist/src/converters/markdown-to-blocks.d.ts.map +1 -1
- package/dist/src/converters/markdown-to-blocks.js +56 -0
- package/dist/src/converters/page-to-markdown.d.ts +5 -20
- package/dist/src/converters/page-to-markdown.d.ts.map +1 -1
- package/dist/src/converters/page-to-markdown.js +47 -37
- package/dist/src/converters/rich-text-to-markdown.d.ts +3 -47
- package/dist/src/converters/rich-text-to-markdown.d.ts.map +1 -1
- package/dist/src/converters/rich-text-to-markdown.js +15 -14
- package/dist/src/notion-client.d.ts +5 -177
- package/dist/src/notion-client.d.ts.map +1 -1
- package/dist/src/notion-client.js +6 -172
- package/dist/src/schemas/descriptions/examples.d.ts +14 -0
- package/dist/src/schemas/descriptions/examples.d.ts.map +1 -0
- package/dist/src/schemas/descriptions/examples.js +87 -0
- package/dist/src/schemas/descriptions/fields.d.ts +146 -0
- package/dist/src/schemas/descriptions/fields.d.ts.map +1 -0
- package/dist/src/schemas/descriptions/fields.js +184 -0
- package/dist/src/schemas/descriptions/index.d.ts +3 -0
- package/dist/src/schemas/descriptions/index.d.ts.map +1 -0
- package/dist/src/schemas/descriptions/index.js +2 -0
- package/dist/src/schemas/index.d.ts +1 -5
- package/dist/src/schemas/index.d.ts.map +1 -1
- package/dist/src/schemas/index.js +2 -10
- package/dist/src/tools/__tests__/context-size.test.d.ts +2 -0
- package/dist/src/tools/__tests__/context-size.test.d.ts.map +1 -0
- package/dist/src/tools/__tests__/context-size.test.js +143 -0
- package/dist/src/tools/__tests__/error-handler.test.d.ts +2 -0
- package/dist/src/tools/__tests__/error-handler.test.d.ts.map +1 -0
- package/dist/src/tools/__tests__/error-handler.test.js +125 -0
- package/dist/src/tools/append-block-children.d.ts.map +1 -1
- package/dist/src/tools/append-block-children.js +8 -5
- package/dist/src/tools/append-blocks-simple.d.ts.map +1 -1
- package/dist/src/tools/append-blocks-simple.js +9 -13
- package/dist/src/tools/archive-database.d.ts.map +1 -1
- package/dist/src/tools/archive-database.js +4 -4
- package/dist/src/tools/archive-page.d.ts.map +1 -1
- package/dist/src/tools/archive-page.js +3 -3
- package/dist/src/tools/create-comment-simple.d.ts +4 -0
- package/dist/src/tools/create-comment-simple.d.ts.map +1 -0
- package/dist/src/tools/create-comment-simple.js +51 -0
- package/dist/src/tools/create-comment.d.ts.map +1 -1
- package/dist/src/tools/create-comment.js +28 -8
- package/dist/src/tools/create-database.d.ts.map +1 -1
- package/dist/src/tools/create-database.js +19 -25
- package/dist/src/tools/create-page-simple.d.ts +1 -1
- package/dist/src/tools/create-page-simple.d.ts.map +1 -1
- package/dist/src/tools/create-page-simple.js +41 -26
- package/dist/src/tools/create-page.d.ts.map +1 -1
- package/dist/src/tools/create-page.js +11 -7
- package/dist/src/tools/delete-block.d.ts.map +1 -1
- package/dist/src/tools/delete-block.js +2 -1
- package/dist/src/tools/get-block-children.d.ts +1 -1
- package/dist/src/tools/get-block-children.d.ts.map +1 -1
- package/dist/src/tools/get-block-children.js +13 -27
- package/dist/src/tools/index.d.ts +4 -3
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +5 -3
- package/dist/src/tools/list-comments.d.ts +1 -1
- package/dist/src/tools/list-comments.d.ts.map +1 -1
- package/dist/src/tools/list-comments.js +11 -10
- package/dist/src/tools/list-users.d.ts.map +1 -1
- package/dist/src/tools/list-users.js +4 -3
- package/dist/src/tools/move-page.d.ts.map +1 -1
- package/dist/src/tools/move-page.js +5 -4
- package/dist/src/tools/query-data-source.d.ts +1 -1
- package/dist/src/tools/query-data-source.d.ts.map +1 -1
- package/dist/src/tools/query-data-source.js +23 -24
- package/dist/src/tools/retrieve-block.d.ts +1 -1
- package/dist/src/tools/retrieve-block.d.ts.map +1 -1
- package/dist/src/tools/retrieve-block.js +13 -10
- package/dist/src/tools/retrieve-bot-user.js +1 -1
- package/dist/src/tools/retrieve-data-source.d.ts +1 -1
- package/dist/src/tools/retrieve-data-source.d.ts.map +1 -1
- package/dist/src/tools/retrieve-data-source.js +15 -11
- package/dist/src/tools/retrieve-database.d.ts +1 -1
- package/dist/src/tools/retrieve-database.d.ts.map +1 -1
- package/dist/src/tools/retrieve-database.js +11 -6
- package/dist/src/tools/retrieve-page-property.d.ts.map +1 -1
- package/dist/src/tools/retrieve-page-property.js +7 -7
- package/dist/src/tools/retrieve-page.d.ts +1 -1
- package/dist/src/tools/retrieve-page.d.ts.map +1 -1
- package/dist/src/tools/retrieve-page.js +15 -20
- package/dist/src/tools/retrieve-user.d.ts.map +1 -1
- package/dist/src/tools/retrieve-user.js +2 -1
- package/dist/src/tools/search.d.ts.map +1 -1
- package/dist/src/tools/search.js +10 -17
- package/dist/src/tools/update-block-simple.d.ts +1 -1
- package/dist/src/tools/update-block-simple.d.ts.map +1 -1
- package/dist/src/tools/update-block-simple.js +14 -4
- package/dist/src/tools/update-block.d.ts.map +1 -1
- package/dist/src/tools/update-block.js +8 -5
- package/dist/src/tools/update-data-source.d.ts.map +1 -1
- package/dist/src/tools/update-data-source.js +8 -8
- package/dist/src/tools/update-database.d.ts.map +1 -1
- package/dist/src/tools/update-database.js +22 -32
- package/dist/src/tools/update-page.d.ts.map +1 -1
- package/dist/src/tools/update-page.js +13 -8
- package/dist/src/utils/error-handler.d.ts +20 -0
- package/dist/src/utils/error-handler.d.ts.map +1 -1
- package/dist/src/utils/error-handler.js +63 -0
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/package.json +2 -1
- package/dist/src/schemas/block.d.ts +0 -3787
- package/dist/src/schemas/block.d.ts.map +0 -1
- package/dist/src/schemas/block.js +0 -402
- package/dist/src/schemas/common.d.ts +0 -638
- package/dist/src/schemas/common.d.ts.map +0 -1
- package/dist/src/schemas/common.js +0 -163
- package/dist/src/schemas/database.d.ts +0 -687
- package/dist/src/schemas/database.d.ts.map +0 -1
- package/dist/src/schemas/database.js +0 -258
- package/dist/src/schemas/filter.d.ts +0 -611
- package/dist/src/schemas/filter.d.ts.map +0 -1
- package/dist/src/schemas/filter.js +0 -222
- package/dist/src/schemas/page.d.ts +0 -2607
- package/dist/src/schemas/page.d.ts.map +0 -1
- package/dist/src/schemas/page.js +0 -328
- package/dist/src/schemas/schemas.test.d.ts +0 -2
- package/dist/src/schemas/schemas.test.d.ts.map +0 -1
- package/dist/src/schemas/schemas.test.js +0 -418
|
@@ -8,27 +8,24 @@ import { richTextToMarkdown } from './rich-text-to-markdown.js';
|
|
|
8
8
|
function extractFileUrl(fileObj) {
|
|
9
9
|
if (!fileObj)
|
|
10
10
|
return '';
|
|
11
|
-
if (fileObj.type === 'external'
|
|
11
|
+
if (fileObj.type === 'external') {
|
|
12
12
|
return fileObj.external.url;
|
|
13
13
|
}
|
|
14
|
-
if (fileObj.type === 'file'
|
|
14
|
+
if (fileObj.type === 'file') {
|
|
15
15
|
return fileObj.file.url;
|
|
16
16
|
}
|
|
17
|
-
// type が指定されていない場合のフォールバック
|
|
18
|
-
if (fileObj.external?.url)
|
|
19
|
-
return fileObj.external.url;
|
|
20
|
-
if (fileObj.file?.url)
|
|
21
|
-
return fileObj.file.url;
|
|
22
17
|
return '';
|
|
23
18
|
}
|
|
24
19
|
/**
|
|
25
20
|
* アイコンからテキストを抽出
|
|
21
|
+
* SDK の PageIconResponse 型は custom_emoji も含むため any 経由で処理
|
|
26
22
|
*/
|
|
27
23
|
function extractIconText(icon) {
|
|
28
|
-
if (!icon)
|
|
24
|
+
if (!icon || typeof icon !== 'object')
|
|
29
25
|
return '';
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
const iconObj = icon;
|
|
27
|
+
if (iconObj.type === 'emoji' && iconObj.emoji) {
|
|
28
|
+
return iconObj.emoji;
|
|
32
29
|
}
|
|
33
30
|
return '';
|
|
34
31
|
}
|
|
@@ -37,33 +34,28 @@ function extractIconText(icon) {
|
|
|
37
34
|
*/
|
|
38
35
|
async function convertBlock(block, options = {}) {
|
|
39
36
|
const indent = ' '.repeat(options.indentLevel ?? 0);
|
|
40
|
-
const blockData = block[block.type];
|
|
41
|
-
if (!blockData && block.type !== 'divider') {
|
|
42
|
-
// 未対応ブロックタイプの場合
|
|
43
|
-
return `${indent}<!-- Unsupported block type: ${block.type} -->`;
|
|
44
|
-
}
|
|
45
37
|
switch (block.type) {
|
|
46
38
|
case 'paragraph': {
|
|
47
|
-
const text = richTextToMarkdown(
|
|
39
|
+
const text = richTextToMarkdown(block.paragraph.rich_text);
|
|
48
40
|
return text ? `${indent}${text}` : '';
|
|
49
41
|
}
|
|
50
42
|
case 'heading_1': {
|
|
51
|
-
const text = richTextToMarkdown(
|
|
43
|
+
const text = richTextToMarkdown(block.heading_1.rich_text);
|
|
52
44
|
return `${indent}# ${text}`;
|
|
53
45
|
}
|
|
54
46
|
case 'heading_2': {
|
|
55
|
-
const text = richTextToMarkdown(
|
|
47
|
+
const text = richTextToMarkdown(block.heading_2.rich_text);
|
|
56
48
|
return `${indent}## ${text}`;
|
|
57
49
|
}
|
|
58
50
|
case 'heading_3': {
|
|
59
|
-
const text = richTextToMarkdown(
|
|
51
|
+
const text = richTextToMarkdown(block.heading_3.rich_text);
|
|
60
52
|
return `${indent}### ${text}`;
|
|
61
53
|
}
|
|
62
54
|
case 'bulleted_list_item': {
|
|
63
|
-
const text = richTextToMarkdown(
|
|
55
|
+
const text = richTextToMarkdown(block.bulleted_list_item.rich_text);
|
|
64
56
|
let result = `${indent}- ${text}`;
|
|
65
57
|
// 子ブロックがある場合
|
|
66
|
-
if (block.has_children && options.fetchChildren
|
|
58
|
+
if (block.has_children && options.fetchChildren) {
|
|
67
59
|
const children = await options.fetchChildren(block.id);
|
|
68
60
|
const childMarkdown = await blocksToMarkdown(children, {
|
|
69
61
|
...options,
|
|
@@ -76,11 +68,11 @@ async function convertBlock(block, options = {}) {
|
|
|
76
68
|
return result;
|
|
77
69
|
}
|
|
78
70
|
case 'numbered_list_item': {
|
|
79
|
-
const text = richTextToMarkdown(
|
|
71
|
+
const text = richTextToMarkdown(block.numbered_list_item.rich_text);
|
|
80
72
|
const index = options.listIndex ?? 1;
|
|
81
73
|
let result = `${indent}${index}. ${text}`;
|
|
82
74
|
// 子ブロックがある場合
|
|
83
|
-
if (block.has_children && options.fetchChildren
|
|
75
|
+
if (block.has_children && options.fetchChildren) {
|
|
84
76
|
const children = await options.fetchChildren(block.id);
|
|
85
77
|
const childMarkdown = await blocksToMarkdown(children, {
|
|
86
78
|
...options,
|
|
@@ -93,15 +85,15 @@ async function convertBlock(block, options = {}) {
|
|
|
93
85
|
return result;
|
|
94
86
|
}
|
|
95
87
|
case 'to_do': {
|
|
96
|
-
const text = richTextToMarkdown(
|
|
97
|
-
const checked =
|
|
88
|
+
const text = richTextToMarkdown(block.to_do.rich_text);
|
|
89
|
+
const checked = block.to_do.checked ? 'x' : ' ';
|
|
98
90
|
return `${indent}- [${checked}] ${text}`;
|
|
99
91
|
}
|
|
100
92
|
case 'toggle': {
|
|
101
|
-
const text = richTextToMarkdown(
|
|
93
|
+
const text = richTextToMarkdown(block.toggle.rich_text);
|
|
102
94
|
let result = `${indent}<details>\n${indent}<summary>${text}</summary>\n`;
|
|
103
95
|
// 子ブロックがある場合
|
|
104
|
-
if (block.has_children && options.fetchChildren
|
|
96
|
+
if (block.has_children && options.fetchChildren) {
|
|
105
97
|
const children = await options.fetchChildren(block.id);
|
|
106
98
|
const childMarkdown = await blocksToMarkdown(children, {
|
|
107
99
|
...options,
|
|
@@ -115,11 +107,9 @@ async function convertBlock(block, options = {}) {
|
|
|
115
107
|
return result;
|
|
116
108
|
}
|
|
117
109
|
case 'code': {
|
|
118
|
-
const text = richTextToMarkdown(
|
|
119
|
-
const language =
|
|
120
|
-
const caption =
|
|
121
|
-
? richTextToMarkdown(blockData.caption)
|
|
122
|
-
: '';
|
|
110
|
+
const text = richTextToMarkdown(block.code.rich_text);
|
|
111
|
+
const language = block.code.language || '';
|
|
112
|
+
const caption = block.code.caption ? richTextToMarkdown(block.code.caption) : '';
|
|
123
113
|
let result = `${indent}\`\`\`${language}\n${text}\n${indent}\`\`\``;
|
|
124
114
|
if (caption) {
|
|
125
115
|
result += `\n${indent}*${caption}*`;
|
|
@@ -127,14 +117,14 @@ async function convertBlock(block, options = {}) {
|
|
|
127
117
|
return result;
|
|
128
118
|
}
|
|
129
119
|
case 'quote': {
|
|
130
|
-
const text = richTextToMarkdown(
|
|
120
|
+
const text = richTextToMarkdown(block.quote.rich_text);
|
|
131
121
|
// 複数行の場合は各行に > を付ける
|
|
132
122
|
const lines = text.split('\n');
|
|
133
123
|
return lines.map((line) => `${indent}> ${line}`).join('\n');
|
|
134
124
|
}
|
|
135
125
|
case 'callout': {
|
|
136
|
-
const text = richTextToMarkdown(
|
|
137
|
-
const icon = extractIconText(
|
|
126
|
+
const text = richTextToMarkdown(block.callout.rich_text);
|
|
127
|
+
const icon = extractIconText(block.callout.icon);
|
|
138
128
|
const prefix = icon ? `${icon} ` : '';
|
|
139
129
|
return `${indent}> ${prefix}**Note:** ${text}`;
|
|
140
130
|
}
|
|
@@ -142,50 +132,42 @@ async function convertBlock(block, options = {}) {
|
|
|
142
132
|
return `${indent}---`;
|
|
143
133
|
}
|
|
144
134
|
case 'bookmark': {
|
|
145
|
-
const url =
|
|
146
|
-
const caption =
|
|
147
|
-
? richTextToMarkdown(blockData.caption)
|
|
148
|
-
: '';
|
|
135
|
+
const url = block.bookmark.url || '';
|
|
136
|
+
const caption = block.bookmark.caption ? richTextToMarkdown(block.bookmark.caption) : '';
|
|
149
137
|
const displayText = caption || url;
|
|
150
138
|
return `${indent}[${displayText}](${url})`;
|
|
151
139
|
}
|
|
152
140
|
case 'image': {
|
|
153
|
-
const url = extractFileUrl(
|
|
154
|
-
const caption =
|
|
155
|
-
? richTextToMarkdown(blockData.caption)
|
|
156
|
-
: '';
|
|
141
|
+
const url = extractFileUrl(block.image);
|
|
142
|
+
const caption = block.image.caption ? richTextToMarkdown(block.image.caption) : '';
|
|
157
143
|
return `${indent}`;
|
|
158
144
|
}
|
|
159
145
|
case 'video': {
|
|
160
|
-
const url = extractFileUrl(
|
|
161
|
-
const caption =
|
|
162
|
-
? richTextToMarkdown(blockData.caption)
|
|
163
|
-
: '';
|
|
146
|
+
const url = extractFileUrl(block.video);
|
|
147
|
+
const caption = block.video.caption ? richTextToMarkdown(block.video.caption) : '';
|
|
164
148
|
const displayText = caption || 'Video';
|
|
165
149
|
return `${indent}[${displayText}](${url})`;
|
|
166
150
|
}
|
|
167
151
|
case 'audio': {
|
|
168
|
-
const url = extractFileUrl(
|
|
169
|
-
const
|
|
170
|
-
? richTextToMarkdown(blockData.caption)
|
|
171
|
-
: '';
|
|
172
|
-
const displayText = caption || 'Audio';
|
|
152
|
+
const url = extractFileUrl(block.audio);
|
|
153
|
+
const displayText = 'Audio';
|
|
173
154
|
return `${indent}[${displayText}](${url})`;
|
|
174
155
|
}
|
|
175
|
-
case 'file':
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
? richTextToMarkdown(blockData.caption)
|
|
180
|
-
: '';
|
|
181
|
-
const name = blockData?.name || caption || 'File';
|
|
156
|
+
case 'file': {
|
|
157
|
+
const url = extractFileUrl(block.file);
|
|
158
|
+
const caption = block.file.caption ? richTextToMarkdown(block.file.caption) : '';
|
|
159
|
+
const name = block.file.name || caption || 'File';
|
|
182
160
|
return `${indent}[${name}](${url})`;
|
|
183
161
|
}
|
|
162
|
+
case 'pdf': {
|
|
163
|
+
const url = extractFileUrl(block.pdf);
|
|
164
|
+
const caption = block.pdf.caption ? richTextToMarkdown(block.pdf.caption) : '';
|
|
165
|
+
const displayText = caption || 'PDF';
|
|
166
|
+
return `${indent}[${displayText}](${url})`;
|
|
167
|
+
}
|
|
184
168
|
case 'embed': {
|
|
185
|
-
const url =
|
|
186
|
-
const caption =
|
|
187
|
-
? richTextToMarkdown(blockData.caption)
|
|
188
|
-
: '';
|
|
169
|
+
const url = block.embed.url || '';
|
|
170
|
+
const caption = block.embed.caption ? richTextToMarkdown(block.embed.caption) : '';
|
|
189
171
|
const displayText = caption || 'Embed';
|
|
190
172
|
return `${indent}[${displayText}](${url})`;
|
|
191
173
|
}
|
|
@@ -193,24 +175,24 @@ async function convertBlock(block, options = {}) {
|
|
|
193
175
|
return `${indent}[TOC]`;
|
|
194
176
|
}
|
|
195
177
|
case 'equation': {
|
|
196
|
-
const expression =
|
|
178
|
+
const expression = block.equation.expression || '';
|
|
197
179
|
return `${indent}$$\n${expression}\n$$`;
|
|
198
180
|
}
|
|
199
181
|
case 'child_page': {
|
|
200
|
-
const title =
|
|
182
|
+
const title = block.child_page.title || 'Untitled';
|
|
201
183
|
return `${indent}📄 [${title}]`;
|
|
202
184
|
}
|
|
203
185
|
case 'child_database': {
|
|
204
|
-
const title =
|
|
186
|
+
const title = block.child_database.title || 'Untitled Database';
|
|
205
187
|
return `${indent}📊 [${title}]`;
|
|
206
188
|
}
|
|
207
189
|
case 'link_preview': {
|
|
208
|
-
const url =
|
|
190
|
+
const url = block.link_preview.url || '';
|
|
209
191
|
return `${indent}[${url}](${url})`;
|
|
210
192
|
}
|
|
211
193
|
case 'synced_block': {
|
|
212
194
|
// 同期ブロックの内容は子ブロックとして取得される
|
|
213
|
-
if (block.has_children && options.fetchChildren
|
|
195
|
+
if (block.has_children && options.fetchChildren) {
|
|
214
196
|
const children = await options.fetchChildren(block.id);
|
|
215
197
|
return await blocksToMarkdown(children, options);
|
|
216
198
|
}
|
|
@@ -218,7 +200,7 @@ async function convertBlock(block, options = {}) {
|
|
|
218
200
|
}
|
|
219
201
|
case 'column_list': {
|
|
220
202
|
// カラムリストは子ブロック(column)として処理
|
|
221
|
-
if (block.has_children && options.fetchChildren
|
|
203
|
+
if (block.has_children && options.fetchChildren) {
|
|
222
204
|
const children = await options.fetchChildren(block.id);
|
|
223
205
|
const columnContents = [];
|
|
224
206
|
for (const column of children) {
|
|
@@ -241,15 +223,14 @@ async function convertBlock(block, options = {}) {
|
|
|
241
223
|
}
|
|
242
224
|
case 'table': {
|
|
243
225
|
// テーブルは子ブロック(table_row)として処理
|
|
244
|
-
if (block.has_children && options.fetchChildren
|
|
226
|
+
if (block.has_children && options.fetchChildren) {
|
|
245
227
|
const children = await options.fetchChildren(block.id);
|
|
246
228
|
const rows = [];
|
|
247
|
-
const hasColumnHeader =
|
|
229
|
+
const hasColumnHeader = block.table.has_column_header;
|
|
248
230
|
for (let i = 0; i < children.length; i++) {
|
|
249
231
|
const row = children[i];
|
|
250
232
|
if (row.type === 'table_row') {
|
|
251
|
-
const
|
|
252
|
-
const cells = rowData?.cells || [];
|
|
233
|
+
const cells = row.table_row.cells || [];
|
|
253
234
|
const cellTexts = cells.map((cell) => richTextToMarkdown(cell));
|
|
254
235
|
rows.push(`${indent}| ${cellTexts.join(' | ')} |`);
|
|
255
236
|
// ヘッダー行の後にセパレーターを追加
|
|
@@ -274,6 +255,16 @@ async function convertBlock(block, options = {}) {
|
|
|
274
255
|
// テンプレートブロックは非推奨
|
|
275
256
|
return `${indent}<!-- Template block -->`;
|
|
276
257
|
}
|
|
258
|
+
case 'link_to_page': {
|
|
259
|
+
const linkTo = block.link_to_page;
|
|
260
|
+
if (linkTo.type === 'page_id') {
|
|
261
|
+
return `${indent}[Link to page](${linkTo.page_id})`;
|
|
262
|
+
}
|
|
263
|
+
if (linkTo.type === 'database_id') {
|
|
264
|
+
return `${indent}[Link to database](${linkTo.database_id})`;
|
|
265
|
+
}
|
|
266
|
+
return `${indent}<!-- Link to page -->`;
|
|
267
|
+
}
|
|
277
268
|
default: {
|
|
278
269
|
// 未対応ブロックタイプ
|
|
279
270
|
return `${indent}<!-- Unsupported block type: ${block.type} -->`;
|
|
@@ -327,66 +318,65 @@ export function blocksToMarkdownSync(blocks) {
|
|
|
327
318
|
let numberedListIndex = 1;
|
|
328
319
|
for (const block of blocks) {
|
|
329
320
|
const indent = '';
|
|
330
|
-
const blockData = block[block.type];
|
|
331
321
|
let markdown = '';
|
|
332
322
|
switch (block.type) {
|
|
333
323
|
case 'paragraph': {
|
|
334
|
-
const text = richTextToMarkdown(
|
|
324
|
+
const text = richTextToMarkdown(block.paragraph.rich_text);
|
|
335
325
|
markdown = text ? `${indent}${text}` : '';
|
|
336
326
|
break;
|
|
337
327
|
}
|
|
338
328
|
case 'heading_1': {
|
|
339
|
-
const text = richTextToMarkdown(
|
|
329
|
+
const text = richTextToMarkdown(block.heading_1.rich_text);
|
|
340
330
|
markdown = `${indent}# ${text}`;
|
|
341
331
|
break;
|
|
342
332
|
}
|
|
343
333
|
case 'heading_2': {
|
|
344
|
-
const text = richTextToMarkdown(
|
|
334
|
+
const text = richTextToMarkdown(block.heading_2.rich_text);
|
|
345
335
|
markdown = `${indent}## ${text}`;
|
|
346
336
|
break;
|
|
347
337
|
}
|
|
348
338
|
case 'heading_3': {
|
|
349
|
-
const text = richTextToMarkdown(
|
|
339
|
+
const text = richTextToMarkdown(block.heading_3.rich_text);
|
|
350
340
|
markdown = `${indent}### ${text}`;
|
|
351
341
|
break;
|
|
352
342
|
}
|
|
353
343
|
case 'bulleted_list_item': {
|
|
354
|
-
const text = richTextToMarkdown(
|
|
344
|
+
const text = richTextToMarkdown(block.bulleted_list_item.rich_text);
|
|
355
345
|
markdown = `${indent}- ${text}`;
|
|
356
346
|
break;
|
|
357
347
|
}
|
|
358
348
|
case 'numbered_list_item': {
|
|
359
|
-
const text = richTextToMarkdown(
|
|
349
|
+
const text = richTextToMarkdown(block.numbered_list_item.rich_text);
|
|
360
350
|
markdown = `${indent}${numberedListIndex}. ${text}`;
|
|
361
351
|
numberedListIndex++;
|
|
362
352
|
break;
|
|
363
353
|
}
|
|
364
354
|
case 'to_do': {
|
|
365
|
-
const text = richTextToMarkdown(
|
|
366
|
-
const checked =
|
|
355
|
+
const text = richTextToMarkdown(block.to_do.rich_text);
|
|
356
|
+
const checked = block.to_do.checked ? 'x' : ' ';
|
|
367
357
|
markdown = `${indent}- [${checked}] ${text}`;
|
|
368
358
|
break;
|
|
369
359
|
}
|
|
370
360
|
case 'toggle': {
|
|
371
|
-
const text = richTextToMarkdown(
|
|
361
|
+
const text = richTextToMarkdown(block.toggle.rich_text);
|
|
372
362
|
markdown = `${indent}<details>\n${indent}<summary>${text}</summary>\n${indent}</details>`;
|
|
373
363
|
break;
|
|
374
364
|
}
|
|
375
365
|
case 'code': {
|
|
376
|
-
const text = richTextToMarkdown(
|
|
377
|
-
const language =
|
|
366
|
+
const text = richTextToMarkdown(block.code.rich_text);
|
|
367
|
+
const language = block.code.language || '';
|
|
378
368
|
markdown = `${indent}\`\`\`${language}\n${text}\n${indent}\`\`\``;
|
|
379
369
|
break;
|
|
380
370
|
}
|
|
381
371
|
case 'quote': {
|
|
382
|
-
const text = richTextToMarkdown(
|
|
383
|
-
const
|
|
384
|
-
markdown =
|
|
372
|
+
const text = richTextToMarkdown(block.quote.rich_text);
|
|
373
|
+
const quoteLines = text.split('\n');
|
|
374
|
+
markdown = quoteLines.map((line) => `${indent}> ${line}`).join('\n');
|
|
385
375
|
break;
|
|
386
376
|
}
|
|
387
377
|
case 'callout': {
|
|
388
|
-
const text = richTextToMarkdown(
|
|
389
|
-
const icon = extractIconText(
|
|
378
|
+
const text = richTextToMarkdown(block.callout.rich_text);
|
|
379
|
+
const icon = extractIconText(block.callout.icon);
|
|
390
380
|
const prefix = icon ? `${icon} ` : '';
|
|
391
381
|
markdown = `${indent}> ${prefix}**Note:** ${text}`;
|
|
392
382
|
break;
|
|
@@ -396,47 +386,43 @@ export function blocksToMarkdownSync(blocks) {
|
|
|
396
386
|
break;
|
|
397
387
|
}
|
|
398
388
|
case 'bookmark': {
|
|
399
|
-
const url =
|
|
400
|
-
const caption =
|
|
401
|
-
? richTextToMarkdown(blockData.caption)
|
|
402
|
-
: '';
|
|
389
|
+
const url = block.bookmark.url || '';
|
|
390
|
+
const caption = block.bookmark.caption ? richTextToMarkdown(block.bookmark.caption) : '';
|
|
403
391
|
const displayText = caption || url;
|
|
404
392
|
markdown = `${indent}[${displayText}](${url})`;
|
|
405
393
|
break;
|
|
406
394
|
}
|
|
407
395
|
case 'image': {
|
|
408
|
-
const url = extractFileUrl(
|
|
409
|
-
const caption =
|
|
410
|
-
? richTextToMarkdown(blockData.caption)
|
|
411
|
-
: '';
|
|
396
|
+
const url = extractFileUrl(block.image);
|
|
397
|
+
const caption = block.image.caption ? richTextToMarkdown(block.image.caption) : '';
|
|
412
398
|
markdown = `${indent}`;
|
|
413
399
|
break;
|
|
414
400
|
}
|
|
415
401
|
case 'video':
|
|
416
402
|
case 'audio': {
|
|
403
|
+
const blockData = block.type === 'video' ? block.video : block.audio;
|
|
417
404
|
const url = extractFileUrl(blockData);
|
|
418
|
-
const
|
|
419
|
-
? richTextToMarkdown(blockData.caption)
|
|
420
|
-
: '';
|
|
421
|
-
const displayText = caption || (block.type === 'video' ? 'Video' : 'Audio');
|
|
405
|
+
const displayText = block.type === 'video' ? 'Video' : 'Audio';
|
|
422
406
|
markdown = `${indent}[${displayText}](${url})`;
|
|
423
407
|
break;
|
|
424
408
|
}
|
|
425
|
-
case 'file':
|
|
426
|
-
|
|
427
|
-
const
|
|
428
|
-
const
|
|
429
|
-
? richTextToMarkdown(blockData.caption)
|
|
430
|
-
: '';
|
|
431
|
-
const name = blockData?.name || caption || 'File';
|
|
409
|
+
case 'file': {
|
|
410
|
+
const url = extractFileUrl(block.file);
|
|
411
|
+
const caption = block.file.caption ? richTextToMarkdown(block.file.caption) : '';
|
|
412
|
+
const name = block.file.name || caption || 'File';
|
|
432
413
|
markdown = `${indent}[${name}](${url})`;
|
|
433
414
|
break;
|
|
434
415
|
}
|
|
416
|
+
case 'pdf': {
|
|
417
|
+
const url = extractFileUrl(block.pdf);
|
|
418
|
+
const caption = block.pdf.caption ? richTextToMarkdown(block.pdf.caption) : '';
|
|
419
|
+
const displayText = caption || 'PDF';
|
|
420
|
+
markdown = `${indent}[${displayText}](${url})`;
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
435
423
|
case 'embed': {
|
|
436
|
-
const url =
|
|
437
|
-
const caption =
|
|
438
|
-
? richTextToMarkdown(blockData.caption)
|
|
439
|
-
: '';
|
|
424
|
+
const url = block.embed.url || '';
|
|
425
|
+
const caption = block.embed.caption ? richTextToMarkdown(block.embed.caption) : '';
|
|
440
426
|
const displayText = caption || 'Embed';
|
|
441
427
|
markdown = `${indent}[${displayText}](${url})`;
|
|
442
428
|
break;
|
|
@@ -446,29 +432,40 @@ export function blocksToMarkdownSync(blocks) {
|
|
|
446
432
|
break;
|
|
447
433
|
}
|
|
448
434
|
case 'equation': {
|
|
449
|
-
const expression =
|
|
435
|
+
const expression = block.equation.expression || '';
|
|
450
436
|
markdown = `${indent}$$\n${expression}\n$$`;
|
|
451
437
|
break;
|
|
452
438
|
}
|
|
453
439
|
case 'child_page': {
|
|
454
|
-
const title =
|
|
440
|
+
const title = block.child_page.title || 'Untitled';
|
|
455
441
|
markdown = `${indent}📄 [${title}]`;
|
|
456
442
|
break;
|
|
457
443
|
}
|
|
458
444
|
case 'child_database': {
|
|
459
|
-
const title =
|
|
445
|
+
const title = block.child_database.title || 'Untitled Database';
|
|
460
446
|
markdown = `${indent}📊 [${title}]`;
|
|
461
447
|
break;
|
|
462
448
|
}
|
|
463
449
|
case 'link_preview': {
|
|
464
|
-
const url =
|
|
450
|
+
const url = block.link_preview.url || '';
|
|
465
451
|
markdown = `${indent}[${url}](${url})`;
|
|
466
452
|
break;
|
|
467
453
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
454
|
+
case 'link_to_page': {
|
|
455
|
+
const linkTo = block.link_to_page;
|
|
456
|
+
if (linkTo.type === 'page_id') {
|
|
457
|
+
markdown = `${indent}[Link to page](${linkTo.page_id})`;
|
|
471
458
|
}
|
|
459
|
+
else if (linkTo.type === 'database_id') {
|
|
460
|
+
markdown = `${indent}[Link to database](${linkTo.database_id})`;
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
markdown = `${indent}<!-- Link to page -->`;
|
|
464
|
+
}
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
default: {
|
|
468
|
+
markdown = `${indent}<!-- Unsupported block type: ${block.type} -->`;
|
|
472
469
|
break;
|
|
473
470
|
}
|
|
474
471
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Notion APIから取得したデータをマークダウンやシンプルな形式に変換する機能を提供
|
|
5
5
|
*/
|
|
6
|
-
export { blocksToMarkdown, blocksToMarkdownSync, type ConvertOptions
|
|
6
|
+
export { blocksToMarkdown, blocksToMarkdownSync, type ConvertOptions } from './block-to-markdown.js';
|
|
7
7
|
export { markdownToBlocks, parseInlineMarkdown } from './markdown-to-blocks.js';
|
|
8
|
-
export { type
|
|
9
|
-
export {
|
|
8
|
+
export { type PropertyValue, pagePropertiesToObject, pagePropertiesToSimple, pagesToSimple, pageToSimple, type SimplePage, type SimpleProperty, } from './page-to-markdown.js';
|
|
9
|
+
export { richTextToMarkdown, richTextToPlain, } from './rich-text-to-markdown.js';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/converters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/converters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEpG,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAE/E,OAAO,EACL,KAAK,aAAa,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,kBAAkB,EAClB,eAAe,GAChB,MAAM,4BAA4B,CAAA"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Notion APIから取得したデータをマークダウンやシンプルな形式に変換する機能を提供
|
|
5
5
|
*/
|
|
6
6
|
// ブロック変換
|
|
7
|
-
export { blocksToMarkdown, blocksToMarkdownSync
|
|
7
|
+
export { blocksToMarkdown, blocksToMarkdownSync } from './block-to-markdown.js';
|
|
8
8
|
// Markdown→ブロック変換
|
|
9
9
|
export { markdownToBlocks, parseInlineMarkdown } from './markdown-to-blocks.js';
|
|
10
10
|
// ページプロパティ変換
|
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markdown文字列をNotionブロック配列に変換するモジュール
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
4
|
+
import type { BlockObjectRequest } from '../notion-client.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* RichTextリクエストの型(SDK内部型に準拠)
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
type:
|
|
10
|
-
|
|
8
|
+
interface RichTextRequest {
|
|
9
|
+
type: 'text';
|
|
10
|
+
text: {
|
|
11
|
+
content: string;
|
|
12
|
+
link?: {
|
|
13
|
+
url: string;
|
|
14
|
+
} | null;
|
|
15
|
+
};
|
|
16
|
+
annotations?: {
|
|
17
|
+
bold?: boolean;
|
|
18
|
+
italic?: boolean;
|
|
19
|
+
strikethrough?: boolean;
|
|
20
|
+
underline?: boolean;
|
|
21
|
+
code?: boolean;
|
|
22
|
+
color?: string;
|
|
23
|
+
};
|
|
11
24
|
}
|
|
12
25
|
/**
|
|
13
26
|
* インラインMarkdown記法をRichText配列に変換
|
|
14
27
|
* サポート: **bold**, *italic*, ~~strike~~, `code`, [text](url)
|
|
15
28
|
*/
|
|
16
|
-
export declare function parseInlineMarkdown(text: string):
|
|
29
|
+
export declare function parseInlineMarkdown(text: string): RichTextRequest[];
|
|
17
30
|
/**
|
|
18
31
|
* Markdown文字列をNotionブロック配列に変換
|
|
19
32
|
*/
|
|
20
|
-
export declare function markdownToBlocks(markdown: string):
|
|
33
|
+
export declare function markdownToBlocks(markdown: string): BlockObjectRequest[];
|
|
34
|
+
export {};
|
|
21
35
|
//# sourceMappingURL=markdown-to-blocks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-to-blocks.d.ts","sourceRoot":"","sources":["../../../src/converters/markdown-to-blocks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"markdown-to-blocks.d.ts","sourceRoot":"","sources":["../../../src/converters/markdown-to-blocks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAO7D;;GAEG;AACH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAC9B,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CA8HnE;AAmBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA8LvE"}
|
|
@@ -236,6 +236,62 @@ export function markdownToBlocks(markdown) {
|
|
|
236
236
|
i++;
|
|
237
237
|
continue;
|
|
238
238
|
}
|
|
239
|
+
// テーブル: | col1 | col2 | ... |
|
|
240
|
+
// テーブル行は | で始まり | で終わる
|
|
241
|
+
if (line.trim().startsWith('|') && line.trim().endsWith('|')) {
|
|
242
|
+
const tableRows = [];
|
|
243
|
+
let hasHeaderSeparator = false;
|
|
244
|
+
let headerSeparatorIndex = -1;
|
|
245
|
+
// テーブル行を収集
|
|
246
|
+
while (i < lines.length) {
|
|
247
|
+
const currentLine = lines[i].trim();
|
|
248
|
+
if (!currentLine.startsWith('|') || !currentLine.endsWith('|')) {
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
// セパレーター行の検出: | --- | --- | or |:---|:---| etc.
|
|
252
|
+
if (/^\|[\s:]*-{3,}[\s:]*\|/.test(currentLine) &&
|
|
253
|
+
/\|[\s:]*-{3,}[\s:]*\|$/.test(currentLine)) {
|
|
254
|
+
// すべてのセルがセパレーターパターンかチェック
|
|
255
|
+
const separatorCells = currentLine.slice(1, -1).split('|');
|
|
256
|
+
const isSeparator = separatorCells.every((cell) => /^[\s:]*-{3,}[\s:]*$/.test(cell));
|
|
257
|
+
if (isSeparator) {
|
|
258
|
+
hasHeaderSeparator = true;
|
|
259
|
+
headerSeparatorIndex = tableRows.length;
|
|
260
|
+
i++;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// セルを抽出 (先頭と末尾の | を除去してから分割)
|
|
265
|
+
const cells = currentLine
|
|
266
|
+
.slice(1, -1)
|
|
267
|
+
.split('|')
|
|
268
|
+
.map((cell) => cell.trim());
|
|
269
|
+
tableRows.push(cells);
|
|
270
|
+
i++;
|
|
271
|
+
}
|
|
272
|
+
// テーブルブロックを生成
|
|
273
|
+
if (tableRows.length > 0) {
|
|
274
|
+
// 列数を最初の行から決定
|
|
275
|
+
const tableWidth = tableRows[0].length;
|
|
276
|
+
// テーブルブロックを作成
|
|
277
|
+
const tableBlock = {
|
|
278
|
+
type: 'table',
|
|
279
|
+
table: {
|
|
280
|
+
table_width: tableWidth,
|
|
281
|
+
has_column_header: hasHeaderSeparator && headerSeparatorIndex === 1,
|
|
282
|
+
has_row_header: false,
|
|
283
|
+
children: tableRows.map((row) => ({
|
|
284
|
+
type: 'table_row',
|
|
285
|
+
table_row: {
|
|
286
|
+
cells: row.map((cell) => parseInlineMarkdown(cell)),
|
|
287
|
+
},
|
|
288
|
+
})),
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
blocks.push(tableBlock);
|
|
292
|
+
}
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
239
295
|
// デフォルト: 段落
|
|
240
296
|
blocks.push(createTextBlock('paragraph', line));
|
|
241
297
|
i++;
|