@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.
Files changed (135) hide show
  1. package/README.ja.md +1 -0
  2. package/README.md +20 -2
  3. package/dist/src/converters/__tests__/block-to-markdown.test.js +482 -111
  4. package/dist/src/converters/__tests__/markdown-to-blocks.test.js +116 -13
  5. package/dist/src/converters/__tests__/page-to-markdown.test.js +83 -70
  6. package/dist/src/converters/__tests__/rich-text-to-markdown.test.js +23 -26
  7. package/dist/src/converters/block-to-markdown.d.ts +4 -13
  8. package/dist/src/converters/block-to-markdown.d.ts.map +1 -1
  9. package/dist/src/converters/block-to-markdown.js +117 -120
  10. package/dist/src/converters/index.d.ts +3 -3
  11. package/dist/src/converters/index.d.ts.map +1 -1
  12. package/dist/src/converters/index.js +1 -1
  13. package/dist/src/converters/markdown-to-blocks.d.ts +21 -7
  14. package/dist/src/converters/markdown-to-blocks.d.ts.map +1 -1
  15. package/dist/src/converters/markdown-to-blocks.js +56 -0
  16. package/dist/src/converters/page-to-markdown.d.ts +5 -20
  17. package/dist/src/converters/page-to-markdown.d.ts.map +1 -1
  18. package/dist/src/converters/page-to-markdown.js +47 -37
  19. package/dist/src/converters/rich-text-to-markdown.d.ts +3 -47
  20. package/dist/src/converters/rich-text-to-markdown.d.ts.map +1 -1
  21. package/dist/src/converters/rich-text-to-markdown.js +15 -14
  22. package/dist/src/notion-client.d.ts +5 -177
  23. package/dist/src/notion-client.d.ts.map +1 -1
  24. package/dist/src/notion-client.js +6 -172
  25. package/dist/src/schemas/descriptions/examples.d.ts +14 -0
  26. package/dist/src/schemas/descriptions/examples.d.ts.map +1 -0
  27. package/dist/src/schemas/descriptions/examples.js +87 -0
  28. package/dist/src/schemas/descriptions/fields.d.ts +146 -0
  29. package/dist/src/schemas/descriptions/fields.d.ts.map +1 -0
  30. package/dist/src/schemas/descriptions/fields.js +184 -0
  31. package/dist/src/schemas/descriptions/index.d.ts +3 -0
  32. package/dist/src/schemas/descriptions/index.d.ts.map +1 -0
  33. package/dist/src/schemas/descriptions/index.js +2 -0
  34. package/dist/src/schemas/index.d.ts +1 -5
  35. package/dist/src/schemas/index.d.ts.map +1 -1
  36. package/dist/src/schemas/index.js +2 -10
  37. package/dist/src/tools/__tests__/context-size.test.d.ts +2 -0
  38. package/dist/src/tools/__tests__/context-size.test.d.ts.map +1 -0
  39. package/dist/src/tools/__tests__/context-size.test.js +143 -0
  40. package/dist/src/tools/__tests__/error-handler.test.d.ts +2 -0
  41. package/dist/src/tools/__tests__/error-handler.test.d.ts.map +1 -0
  42. package/dist/src/tools/__tests__/error-handler.test.js +125 -0
  43. package/dist/src/tools/append-block-children.d.ts.map +1 -1
  44. package/dist/src/tools/append-block-children.js +8 -5
  45. package/dist/src/tools/append-blocks-simple.d.ts.map +1 -1
  46. package/dist/src/tools/append-blocks-simple.js +9 -13
  47. package/dist/src/tools/archive-database.d.ts.map +1 -1
  48. package/dist/src/tools/archive-database.js +4 -4
  49. package/dist/src/tools/archive-page.d.ts.map +1 -1
  50. package/dist/src/tools/archive-page.js +3 -3
  51. package/dist/src/tools/create-comment-simple.d.ts +4 -0
  52. package/dist/src/tools/create-comment-simple.d.ts.map +1 -0
  53. package/dist/src/tools/create-comment-simple.js +51 -0
  54. package/dist/src/tools/create-comment.d.ts.map +1 -1
  55. package/dist/src/tools/create-comment.js +28 -8
  56. package/dist/src/tools/create-database.d.ts.map +1 -1
  57. package/dist/src/tools/create-database.js +19 -25
  58. package/dist/src/tools/create-page-simple.d.ts +1 -1
  59. package/dist/src/tools/create-page-simple.d.ts.map +1 -1
  60. package/dist/src/tools/create-page-simple.js +41 -26
  61. package/dist/src/tools/create-page.d.ts.map +1 -1
  62. package/dist/src/tools/create-page.js +11 -7
  63. package/dist/src/tools/delete-block.d.ts.map +1 -1
  64. package/dist/src/tools/delete-block.js +2 -1
  65. package/dist/src/tools/get-block-children.d.ts +1 -1
  66. package/dist/src/tools/get-block-children.d.ts.map +1 -1
  67. package/dist/src/tools/get-block-children.js +13 -27
  68. package/dist/src/tools/index.d.ts +4 -3
  69. package/dist/src/tools/index.d.ts.map +1 -1
  70. package/dist/src/tools/index.js +5 -3
  71. package/dist/src/tools/list-comments.d.ts +1 -1
  72. package/dist/src/tools/list-comments.d.ts.map +1 -1
  73. package/dist/src/tools/list-comments.js +11 -10
  74. package/dist/src/tools/list-users.d.ts.map +1 -1
  75. package/dist/src/tools/list-users.js +4 -3
  76. package/dist/src/tools/move-page.d.ts.map +1 -1
  77. package/dist/src/tools/move-page.js +5 -4
  78. package/dist/src/tools/query-data-source.d.ts +1 -1
  79. package/dist/src/tools/query-data-source.d.ts.map +1 -1
  80. package/dist/src/tools/query-data-source.js +23 -24
  81. package/dist/src/tools/retrieve-block.d.ts +1 -1
  82. package/dist/src/tools/retrieve-block.d.ts.map +1 -1
  83. package/dist/src/tools/retrieve-block.js +13 -10
  84. package/dist/src/tools/retrieve-bot-user.js +1 -1
  85. package/dist/src/tools/retrieve-data-source.d.ts +1 -1
  86. package/dist/src/tools/retrieve-data-source.d.ts.map +1 -1
  87. package/dist/src/tools/retrieve-data-source.js +15 -11
  88. package/dist/src/tools/retrieve-database.d.ts +1 -1
  89. package/dist/src/tools/retrieve-database.d.ts.map +1 -1
  90. package/dist/src/tools/retrieve-database.js +11 -6
  91. package/dist/src/tools/retrieve-page-property.d.ts.map +1 -1
  92. package/dist/src/tools/retrieve-page-property.js +7 -7
  93. package/dist/src/tools/retrieve-page.d.ts +1 -1
  94. package/dist/src/tools/retrieve-page.d.ts.map +1 -1
  95. package/dist/src/tools/retrieve-page.js +15 -20
  96. package/dist/src/tools/retrieve-user.d.ts.map +1 -1
  97. package/dist/src/tools/retrieve-user.js +2 -1
  98. package/dist/src/tools/search.d.ts.map +1 -1
  99. package/dist/src/tools/search.js +10 -17
  100. package/dist/src/tools/update-block-simple.d.ts +1 -1
  101. package/dist/src/tools/update-block-simple.d.ts.map +1 -1
  102. package/dist/src/tools/update-block-simple.js +14 -4
  103. package/dist/src/tools/update-block.d.ts.map +1 -1
  104. package/dist/src/tools/update-block.js +8 -5
  105. package/dist/src/tools/update-data-source.d.ts.map +1 -1
  106. package/dist/src/tools/update-data-source.js +8 -8
  107. package/dist/src/tools/update-database.d.ts.map +1 -1
  108. package/dist/src/tools/update-database.js +22 -32
  109. package/dist/src/tools/update-page.d.ts.map +1 -1
  110. package/dist/src/tools/update-page.js +13 -8
  111. package/dist/src/utils/error-handler.d.ts +20 -0
  112. package/dist/src/utils/error-handler.d.ts.map +1 -1
  113. package/dist/src/utils/error-handler.js +63 -0
  114. package/dist/src/utils/index.d.ts +1 -1
  115. package/dist/src/utils/index.d.ts.map +1 -1
  116. package/dist/src/utils/index.js +1 -1
  117. package/package.json +2 -1
  118. package/dist/src/schemas/block.d.ts +0 -3787
  119. package/dist/src/schemas/block.d.ts.map +0 -1
  120. package/dist/src/schemas/block.js +0 -402
  121. package/dist/src/schemas/common.d.ts +0 -638
  122. package/dist/src/schemas/common.d.ts.map +0 -1
  123. package/dist/src/schemas/common.js +0 -163
  124. package/dist/src/schemas/database.d.ts +0 -687
  125. package/dist/src/schemas/database.d.ts.map +0 -1
  126. package/dist/src/schemas/database.js +0 -258
  127. package/dist/src/schemas/filter.d.ts +0 -611
  128. package/dist/src/schemas/filter.d.ts.map +0 -1
  129. package/dist/src/schemas/filter.js +0 -222
  130. package/dist/src/schemas/page.d.ts +0 -2607
  131. package/dist/src/schemas/page.d.ts.map +0 -1
  132. package/dist/src/schemas/page.js +0 -328
  133. package/dist/src/schemas/schemas.test.d.ts +0 -2
  134. package/dist/src/schemas/schemas.test.d.ts.map +0 -1
  135. 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' && fileObj.external?.url) {
11
+ if (fileObj.type === 'external') {
12
12
  return fileObj.external.url;
13
13
  }
14
- if (fileObj.type === 'file' && fileObj.file?.url) {
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
- if (icon.type === 'emoji' && icon.emoji) {
31
- return icon.emoji;
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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 && block.id) {
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(blockData?.rich_text);
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 && block.id) {
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(blockData?.rich_text);
97
- const checked = blockData?.checked ? 'x' : ' ';
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(blockData?.rich_text);
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 && block.id) {
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(blockData?.rich_text);
119
- const language = blockData?.language || '';
120
- const caption = blockData?.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(blockData?.rich_text);
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(blockData?.rich_text);
137
- const icon = extractIconText(blockData?.icon);
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 = blockData?.url || '';
146
- const caption = blockData?.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(blockData);
154
- const caption = blockData?.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}![${caption}](${url})`;
158
144
  }
159
145
  case 'video': {
160
- const url = extractFileUrl(blockData);
161
- const caption = blockData?.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(blockData);
169
- const caption = blockData?.caption
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
- case 'pdf': {
177
- const url = extractFileUrl(blockData);
178
- const caption = blockData?.caption
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 = blockData?.url || '';
186
- const caption = blockData?.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 = blockData?.expression || '';
178
+ const expression = block.equation.expression || '';
197
179
  return `${indent}$$\n${expression}\n$$`;
198
180
  }
199
181
  case 'child_page': {
200
- const title = blockData?.title || 'Untitled';
182
+ const title = block.child_page.title || 'Untitled';
201
183
  return `${indent}📄 [${title}]`;
202
184
  }
203
185
  case 'child_database': {
204
- const title = blockData?.title || 'Untitled Database';
186
+ const title = block.child_database.title || 'Untitled Database';
205
187
  return `${indent}📊 [${title}]`;
206
188
  }
207
189
  case 'link_preview': {
208
- const url = blockData?.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 && block.id) {
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 && block.id) {
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 && block.id) {
226
+ if (block.has_children && options.fetchChildren) {
245
227
  const children = await options.fetchChildren(block.id);
246
228
  const rows = [];
247
- const hasColumnHeader = blockData?.has_column_header;
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 rowData = row.table_row;
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
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(blockData?.rich_text);
366
- const checked = blockData?.checked ? 'x' : ' ';
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(blockData?.rich_text);
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(blockData?.rich_text);
377
- const language = blockData?.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(blockData?.rich_text);
383
- const lines = text.split('\n');
384
- markdown = lines.map((line) => `${indent}> ${line}`).join('\n');
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(blockData?.rich_text);
389
- const icon = extractIconText(blockData?.icon);
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 = blockData?.url || '';
400
- const caption = blockData?.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(blockData);
409
- const caption = blockData?.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}![${caption}](${url})`;
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 caption = blockData?.caption
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
- case 'pdf': {
427
- const url = extractFileUrl(blockData);
428
- const caption = blockData?.caption
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 = blockData?.url || '';
437
- const caption = blockData?.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 = blockData?.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 = blockData?.title || 'Untitled';
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 = blockData?.title || 'Untitled Database';
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 = blockData?.url || '';
450
+ const url = block.link_preview.url || '';
465
451
  markdown = `${indent}[${url}](${url})`;
466
452
  break;
467
453
  }
468
- default: {
469
- if (blockData) {
470
- markdown = `${indent}<!-- Unsupported block type: ${block.type} -->`;
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, type NotionBlock, } from './block-to-markdown.js';
6
+ export { blocksToMarkdown, blocksToMarkdownSync, type ConvertOptions } from './block-to-markdown.js';
7
7
  export { markdownToBlocks, parseInlineMarkdown } from './markdown-to-blocks.js';
8
- export { type NotionProperty, type PropertyValue, pagePropertiesToObject, pagePropertiesToSimple, pagesToSimple, pageToSimple, type SimplePage, type SimpleProperty, } from './page-to-markdown.js';
9
- export { type RichTextItem, richTextToMarkdown, richTextToPlain, } from './rich-text-to-markdown.js';
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,EACL,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAE/E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,KAAK,YAAY,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,4BAA4B,CAAA"}
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, } from './block-to-markdown.js';
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 { RichTextItem } from './rich-text-to-markdown.js';
4
+ import type { BlockObjectRequest } from '../notion-client.js';
5
5
  /**
6
- * Notionブロックの型定義(簡易版)
6
+ * RichTextリクエストの型(SDK内部型に準拠)
7
7
  */
8
- export interface NotionBlock {
9
- type: string;
10
- [key: string]: unknown;
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): RichTextItem[];
29
+ export declare function parseInlineMarkdown(text: string): RichTextRequest[];
17
30
  /**
18
31
  * Markdown文字列をNotionブロック配列に変換
19
32
  */
20
- export declare function markdownToBlocks(markdown: string): NotionBlock[];
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,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAO9D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CA8HhE;AAmBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CA8HhE"}
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++;