n8n-nodes-notion-advanced 1.2.13-beta → 1.2.15-beta
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/nodes → nodes}/NotionAdvanced/NotionAITool.node.d.ts +1 -0
- package/{dist/nodes → nodes}/NotionAdvanced/NotionAITool.node.js +196 -96
- package/package.json +69 -78
- package/LICENSE +0 -21
- package/README.md +0 -306
- package/dist/NotionAdvanced/notion.svg +0 -3
- package/dist/package.json +0 -69
- package/dist/tests/NotionAdvanced.test.d.ts +0 -15
- package/dist/tests/NotionAdvanced.test.js +0 -290
- /package/{dist/nodes → nodes}/NotionAdvanced/NotionAdvanced.node.d.ts +0 -0
- /package/{dist/nodes → nodes}/NotionAdvanced/NotionAdvanced.node.js +0 -0
- /package/{dist/nodes → nodes}/NotionAdvanced/NotionUtils.d.ts +0 -0
- /package/{dist/nodes → nodes}/NotionAdvanced/NotionUtils.js +0 -0
- /package/{dist/types → types}/NotionTypes.d.ts +0 -0
- /package/{dist/types → types}/NotionTypes.js +0 -0
@@ -48,6 +48,7 @@ export declare class NotionAITool implements INodeType {
|
|
48
48
|
static processXmlTags(content: string, blocks: IDataObject[]): string;
|
49
49
|
static cleanupRemainingHtml(content: string, placeholderPrefix?: string): string;
|
50
50
|
static processNestedHtmlInListItem(content: string): string;
|
51
|
+
static convertInlineHtmlToMarkdown(content: string): string;
|
51
52
|
static processNestedList(listContent: string, listType: 'bulleted_list_item' | 'numbered_list_item', blocks: IDataObject[]): void;
|
52
53
|
static getCalloutEmoji(type: string): string;
|
53
54
|
static getCalloutColor(type: string): string;
|
@@ -765,22 +765,37 @@ class NotionAITool {
|
|
765
765
|
replacements.set(child.id, childReplacement);
|
766
766
|
}
|
767
767
|
// Extract inner content (content between opening and closing tags)
|
768
|
-
let innerContent =
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
const
|
774
|
-
const
|
775
|
-
const
|
776
|
-
|
777
|
-
|
768
|
+
let innerContent = '';
|
769
|
+
try {
|
770
|
+
// More robust inner content extraction
|
771
|
+
const tagName = node.tagName.toLowerCase();
|
772
|
+
const openTagRegex = new RegExp(`^<${tagName}[^>]*>`, 'i');
|
773
|
+
const closeTagRegex = new RegExp(`</${tagName}>$`, 'i');
|
774
|
+
const openMatch = node.match.match(openTagRegex);
|
775
|
+
const closeMatch = node.match.match(closeTagRegex);
|
776
|
+
if (openMatch && closeMatch) {
|
777
|
+
const openTag = openMatch[0];
|
778
|
+
const closeTag = closeMatch[0];
|
779
|
+
const startIndex = openTag.length;
|
780
|
+
const endIndex = node.match.length - closeTag.length;
|
781
|
+
innerContent = node.match.substring(startIndex, endIndex);
|
782
|
+
}
|
783
|
+
else {
|
784
|
+
// Fallback for self-closing or malformed tags
|
785
|
+
innerContent = node.match.replace(/^<[^>]*>/, '').replace(/<\/[^>]*>$/, '');
|
786
|
+
}
|
778
787
|
// Replace child nodes in inner content with their processed content
|
779
788
|
for (const child of node.children) {
|
780
789
|
const childReplacement = replacements.get(child.id) || '';
|
781
|
-
|
790
|
+
if (childReplacement !== undefined && innerContent.includes(child.match)) {
|
791
|
+
innerContent = innerContent.replace(child.match, childReplacement);
|
792
|
+
}
|
782
793
|
}
|
783
794
|
}
|
795
|
+
catch (error) {
|
796
|
+
console.warn(`Error extracting inner content for ${node.tagName}:`, error);
|
797
|
+
innerContent = node.match;
|
798
|
+
}
|
784
799
|
// Process this node with updated inner content
|
785
800
|
try {
|
786
801
|
// Handle special list processors
|
@@ -1005,10 +1020,12 @@ class NotionAITool {
|
|
1005
1020
|
{
|
1006
1021
|
regex: /<p>(.*?)<\/p>/gis,
|
1007
1022
|
blockCreator: (content) => {
|
1023
|
+
// First convert HTML tags to markdown, then parse to rich text
|
1024
|
+
const markdownContent = NotionAITool.convertInlineHtmlToMarkdown(content.trim());
|
1008
1025
|
return {
|
1009
1026
|
type: 'paragraph',
|
1010
1027
|
paragraph: {
|
1011
|
-
rich_text: NotionAITool.parseBasicMarkdown(
|
1028
|
+
rich_text: NotionAITool.parseBasicMarkdown(markdownContent),
|
1012
1029
|
},
|
1013
1030
|
};
|
1014
1031
|
}
|
@@ -1065,10 +1082,12 @@ class NotionAITool {
|
|
1065
1082
|
regex: /<li\s*[^>]*>(.*?)<\/li>/gis,
|
1066
1083
|
blockCreator: (content) => {
|
1067
1084
|
if (content.trim()) {
|
1085
|
+
// Convert HTML to markdown first, then parse to rich text
|
1086
|
+
const markdownContent = NotionAITool.convertInlineHtmlToMarkdown(content.trim());
|
1068
1087
|
return {
|
1069
1088
|
type: 'bulleted_list_item',
|
1070
1089
|
bulleted_list_item: {
|
1071
|
-
rich_text: NotionAITool.parseBasicMarkdown(
|
1090
|
+
rich_text: NotionAITool.parseBasicMarkdown(markdownContent),
|
1072
1091
|
},
|
1073
1092
|
};
|
1074
1093
|
}
|
@@ -1185,14 +1204,27 @@ class NotionAITool {
|
|
1185
1204
|
let cleaned = content;
|
1186
1205
|
// Remove XML_BLOCK placeholder artifacts (support both old and new format)
|
1187
1206
|
if (placeholderPrefix) {
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1207
|
+
// More aggressive placeholder cleanup with multiple patterns
|
1208
|
+
const placeholderPatterns = [
|
1209
|
+
new RegExp(`${placeholderPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\d+__`, 'g'),
|
1210
|
+
new RegExp(`_${placeholderPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\d+_`, 'g'),
|
1211
|
+
new RegExp(`${placeholderPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\d+`, 'g')
|
1212
|
+
];
|
1213
|
+
placeholderPatterns.forEach(pattern => {
|
1214
|
+
cleaned = cleaned.replace(pattern, '');
|
1215
|
+
});
|
1195
1216
|
}
|
1217
|
+
// Comprehensive fallback cleanup for all possible placeholder formats
|
1218
|
+
const fallbackPatterns = [
|
1219
|
+
/__XML_BLOCK_\d+__/g,
|
1220
|
+
/__XML_[a-f0-9]{8}_\d+__/g,
|
1221
|
+
/_XML_[a-f0-9]{8}_\d+_/g,
|
1222
|
+
/__XML_[a-f0-9-]+_\d+__/g,
|
1223
|
+
/_XML_[a-f0-9-]+_\d+_/g
|
1224
|
+
];
|
1225
|
+
fallbackPatterns.forEach(pattern => {
|
1226
|
+
cleaned = cleaned.replace(pattern, '');
|
1227
|
+
});
|
1196
1228
|
// Remove common HTML tags that might be left behind
|
1197
1229
|
const htmlTagsToRemove = [
|
1198
1230
|
/<\/?ul\s*[^>]*>/gi,
|
@@ -1220,16 +1252,88 @@ class NotionAITool {
|
|
1220
1252
|
cleaned = cleaned.replace(/^\s*[\r\n]/gm, '');
|
1221
1253
|
// Remove multiple consecutive line breaks
|
1222
1254
|
cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
|
1223
|
-
// Remove lines that contain only XML_BLOCK artifacts
|
1224
|
-
|
1225
|
-
|
1255
|
+
// Remove lines that contain only XML_BLOCK artifacts (more patterns)
|
1256
|
+
const artifactPatterns = [
|
1257
|
+
/^.*__XML_BLOCK_\d+__.*$/gm,
|
1258
|
+
/^.*__XML_[a-f0-9]{8}_\d+__.*$/gm,
|
1259
|
+
/^.*_XML_[a-f0-9]{8}_\d+_.*$/gm,
|
1260
|
+
/^.*__XML_[a-f0-9-]+_\d+__.*$/gm,
|
1261
|
+
/^.*_XML_[a-f0-9-]+_\d+_.*$/gm
|
1262
|
+
];
|
1263
|
+
artifactPatterns.forEach(pattern => {
|
1264
|
+
cleaned = cleaned.replace(pattern, '');
|
1265
|
+
});
|
1266
|
+
// Final cleanup of any remaining isolated placeholder patterns
|
1267
|
+
cleaned = cleaned.replace(/\b_+XML_[a-f0-9-]+_\d+_*\b/g, '');
|
1268
|
+
cleaned = cleaned.replace(/\b_*XML_[a-f0-9-]+_\d+_+\b/g, '');
|
1226
1269
|
return cleaned.trim();
|
1227
1270
|
}
|
1228
1271
|
// Helper function to process nested HTML elements in list items
|
1229
1272
|
static processNestedHtmlInListItem(content) {
|
1273
|
+
let processed = content.trim();
|
1274
|
+
if (!processed)
|
1275
|
+
return '';
|
1276
|
+
try {
|
1277
|
+
// Handle multiple segments separated by HTML block elements
|
1278
|
+
const segments = [];
|
1279
|
+
// Split by block-level HTML elements like <p>, <div>, etc.
|
1280
|
+
const blockElements = /<(p|div|h[1-6]|blockquote)\s*[^>]*>.*?<\/\1>/gis;
|
1281
|
+
let lastIndex = 0;
|
1282
|
+
let match;
|
1283
|
+
const blockMatches = [];
|
1284
|
+
while ((match = blockElements.exec(processed)) !== null) {
|
1285
|
+
blockMatches.push({
|
1286
|
+
start: match.index,
|
1287
|
+
end: match.index + match[0].length,
|
1288
|
+
content: match[0],
|
1289
|
+
tag: match[1]
|
1290
|
+
});
|
1291
|
+
}
|
1292
|
+
// Sort matches by position
|
1293
|
+
blockMatches.sort((a, b) => a.start - b.start);
|
1294
|
+
// Process text segments between block elements
|
1295
|
+
blockMatches.forEach((blockMatch, index) => {
|
1296
|
+
// Add text before this block element
|
1297
|
+
if (blockMatch.start > lastIndex) {
|
1298
|
+
const beforeText = processed.substring(lastIndex, blockMatch.start).trim();
|
1299
|
+
if (beforeText) {
|
1300
|
+
segments.push(NotionAITool.convertInlineHtmlToMarkdown(beforeText));
|
1301
|
+
}
|
1302
|
+
}
|
1303
|
+
// Process content inside block element
|
1304
|
+
const innerContent = blockMatch.content.replace(new RegExp(`^<${blockMatch.tag}[^>]*>`, 'i'), '')
|
1305
|
+
.replace(new RegExp(`</${blockMatch.tag}>$`, 'i'), '')
|
1306
|
+
.trim();
|
1307
|
+
if (innerContent) {
|
1308
|
+
segments.push(NotionAITool.convertInlineHtmlToMarkdown(innerContent));
|
1309
|
+
}
|
1310
|
+
lastIndex = blockMatch.end;
|
1311
|
+
});
|
1312
|
+
// Add remaining text after last block element
|
1313
|
+
if (lastIndex < processed.length) {
|
1314
|
+
const remainingText = processed.substring(lastIndex).trim();
|
1315
|
+
if (remainingText) {
|
1316
|
+
segments.push(NotionAITool.convertInlineHtmlToMarkdown(remainingText));
|
1317
|
+
}
|
1318
|
+
}
|
1319
|
+
// If no block elements were found, process the whole content
|
1320
|
+
if (blockMatches.length === 0) {
|
1321
|
+
segments.push(NotionAITool.convertInlineHtmlToMarkdown(processed));
|
1322
|
+
}
|
1323
|
+
// Join segments with space and clean up
|
1324
|
+
const result = segments.filter(s => s.trim()).join(' ').trim();
|
1325
|
+
// Final cleanup of any remaining artifacts
|
1326
|
+
return result.replace(/\s+/g, ' ').trim();
|
1327
|
+
}
|
1328
|
+
catch (error) {
|
1329
|
+
console.warn('Error processing nested HTML in list item:', error);
|
1330
|
+
// Fallback: just remove HTML tags and return text
|
1331
|
+
return processed.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
|
1332
|
+
}
|
1333
|
+
}
|
1334
|
+
// Helper function to convert inline HTML to markdown
|
1335
|
+
static convertInlineHtmlToMarkdown(content) {
|
1230
1336
|
let processed = content;
|
1231
|
-
// First, remove wrapping <p> tags (common in nested content)
|
1232
|
-
processed = processed.replace(/^<p\s*[^>]*>(.*?)<\/p>$/gis, '$1');
|
1233
1337
|
// Convert HTML formatting tags to markdown equivalents
|
1234
1338
|
const htmlToMarkdown = [
|
1235
1339
|
{ regex: /<strong\s*[^>]*>(.*?)<\/strong>/gis, replacement: '**$1**' },
|
@@ -1249,9 +1353,7 @@ class NotionAITool {
|
|
1249
1353
|
});
|
1250
1354
|
// Remove any remaining HTML tags that we don't handle
|
1251
1355
|
const tagsToRemove = [
|
1252
|
-
/<\/?div\s*[^>]*>/gi,
|
1253
1356
|
/<\/?span\s*[^>]*>/gi,
|
1254
|
-
/<\/?p\s*[^>]*>/gi,
|
1255
1357
|
/<br\s*\/?>/gi,
|
1256
1358
|
];
|
1257
1359
|
tagsToRemove.forEach(regex => {
|
@@ -1263,56 +1365,64 @@ class NotionAITool {
|
|
1263
1365
|
}
|
1264
1366
|
// Helper function to process nested lists and flatten them for Notion
|
1265
1367
|
static processNestedList(listContent, listType, blocks) {
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1368
|
+
try {
|
1369
|
+
// More robust list item extraction using regex
|
1370
|
+
const liRegex = /<li[^>]*>([\s\S]*?)<\/li>/gi;
|
1371
|
+
let match;
|
1372
|
+
while ((match = liRegex.exec(listContent)) !== null) {
|
1373
|
+
let itemContent = match[1].trim();
|
1374
|
+
if (!itemContent)
|
1375
|
+
continue;
|
1376
|
+
// Check if this item contains nested lists
|
1377
|
+
const hasNestedList = /<[uo]l\s*[^>]*>/i.test(itemContent);
|
1378
|
+
if (hasNestedList) {
|
1379
|
+
// Split content into parts: before nested list, nested list, after nested list
|
1380
|
+
const parts = itemContent.split(/(<[uo]l\s*[^>]*>[\s\S]*?<\/[uo]l>)/i);
|
1381
|
+
// Process the main content (before nested list)
|
1382
|
+
const mainContent = parts[0] ? parts[0].trim() : '';
|
1383
|
+
if (mainContent) {
|
1384
|
+
const cleanContent = NotionAITool.processNestedHtmlInListItem(mainContent);
|
1385
|
+
if (cleanContent) {
|
1386
|
+
blocks.push({
|
1387
|
+
type: listType,
|
1388
|
+
[listType]: {
|
1389
|
+
rich_text: NotionAITool.parseBasicMarkdown(cleanContent),
|
1390
|
+
},
|
1391
|
+
});
|
1392
|
+
}
|
1393
|
+
}
|
1394
|
+
// Process nested lists
|
1395
|
+
for (let i = 1; i < parts.length; i += 2) {
|
1396
|
+
const nestedListHtml = parts[i];
|
1397
|
+
if (nestedListHtml) {
|
1398
|
+
const nestedListMatch = nestedListHtml.match(/<([uo]l)\s*[^>]*>([\s\S]*?)<\/\1>/i);
|
1399
|
+
if (nestedListMatch) {
|
1400
|
+
const [, nestedListTag, nestedContent] = nestedListMatch;
|
1401
|
+
const nestedListType = nestedListTag === 'ul' ? 'bulleted_list_item' : 'numbered_list_item';
|
1402
|
+
// Recursively process nested list
|
1403
|
+
NotionAITool.processNestedList(nestedContent, nestedListType, blocks);
|
1404
|
+
}
|
1405
|
+
}
|
1406
|
+
}
|
1407
|
+
// Process any content after nested lists
|
1408
|
+
if (parts.length > 2) {
|
1409
|
+
const afterContent = parts.slice(2).join('').trim();
|
1410
|
+
if (afterContent) {
|
1411
|
+
const cleanContent = NotionAITool.processNestedHtmlInListItem(afterContent);
|
1412
|
+
if (cleanContent) {
|
1413
|
+
blocks.push({
|
1414
|
+
type: listType,
|
1415
|
+
[listType]: {
|
1416
|
+
rich_text: NotionAITool.parseBasicMarkdown(cleanContent),
|
1417
|
+
},
|
1418
|
+
});
|
1419
|
+
}
|
1420
|
+
}
|
1293
1421
|
}
|
1294
|
-
searchPos = nextLiEnd + 5;
|
1295
1422
|
}
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
// Extract the full <li>...</li> content
|
1300
|
-
const fullItem = listContent.substring(liStart, liEnd + 5);
|
1301
|
-
items.push(fullItem);
|
1302
|
-
currentPos = liEnd + 5;
|
1303
|
-
}
|
1304
|
-
// Process each top-level item
|
1305
|
-
items.forEach(item => {
|
1306
|
-
// Remove the outer <li> tags
|
1307
|
-
let itemContent = item.replace(/^<li[^>]*>/, '').replace(/<\/li>$/, '').trim();
|
1308
|
-
// Check if this item contains nested lists
|
1309
|
-
const hasNestedList = /<[uo]l\s*[^>]*>/i.test(itemContent);
|
1310
|
-
if (hasNestedList) {
|
1311
|
-
// Extract the text before the nested list
|
1312
|
-
const beforeNestedList = itemContent.replace(/<[uo]l\s*[^>]*>.*$/is, '').trim();
|
1313
|
-
if (beforeNestedList) {
|
1314
|
-
// Clean up and add the main item
|
1315
|
-
const cleanContent = NotionAITool.processNestedHtmlInListItem(beforeNestedList);
|
1423
|
+
else {
|
1424
|
+
// Simple item without nested lists
|
1425
|
+
const cleanContent = NotionAITool.processNestedHtmlInListItem(itemContent);
|
1316
1426
|
if (cleanContent) {
|
1317
1427
|
blocks.push({
|
1318
1428
|
type: listType,
|
@@ -1322,28 +1432,18 @@ class NotionAITool {
|
|
1322
1432
|
});
|
1323
1433
|
}
|
1324
1434
|
}
|
1325
|
-
// Extract and process nested lists
|
1326
|
-
const nestedListMatch = itemContent.match(/<([uo]l)\s*[^>]*>(.*?)<\/\1>/is);
|
1327
|
-
if (nestedListMatch) {
|
1328
|
-
const [, nestedListTag, nestedContent] = nestedListMatch;
|
1329
|
-
const nestedListType = nestedListTag === 'ul' ? 'bulleted_list_item' : 'numbered_list_item';
|
1330
|
-
// Recursively process nested list
|
1331
|
-
NotionAITool.processNestedList(nestedContent, nestedListType, blocks);
|
1332
|
-
}
|
1333
|
-
}
|
1334
|
-
else {
|
1335
|
-
// Simple item without nested lists
|
1336
|
-
const cleanContent = NotionAITool.processNestedHtmlInListItem(itemContent);
|
1337
|
-
if (cleanContent) {
|
1338
|
-
blocks.push({
|
1339
|
-
type: listType,
|
1340
|
-
[listType]: {
|
1341
|
-
rich_text: NotionAITool.parseBasicMarkdown(cleanContent),
|
1342
|
-
},
|
1343
|
-
});
|
1344
|
-
}
|
1345
1435
|
}
|
1346
|
-
}
|
1436
|
+
}
|
1437
|
+
catch (error) {
|
1438
|
+
console.warn('Error processing nested list:', error);
|
1439
|
+
// Fallback: create a simple text block with the content
|
1440
|
+
blocks.push({
|
1441
|
+
type: 'paragraph',
|
1442
|
+
paragraph: {
|
1443
|
+
rich_text: [{ type: 'text', text: { content: 'Error processing list content' } }],
|
1444
|
+
},
|
1445
|
+
});
|
1446
|
+
}
|
1347
1447
|
}
|
1348
1448
|
// Helper function to get callout emoji based on type
|
1349
1449
|
static getCalloutEmoji(type) {
|
package/package.json
CHANGED
@@ -1,78 +1,69 @@
|
|
1
|
-
{
|
2
|
-
"name": "n8n-nodes-notion-advanced",
|
3
|
-
"version": "1.2.
|
4
|
-
"description": "Advanced n8n Notion nodes: Full-featured workflow node + AI Agent Tool for intelligent Notion automation with 25+ block types (BETA)",
|
5
|
-
"scripts": {
|
6
|
-
|
7
|
-
"
|
8
|
-
"
|
9
|
-
|
10
|
-
|
11
|
-
"
|
12
|
-
"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
"
|
21
|
-
"
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
"
|
28
|
-
"
|
29
|
-
"
|
30
|
-
"
|
31
|
-
"
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"
|
35
|
-
"
|
36
|
-
"
|
37
|
-
"
|
38
|
-
"
|
39
|
-
"
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
"
|
45
|
-
"
|
46
|
-
|
47
|
-
|
48
|
-
"
|
49
|
-
|
50
|
-
|
51
|
-
"
|
52
|
-
|
53
|
-
"
|
54
|
-
|
55
|
-
|
56
|
-
"
|
57
|
-
"
|
58
|
-
"
|
59
|
-
|
60
|
-
|
61
|
-
"
|
62
|
-
"
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
"
|
68
|
-
|
69
|
-
|
70
|
-
"eslint": "^9.32.0",
|
71
|
-
"eslint-plugin-n8n-nodes-base": "^1.11.0",
|
72
|
-
"prettier": "^3.6.2",
|
73
|
-
"typescript": "^5.1.3"
|
74
|
-
},
|
75
|
-
"peerDependencies": {
|
76
|
-
"n8n-workflow": "^1.82.0"
|
77
|
-
}
|
78
|
-
}
|
1
|
+
{
|
2
|
+
"name": "n8n-nodes-notion-advanced",
|
3
|
+
"version": "1.2.15-beta",
|
4
|
+
"description": "Advanced n8n Notion nodes: Full-featured workflow node + AI Agent Tool for intelligent Notion automation with 25+ block types (BETA)",
|
5
|
+
"scripts": {},
|
6
|
+
"files": [
|
7
|
+
"nodes",
|
8
|
+
"types"
|
9
|
+
],
|
10
|
+
"n8n": {
|
11
|
+
"n8nNodesApiVersion": 1,
|
12
|
+
"nodes": [
|
13
|
+
"nodes/NotionAdvanced/NotionAdvanced.node.js",
|
14
|
+
"nodes/NotionAdvanced/NotionAITool.node.js"
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"keywords": [
|
18
|
+
"n8n-community-node-package",
|
19
|
+
"notion",
|
20
|
+
"productivity",
|
21
|
+
"api",
|
22
|
+
"blocks",
|
23
|
+
"rich-text",
|
24
|
+
"database",
|
25
|
+
"pages",
|
26
|
+
"automation",
|
27
|
+
"workflow",
|
28
|
+
"integration",
|
29
|
+
"notion-api",
|
30
|
+
"block-types",
|
31
|
+
"formatting",
|
32
|
+
"ai",
|
33
|
+
"ai-agent",
|
34
|
+
"ai-tool",
|
35
|
+
"chatgpt",
|
36
|
+
"claude",
|
37
|
+
"llm",
|
38
|
+
"natural-language",
|
39
|
+
"intelligent-automation"
|
40
|
+
],
|
41
|
+
"license": "MIT",
|
42
|
+
"homepage": "https://github.com/your-username/n8n-notion-advanced-node#readme",
|
43
|
+
"author": {
|
44
|
+
"name": "AZ-IT.US",
|
45
|
+
"email": "azuniga6290@gmail.com"
|
46
|
+
},
|
47
|
+
"repository": {
|
48
|
+
"type": "git",
|
49
|
+
"url": "https://github.com/AZ-IT-US/n8n-notion-advanced-node.git"
|
50
|
+
},
|
51
|
+
"engines": {
|
52
|
+
"node": ">=16.10",
|
53
|
+
"pnpm": ">=7.18"
|
54
|
+
},
|
55
|
+
"packageManager": "pnpm@7.18.0",
|
56
|
+
"devDependencies": {
|
57
|
+
"@types/node": "^24.1.0",
|
58
|
+
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
59
|
+
"@typescript-eslint/parser": "^8.38.0",
|
60
|
+
"copyfiles": "^2.4.1",
|
61
|
+
"eslint": "^9.32.0",
|
62
|
+
"eslint-plugin-n8n-nodes-base": "^1.11.0",
|
63
|
+
"prettier": "^3.6.2",
|
64
|
+
"typescript": "^5.1.3"
|
65
|
+
},
|
66
|
+
"peerDependencies": {
|
67
|
+
"n8n-workflow": "^1.82.0"
|
68
|
+
}
|
69
|
+
}
|
package/LICENSE
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
MIT License
|
2
|
-
|
3
|
-
Copyright (c) 2024 n8n Community
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
@@ -1,306 +0,0 @@
|
|
1
|
-
# n8n Notion Advanced Nodes
|
2
|
-
|
3
|
-
A comprehensive n8n community package that provides complete access to the Notion API v2022-06-28 with support for all block types, rich text formatting, and CRUD operations. Includes both a full-featured workflow node and an AI Agent Tool for intelligent automation.
|
4
|
-
|
5
|
-
## What's Included
|
6
|
-
|
7
|
-
### 1. **Notion Advanced** - Full-Featured Workflow Node
|
8
|
-
Complete Notion integration for traditional n8n workflows with comprehensive CRUD operations and all 25+ block types.
|
9
|
-
|
10
|
-
### 2. **Notion AI Tool** - AI Agent Integration
|
11
|
-
Specialized tool designed for n8n's AI Agent Nodes, enabling natural language Notion automation.
|
12
|
-
|
13
|
-
📖 **For AI Agent usage, see [AI-TOOL-USAGE.md](./AI-TOOL-USAGE.md)**
|
14
|
-
|
15
|
-
## Features
|
16
|
-
|
17
|
-
### Complete Block Type Support
|
18
|
-
- **Basic Text Blocks**: paragraph, heading_1/2/3, bulleted_list_item, numbered_list_item, to_do, toggle, quote, callout, divider
|
19
|
-
- **Code Blocks**: code with syntax highlighting support for 170+ languages
|
20
|
-
- **Media Blocks**: image, video, audio, file, pdf with upload and external URL support
|
21
|
-
- **Interactive Blocks**: bookmark, embed, link_preview, equation (LaTeX)
|
22
|
-
- **Advanced Layout**: table, table_row, column_list, column, synced_block, template, table_of_contents
|
23
|
-
- **Database Integration**: child_database, child_page references
|
24
|
-
|
25
|
-
### Rich Text Formatting
|
26
|
-
- **Annotations**: bold, italic, strikethrough, underline, code
|
27
|
-
- **Colors**: All 10 text colors and 9 background colors
|
28
|
-
- **Links**: Internal page links and external URLs
|
29
|
-
- **Mentions**: User, page, database, and date mentions
|
30
|
-
- **Equations**: Inline and block LaTeX math expressions
|
31
|
-
|
32
|
-
### Operations
|
33
|
-
- **Pages**: Create, read, update, archive, search with full property support
|
34
|
-
- **Blocks**: Create, read, update, delete, get children, append children
|
35
|
-
- **Databases**: Get, query, create with complete schema support
|
36
|
-
- **Users**: Get, list workspace users
|
37
|
-
|
38
|
-
## Installation
|
39
|
-
|
40
|
-
### Via n8n GUI (Recommended)
|
41
|
-
1. Open n8n Settings → Community Nodes
|
42
|
-
2. Click "Install a community node"
|
43
|
-
3. Enter: `n8n-nodes-notion-advanced`
|
44
|
-
4. Click Install
|
45
|
-
|
46
|
-
### Via npm
|
47
|
-
```bash
|
48
|
-
npm install n8n-nodes-notion-advanced
|
49
|
-
```
|
50
|
-
|
51
|
-
📖 **For detailed installation instructions including Docker setup, development mode, and troubleshooting, see [INSTALLATION.md](./INSTALLATION.md)**
|
52
|
-
|
53
|
-
## Quick Start
|
54
|
-
|
55
|
-
### For AI Agents
|
56
|
-
```markdown
|
57
|
-
1. Add AI Agent Node to your workflow
|
58
|
-
2. Configure your chat model (OpenAI, Anthropic, etc.)
|
59
|
-
3. Add "Notion AI Tool" from available tools
|
60
|
-
4. Configure Notion credentials
|
61
|
-
5. AI Agent can now create/manage Notion content with natural language!
|
62
|
-
|
63
|
-
Example: "Create a project plan page with timeline and milestones"
|
64
|
-
```
|
65
|
-
|
66
|
-
### For Traditional Workflows
|
67
|
-
```markdown
|
68
|
-
1. Add "Notion Advanced" node to your workflow
|
69
|
-
2. Configure Notion credentials
|
70
|
-
3. Choose resource (Page/Block/Database/User)
|
71
|
-
4. Select operation and configure parameters
|
72
|
-
5. Execute comprehensive Notion operations
|
73
|
-
```
|
74
|
-
|
75
|
-
## Prerequisites
|
76
|
-
|
77
|
-
- n8n instance (self-hosted or cloud)
|
78
|
-
- Notion API integration with appropriate permissions
|
79
|
-
- Existing `notionApi` credentials configured in n8n
|
80
|
-
|
81
|
-
## Usage
|
82
|
-
|
83
|
-
### Setting up Credentials
|
84
|
-
|
85
|
-
This node uses the existing n8n Notion API credentials. Ensure you have:
|
86
|
-
|
87
|
-
1. Created a Notion integration at https://developers.notion.com/
|
88
|
-
2. Added the integration to your Notion workspace
|
89
|
-
3. Configured the `notionApi` credential in n8n with your integration token
|
90
|
-
|
91
|
-
### Basic Examples
|
92
|
-
|
93
|
-
#### Creating a Page
|
94
|
-
|
95
|
-
```json
|
96
|
-
{
|
97
|
-
"resource": "page",
|
98
|
-
"operation": "create",
|
99
|
-
"parent": "page-id-or-url",
|
100
|
-
"title": "My New Page",
|
101
|
-
"properties": {
|
102
|
-
"property": [
|
103
|
-
{
|
104
|
-
"name": "Status",
|
105
|
-
"type": "select",
|
106
|
-
"value": "{\"name\": \"In Progress\"}"
|
107
|
-
}
|
108
|
-
]
|
109
|
-
}
|
110
|
-
}
|
111
|
-
```
|
112
|
-
|
113
|
-
#### Adding Blocks to a Page
|
114
|
-
|
115
|
-
```json
|
116
|
-
{
|
117
|
-
"resource": "block",
|
118
|
-
"operation": "create",
|
119
|
-
"parentId": "page-id",
|
120
|
-
"blocks": {
|
121
|
-
"block": [
|
122
|
-
{
|
123
|
-
"type": "paragraph",
|
124
|
-
"content": "This is a simple paragraph"
|
125
|
-
},
|
126
|
-
{
|
127
|
-
"type": "heading_1",
|
128
|
-
"content": "Main Heading",
|
129
|
-
"properties": "{\"color\": \"blue\"}"
|
130
|
-
},
|
131
|
-
{
|
132
|
-
"type": "code",
|
133
|
-
"content": "console.log('Hello World');",
|
134
|
-
"properties": "{\"language\": \"javascript\"}"
|
135
|
-
}
|
136
|
-
]
|
137
|
-
}
|
138
|
-
}
|
139
|
-
```
|
140
|
-
|
141
|
-
#### Rich Text with Formatting
|
142
|
-
|
143
|
-
```json
|
144
|
-
{
|
145
|
-
"type": "paragraph",
|
146
|
-
"richText": "[{\"type\": \"text\", \"text\": {\"content\": \"Bold text\"}, \"annotations\": {\"bold\": true}}, {\"type\": \"text\", \"text\": {\"content\": \" and \"}, \"annotations\": {}}, {\"type\": \"text\", \"text\": {\"content\": \"italic text\", \"link\": {\"url\": \"https://example.com\"}}, \"annotations\": {\"italic\": true, \"color\": \"blue\"}}]"
|
147
|
-
}
|
148
|
-
```
|
149
|
-
|
150
|
-
## Block Types Reference
|
151
|
-
|
152
|
-
### Text Blocks
|
153
|
-
|
154
|
-
| Block Type | Properties | Description |
|
155
|
-
|------------|-----------|-------------|
|
156
|
-
| `paragraph` | `rich_text`, `color`, `children` | Basic text paragraph |
|
157
|
-
| `heading_1` | `rich_text`, `color`, `is_toggleable` | Top-level heading |
|
158
|
-
| `heading_2` | `rich_text`, `color`, `is_toggleable` | Second-level heading |
|
159
|
-
| `heading_3` | `rich_text`, `color`, `is_toggleable` | Third-level heading |
|
160
|
-
| `bulleted_list_item` | `rich_text`, `color`, `children` | Bullet point list item |
|
161
|
-
| `numbered_list_item` | `rich_text`, `color`, `children` | Numbered list item |
|
162
|
-
| `to_do` | `rich_text`, `checked`, `color`, `children` | Checkbox item |
|
163
|
-
| `toggle` | `rich_text`, `color`, `children` | Collapsible section |
|
164
|
-
| `quote` | `rich_text`, `color`, `children` | Block quote |
|
165
|
-
| `callout` | `rich_text`, `icon`, `color`, `children` | Highlighted callout |
|
166
|
-
|
167
|
-
### Code Blocks
|
168
|
-
|
169
|
-
| Block Type | Properties | Description |
|
170
|
-
|------------|-----------|-------------|
|
171
|
-
| `code` | `rich_text`, `language`, `caption` | Code block with syntax highlighting |
|
172
|
-
|
173
|
-
**Supported Languages**: JavaScript, Python, Java, C++, HTML, CSS, SQL, JSON, XML, and 160+ more.
|
174
|
-
|
175
|
-
### Media Blocks
|
176
|
-
|
177
|
-
| Block Type | Properties | Description |
|
178
|
-
|------------|-----------|-------------|
|
179
|
-
| `image` | `url`, `caption` | Image from URL or upload |
|
180
|
-
| `video` | `url`, `caption` | Video embed or upload |
|
181
|
-
| `audio` | `url`, `caption` | Audio file |
|
182
|
-
| `file` | `url`, `caption` | Generic file attachment |
|
183
|
-
| `pdf` | `url`, `caption` | PDF document |
|
184
|
-
|
185
|
-
### Interactive Blocks
|
186
|
-
|
187
|
-
| Block Type | Properties | Description |
|
188
|
-
|------------|-----------|-------------|
|
189
|
-
| `bookmark` | `url`, `caption` | Website bookmark with preview |
|
190
|
-
| `embed` | `url`, `caption` | Embedded content |
|
191
|
-
| `link_preview` | `url` | Auto-generated link preview |
|
192
|
-
| `equation` | `expression` | LaTeX mathematical expression |
|
193
|
-
|
194
|
-
### Layout Blocks
|
195
|
-
|
196
|
-
| Block Type | Properties | Description |
|
197
|
-
|------------|-----------|-------------|
|
198
|
-
| `table` | `table_width`, `has_column_header`, `has_row_header`, `children` | Data table |
|
199
|
-
| `table_row` | `cells` | Table row with cells |
|
200
|
-
| `column_list` | `children` | Container for columns |
|
201
|
-
| `column` | `children` | Individual column |
|
202
|
-
| `divider` | None | Horizontal divider line |
|
203
|
-
|
204
|
-
### Advanced Blocks
|
205
|
-
|
206
|
-
| Block Type | Properties | Description |
|
207
|
-
|------------|-----------|-------------|
|
208
|
-
| `synced_block` | `synced_from`, `children` | Synchronized content block |
|
209
|
-
| `template` | `rich_text`, `children` | Template block |
|
210
|
-
| `table_of_contents` | `color` | Auto-generated table of contents |
|
211
|
-
| `child_database` | `title` | Inline database |
|
212
|
-
| `child_page` | `title` | Child page reference |
|
213
|
-
|
214
|
-
## Rich Text Formatting
|
215
|
-
|
216
|
-
### Annotations
|
217
|
-
|
218
|
-
```json
|
219
|
-
{
|
220
|
-
"annotations": {
|
221
|
-
"bold": true,
|
222
|
-
"italic": false,
|
223
|
-
"strikethrough": false,
|
224
|
-
"underline": true,
|
225
|
-
"code": false,
|
226
|
-
"color": "blue"
|
227
|
-
}
|
228
|
-
}
|
229
|
-
```
|
230
|
-
|
231
|
-
### Colors
|
232
|
-
|
233
|
-
**Text Colors**: `default`, `gray`, `brown`, `orange`, `yellow`, `green`, `blue`, `purple`, `pink`, `red`
|
234
|
-
|
235
|
-
**Background Colors**: `gray_background`, `brown_background`, `orange_background`, `yellow_background`, `green_background`, `blue_background`, `purple_background`, `pink_background`, `red_background`
|
236
|
-
|
237
|
-
### Links
|
238
|
-
|
239
|
-
```json
|
240
|
-
{
|
241
|
-
"text": {
|
242
|
-
"content": "Link text",
|
243
|
-
"link": {
|
244
|
-
"url": "https://example.com"
|
245
|
-
}
|
246
|
-
}
|
247
|
-
}
|
248
|
-
```
|
249
|
-
|
250
|
-
## Error Handling
|
251
|
-
|
252
|
-
The node provides comprehensive error handling:
|
253
|
-
|
254
|
-
- **Credential Validation**: Automatically validates API credentials
|
255
|
-
- **Input Validation**: Validates all required fields and block structures
|
256
|
-
- **API Error Mapping**: Maps Notion API errors to user-friendly messages
|
257
|
-
- **Graceful Degradation**: Continues processing with `continueOnFail` option
|
258
|
-
|
259
|
-
## Performance Features
|
260
|
-
|
261
|
-
- **Pagination Support**: Automatically handles paginated responses
|
262
|
-
- **Batch Operations**: Efficient bulk block creation and updates
|
263
|
-
- **Credential Caching**: Reuses authentication across requests
|
264
|
-
- **Request Optimization**: Minimizes API calls with intelligent batching
|
265
|
-
|
266
|
-
## Troubleshooting
|
267
|
-
|
268
|
-
### Common Issues
|
269
|
-
|
270
|
-
1. **Permission Errors**: Ensure your Notion integration has access to the target pages/databases
|
271
|
-
2. **Invalid Block Types**: Check that all block properties match the expected schema
|
272
|
-
3. **Rate Limiting**: The node respects Notion's rate limits automatically
|
273
|
-
4. **Large Content**: For pages with many blocks, consider using batch operations
|
274
|
-
|
275
|
-
### Debug Tips
|
276
|
-
|
277
|
-
- Enable n8n's debug mode to see full API requests/responses
|
278
|
-
- Validate JSON strings in block properties before sending
|
279
|
-
- Test with simple blocks before adding complex formatting
|
280
|
-
- Check Notion's API documentation for the latest block schemas
|
281
|
-
|
282
|
-
## API Reference
|
283
|
-
|
284
|
-
This node implements Notion API version `2022-06-28`. For the most up-to-date API documentation, visit:
|
285
|
-
https://developers.notion.com/reference
|
286
|
-
|
287
|
-
## Contributing
|
288
|
-
|
289
|
-
Contributions are welcome! Please:
|
290
|
-
|
291
|
-
1. Fork the repository
|
292
|
-
2. Create a feature branch
|
293
|
-
3. Add tests for new functionality
|
294
|
-
4. Submit a pull request
|
295
|
-
|
296
|
-
## License
|
297
|
-
|
298
|
-
MIT License - see LICENSE file for details.
|
299
|
-
|
300
|
-
## Support
|
301
|
-
|
302
|
-
For issues and questions:
|
303
|
-
- Check the troubleshooting section
|
304
|
-
- Review Notion's API documentation
|
305
|
-
- Open an issue on GitHub
|
306
|
-
- Join the n8n community forum
|
@@ -1,3 +0,0 @@
|
|
1
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
-
<path d="M4.459 4.208c.746.606 1.026.56 2.428.466l13.215-.793c.28 0 .047-.28-.046-.326L17.86 1.968c-.42-.326-.981-.7-2.055-.607L3.533 2.221c-.466.047-.56.28-.374.466l1.3.979zM5.206 6.678v14.018c0 .746.373 1.027 1.214.98l14.523-.84c.841-.046.935-.56.935-1.167V6.305c0-.607-.28-.887-.747-.84l-15.177.887c-.56.047-.748.327-.748.746v-.42zm14.337.793c.093.42 0 .84-.42.888l-.7.14v10.264c-.608.327-1.168.514-1.635.514-.748 0-.935-.234-1.495-.933l-4.577-7.186v6.952L12.21 18s0 .84-1.168.84l-3.222.186c-.093-.186 0-.653.327-.746l.84-.233V9.854L7.822 9.76c-.094-.42.14-1.026.793-1.073l3.456-.233 4.764 7.279v-6.44l-1.215-.139c-.093-.514.28-.887.747-.933l3.176-.233z" fill="currentColor"/>
|
3
|
-
</svg>
|
package/dist/package.json
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"name": "n8n-nodes-notion-advanced",
|
3
|
-
"version": "1.2.13-beta",
|
4
|
-
"description": "Advanced n8n Notion nodes: Full-featured workflow node + AI Agent Tool for intelligent Notion automation with 25+ block types (BETA)",
|
5
|
-
"scripts": {},
|
6
|
-
"files": [
|
7
|
-
"nodes",
|
8
|
-
"types"
|
9
|
-
],
|
10
|
-
"n8n": {
|
11
|
-
"n8nNodesApiVersion": 1,
|
12
|
-
"nodes": [
|
13
|
-
"nodes/NotionAdvanced/NotionAdvanced.node.js",
|
14
|
-
"nodes/NotionAdvanced/NotionAITool.node.js"
|
15
|
-
]
|
16
|
-
},
|
17
|
-
"keywords": [
|
18
|
-
"n8n-community-node-package",
|
19
|
-
"notion",
|
20
|
-
"productivity",
|
21
|
-
"api",
|
22
|
-
"blocks",
|
23
|
-
"rich-text",
|
24
|
-
"database",
|
25
|
-
"pages",
|
26
|
-
"automation",
|
27
|
-
"workflow",
|
28
|
-
"integration",
|
29
|
-
"notion-api",
|
30
|
-
"block-types",
|
31
|
-
"formatting",
|
32
|
-
"ai",
|
33
|
-
"ai-agent",
|
34
|
-
"ai-tool",
|
35
|
-
"chatgpt",
|
36
|
-
"claude",
|
37
|
-
"llm",
|
38
|
-
"natural-language",
|
39
|
-
"intelligent-automation"
|
40
|
-
],
|
41
|
-
"license": "MIT",
|
42
|
-
"homepage": "https://github.com/your-username/n8n-notion-advanced-node#readme",
|
43
|
-
"author": {
|
44
|
-
"name": "AZ-IT.US",
|
45
|
-
"email": "azuniga6290@gmail.com"
|
46
|
-
},
|
47
|
-
"repository": {
|
48
|
-
"type": "git",
|
49
|
-
"url": "https://github.com/AZ-IT-US/n8n-notion-advanced-node.git"
|
50
|
-
},
|
51
|
-
"engines": {
|
52
|
-
"node": ">=16.10",
|
53
|
-
"pnpm": ">=7.18"
|
54
|
-
},
|
55
|
-
"packageManager": "pnpm@7.18.0",
|
56
|
-
"devDependencies": {
|
57
|
-
"@types/node": "^24.1.0",
|
58
|
-
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
59
|
-
"@typescript-eslint/parser": "^8.38.0",
|
60
|
-
"copyfiles": "^2.4.1",
|
61
|
-
"eslint": "^9.32.0",
|
62
|
-
"eslint-plugin-n8n-nodes-base": "^1.11.0",
|
63
|
-
"prettier": "^3.6.2",
|
64
|
-
"typescript": "^5.1.3"
|
65
|
-
},
|
66
|
-
"peerDependencies": {
|
67
|
-
"n8n-workflow": "^1.82.0"
|
68
|
-
}
|
69
|
-
}
|
@@ -1,15 +0,0 @@
|
|
1
|
-
import type { RichTextObject, Block } from '../types/NotionTypes';
|
2
|
-
export declare function testRichTextCreation(): void;
|
3
|
-
export declare function testRichTextParsing(): void;
|
4
|
-
export declare function testBlockCreation(): void;
|
5
|
-
export declare function testBlockInputConversion(): void;
|
6
|
-
export declare function testBlockValidation(): void;
|
7
|
-
export declare function testTableCreation(): void;
|
8
|
-
export declare function testComplexRichText(): void;
|
9
|
-
export declare function testAllBlockTypes(): void;
|
10
|
-
export declare function testTypicalWorkflow(): void;
|
11
|
-
export declare function runAllTests(): void;
|
12
|
-
export declare const testData: {
|
13
|
-
sampleRichText: RichTextObject[];
|
14
|
-
sampleBlocks: Block[];
|
15
|
-
};
|
@@ -1,290 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
// Test file for Notion Advanced Node
|
3
|
-
// Note: These are conceptual tests. In a real environment, you would use Jest or similar testing framework
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
5
|
-
exports.testData = void 0;
|
6
|
-
exports.testRichTextCreation = testRichTextCreation;
|
7
|
-
exports.testRichTextParsing = testRichTextParsing;
|
8
|
-
exports.testBlockCreation = testBlockCreation;
|
9
|
-
exports.testBlockInputConversion = testBlockInputConversion;
|
10
|
-
exports.testBlockValidation = testBlockValidation;
|
11
|
-
exports.testTableCreation = testTableCreation;
|
12
|
-
exports.testComplexRichText = testComplexRichText;
|
13
|
-
exports.testAllBlockTypes = testAllBlockTypes;
|
14
|
-
exports.testTypicalWorkflow = testTypicalWorkflow;
|
15
|
-
exports.runAllTests = runAllTests;
|
16
|
-
const NotionUtils_1 = require("../nodes/NotionAdvanced/NotionUtils");
|
17
|
-
// Test Rich Text Creation
|
18
|
-
function testRichTextCreation() {
|
19
|
-
var _a, _b, _c;
|
20
|
-
console.log('Testing Rich Text Creation...');
|
21
|
-
// Test basic rich text
|
22
|
-
const basicText = (0, NotionUtils_1.createRichText)('Hello World');
|
23
|
-
console.assert(basicText.type === 'text', 'Basic text type should be text');
|
24
|
-
console.assert(((_a = basicText.text) === null || _a === void 0 ? void 0 : _a.content) === 'Hello World', 'Content should match');
|
25
|
-
console.assert(basicText.annotations.bold === false, 'Bold should default to false');
|
26
|
-
// Test formatted rich text
|
27
|
-
const formattedText = (0, NotionUtils_1.createRichText)('Bold Text', { bold: true, color: 'red' });
|
28
|
-
console.assert(formattedText.annotations.bold === true, 'Bold should be true');
|
29
|
-
console.assert(formattedText.annotations.color === 'red', 'Color should be red');
|
30
|
-
// Test rich text with link
|
31
|
-
const linkedText = (0, NotionUtils_1.createRichText)('Link Text', {}, 'https://example.com');
|
32
|
-
console.assert(((_c = (_b = linkedText.text) === null || _b === void 0 ? void 0 : _b.link) === null || _c === void 0 ? void 0 : _c.url) === 'https://example.com', 'Link URL should match');
|
33
|
-
console.log('✅ Rich Text Creation tests passed');
|
34
|
-
}
|
35
|
-
// Test Rich Text Parsing
|
36
|
-
function testRichTextParsing() {
|
37
|
-
var _a;
|
38
|
-
console.log('Testing Rich Text Parsing...');
|
39
|
-
// Test string input
|
40
|
-
const stringResult = (0, NotionUtils_1.parseRichTextInput)('Simple string');
|
41
|
-
console.assert(Array.isArray(stringResult), 'Should return array');
|
42
|
-
console.assert(stringResult.length === 1, 'Should have one element');
|
43
|
-
console.assert(((_a = stringResult[0].text) === null || _a === void 0 ? void 0 : _a.content) === 'Simple string', 'Content should match');
|
44
|
-
// Test array input
|
45
|
-
const arrayInput = [
|
46
|
-
{ text: 'First part', annotations: { bold: true } },
|
47
|
-
{ text: 'Second part', annotations: { italic: true } }
|
48
|
-
];
|
49
|
-
const arrayResult = (0, NotionUtils_1.parseRichTextInput)(arrayInput);
|
50
|
-
console.assert(arrayResult.length === 2, 'Should have two elements');
|
51
|
-
// Test object input
|
52
|
-
const objectInput = { text: 'Object text', annotations: { color: 'blue' } };
|
53
|
-
const objectResult = (0, NotionUtils_1.parseRichTextInput)(objectInput);
|
54
|
-
console.assert(objectResult.length === 1, 'Should have one element');
|
55
|
-
console.log('✅ Rich Text Parsing tests passed');
|
56
|
-
}
|
57
|
-
// Test Block Creation
|
58
|
-
function testBlockCreation() {
|
59
|
-
var _a, _b;
|
60
|
-
console.log('Testing Block Creation...');
|
61
|
-
// Test paragraph block
|
62
|
-
const paragraph = (0, NotionUtils_1.createParagraphBlock)('Test paragraph', 'blue');
|
63
|
-
console.assert(paragraph.type === 'paragraph', 'Type should be paragraph');
|
64
|
-
console.assert('paragraph' in paragraph && paragraph.paragraph.color === 'blue', 'Color should be blue');
|
65
|
-
// Test heading blocks
|
66
|
-
const h1 = (0, NotionUtils_1.createHeadingBlock)(1, 'Main Title', 'red');
|
67
|
-
console.assert(h1.type === 'heading_1', 'Type should be heading_1');
|
68
|
-
console.assert('heading_1' in h1 && ((_a = h1.heading_1) === null || _a === void 0 ? void 0 : _a.color) === 'red', 'Color should be red');
|
69
|
-
const h2 = (0, NotionUtils_1.createHeadingBlock)(2, 'Section Title');
|
70
|
-
console.assert(h2.type === 'heading_2', 'Type should be heading_2');
|
71
|
-
const h3 = (0, NotionUtils_1.createHeadingBlock)(3, 'Sub Title', undefined, true);
|
72
|
-
console.assert(h3.type === 'heading_3', 'Type should be heading_3');
|
73
|
-
console.assert('heading_3' in h3 && ((_b = h3.heading_3) === null || _b === void 0 ? void 0 : _b.is_toggleable) === true, 'Should be toggleable');
|
74
|
-
// Test code block
|
75
|
-
const code = (0, NotionUtils_1.createCodeBlock)('console.log("test");', 'javascript');
|
76
|
-
console.assert(code.type === 'code', 'Type should be code');
|
77
|
-
console.assert('code' in code && code.code.language === 'javascript', 'Language should be javascript');
|
78
|
-
console.log('✅ Block Creation tests passed');
|
79
|
-
}
|
80
|
-
// Test Block Input Conversion
|
81
|
-
function testBlockInputConversion() {
|
82
|
-
console.log('Testing Block Input Conversion...');
|
83
|
-
// Test paragraph conversion
|
84
|
-
const paragraphInput = {
|
85
|
-
type: 'paragraph',
|
86
|
-
content: 'Test content',
|
87
|
-
properties: { color: 'green' }
|
88
|
-
};
|
89
|
-
const paragraphBlock = (0, NotionUtils_1.convertBlockInput)(paragraphInput);
|
90
|
-
console.assert(paragraphBlock.type === 'paragraph', 'Type should be paragraph');
|
91
|
-
// Test heading conversion
|
92
|
-
const headingInput = {
|
93
|
-
type: 'heading_1',
|
94
|
-
content: 'Heading text',
|
95
|
-
properties: { color: 'blue', isToggleable: true }
|
96
|
-
};
|
97
|
-
const headingBlock = (0, NotionUtils_1.convertBlockInput)(headingInput);
|
98
|
-
console.assert(headingBlock.type === 'heading_1', 'Type should be heading_1');
|
99
|
-
// Test code conversion
|
100
|
-
const codeInput = {
|
101
|
-
type: 'code',
|
102
|
-
content: 'print("Hello")',
|
103
|
-
properties: { language: 'python' }
|
104
|
-
};
|
105
|
-
const codeBlock = (0, NotionUtils_1.convertBlockInput)(codeInput);
|
106
|
-
console.assert(codeBlock.type === 'code', 'Type should be code');
|
107
|
-
console.assert('code' in codeBlock && codeBlock.code.language === 'python', 'Language should be python');
|
108
|
-
console.log('✅ Block Input Conversion tests passed');
|
109
|
-
}
|
110
|
-
// Test Block Validation
|
111
|
-
function testBlockValidation() {
|
112
|
-
console.log('Testing Block Validation...');
|
113
|
-
// Test valid paragraph
|
114
|
-
const validParagraph = (0, NotionUtils_1.createParagraphBlock)('Valid content');
|
115
|
-
try {
|
116
|
-
(0, NotionUtils_1.validateBlock)(validParagraph);
|
117
|
-
console.log('Valid paragraph passed validation');
|
118
|
-
}
|
119
|
-
catch (error) {
|
120
|
-
console.error('Valid paragraph failed validation:', error);
|
121
|
-
}
|
122
|
-
// Test valid code block
|
123
|
-
const validCode = (0, NotionUtils_1.createCodeBlock)('Valid code', 'javascript');
|
124
|
-
try {
|
125
|
-
(0, NotionUtils_1.validateBlock)(validCode);
|
126
|
-
console.log('Valid code block passed validation');
|
127
|
-
}
|
128
|
-
catch (error) {
|
129
|
-
console.error('Valid code block failed validation:', error);
|
130
|
-
}
|
131
|
-
console.log('✅ Block Validation tests passed');
|
132
|
-
}
|
133
|
-
// Test Table Creation
|
134
|
-
function testTableCreation() {
|
135
|
-
console.log('Testing Table Creation...');
|
136
|
-
const tableData = [
|
137
|
-
[[(0, NotionUtils_1.createRichText)('Header 1')], [(0, NotionUtils_1.createRichText)('Header 2')]],
|
138
|
-
[[(0, NotionUtils_1.createRichText)('Cell 1')], [(0, NotionUtils_1.createRichText)('Cell 2')]],
|
139
|
-
[[(0, NotionUtils_1.createRichText)('Cell 3')], [(0, NotionUtils_1.createRichText)('Cell 4')]]
|
140
|
-
];
|
141
|
-
const table = (0, NotionUtils_1.createTableBlock)(2, tableData, true, false);
|
142
|
-
console.assert(table.type === 'table', 'Type should be table');
|
143
|
-
console.assert('table' in table && table.table.table_width === 2, 'Width should be 2');
|
144
|
-
console.assert('table' in table && table.table.has_column_header === true, 'Should have column header');
|
145
|
-
console.assert('table' in table && table.table.has_row_header === false, 'Should not have row header');
|
146
|
-
console.log('✅ Table Creation tests passed');
|
147
|
-
}
|
148
|
-
// Test Complex Rich Text
|
149
|
-
function testComplexRichText() {
|
150
|
-
var _a, _b;
|
151
|
-
console.log('Testing Complex Rich Text...');
|
152
|
-
const complexRichText = [
|
153
|
-
(0, NotionUtils_1.createRichText)('Normal text '),
|
154
|
-
(0, NotionUtils_1.createRichText)('bold text', { bold: true }),
|
155
|
-
(0, NotionUtils_1.createRichText)(' and '),
|
156
|
-
(0, NotionUtils_1.createRichText)('italic blue text', { italic: true, color: 'blue' }),
|
157
|
-
(0, NotionUtils_1.createRichText)(' with a ', {}),
|
158
|
-
(0, NotionUtils_1.createRichText)('link', { underline: true }, 'https://example.com')
|
159
|
-
];
|
160
|
-
console.assert(complexRichText.length === 6, 'Should have 6 rich text objects');
|
161
|
-
console.assert(complexRichText[1].annotations.bold === true, 'Second element should be bold');
|
162
|
-
console.assert(complexRichText[3].annotations.italic === true, 'Fourth element should be italic');
|
163
|
-
console.assert(complexRichText[3].annotations.color === 'blue', 'Fourth element should be blue');
|
164
|
-
console.assert(((_b = (_a = complexRichText[5].text) === null || _a === void 0 ? void 0 : _a.link) === null || _b === void 0 ? void 0 : _b.url) === 'https://example.com', 'Last element should have link');
|
165
|
-
console.log('✅ Complex Rich Text tests passed');
|
166
|
-
}
|
167
|
-
// Test All Block Types
|
168
|
-
function testAllBlockTypes() {
|
169
|
-
console.log('Testing All Block Types...');
|
170
|
-
const blockTypes = [
|
171
|
-
'paragraph', 'heading_1', 'heading_2', 'heading_3',
|
172
|
-
'bulleted_list_item', 'numbered_list_item', 'to_do',
|
173
|
-
'toggle', 'quote', 'callout', 'code', 'divider',
|
174
|
-
'equation', 'image', 'bookmark', 'embed'
|
175
|
-
];
|
176
|
-
for (const blockType of blockTypes) {
|
177
|
-
try {
|
178
|
-
const blockInput = {
|
179
|
-
type: blockType,
|
180
|
-
content: 'Test content',
|
181
|
-
properties: {}
|
182
|
-
};
|
183
|
-
// Special cases for specific block types
|
184
|
-
if (blockType === 'equation') {
|
185
|
-
blockInput.properties = { expression: 'E = mc^2' };
|
186
|
-
}
|
187
|
-
else if (['image', 'bookmark', 'embed'].includes(blockType)) {
|
188
|
-
blockInput.properties = { url: 'https://example.com' };
|
189
|
-
}
|
190
|
-
else if (blockType === 'code') {
|
191
|
-
blockInput.properties = { language: 'javascript' };
|
192
|
-
}
|
193
|
-
else if (blockType === 'callout') {
|
194
|
-
blockInput.properties = { icon: '💡' };
|
195
|
-
}
|
196
|
-
const block = (0, NotionUtils_1.convertBlockInput)(blockInput);
|
197
|
-
(0, NotionUtils_1.validateBlock)(block);
|
198
|
-
console.log(`✓ ${blockType} block created and validated`);
|
199
|
-
}
|
200
|
-
catch (error) {
|
201
|
-
console.error(`✗ ${blockType} block failed:`, error);
|
202
|
-
}
|
203
|
-
}
|
204
|
-
console.log('✅ All Block Types tests completed');
|
205
|
-
}
|
206
|
-
// Integration test for typical workflow
|
207
|
-
function testTypicalWorkflow() {
|
208
|
-
console.log('Testing Typical Workflow...');
|
209
|
-
// Simulate creating a documentation page
|
210
|
-
const pageBlocks = [
|
211
|
-
{
|
212
|
-
type: 'heading_1',
|
213
|
-
content: 'API Documentation',
|
214
|
-
properties: { color: 'blue' }
|
215
|
-
},
|
216
|
-
{
|
217
|
-
type: 'paragraph',
|
218
|
-
content: 'This document describes the REST API endpoints.',
|
219
|
-
properties: {}
|
220
|
-
},
|
221
|
-
{
|
222
|
-
type: 'heading_2',
|
223
|
-
content: 'Authentication',
|
224
|
-
properties: {}
|
225
|
-
},
|
226
|
-
{
|
227
|
-
type: 'paragraph',
|
228
|
-
richText: [
|
229
|
-
(0, NotionUtils_1.createRichText)('Use the '),
|
230
|
-
(0, NotionUtils_1.createRichText)('Authorization', { code: true }),
|
231
|
-
(0, NotionUtils_1.createRichText)(' header with your API key.')
|
232
|
-
]
|
233
|
-
},
|
234
|
-
{
|
235
|
-
type: 'code',
|
236
|
-
content: 'curl -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/users',
|
237
|
-
properties: { language: 'bash' }
|
238
|
-
},
|
239
|
-
{
|
240
|
-
type: 'callout',
|
241
|
-
content: 'Keep your API key secure and never commit it to version control.',
|
242
|
-
properties: { icon: '🔒', color: 'yellow_background' }
|
243
|
-
}
|
244
|
-
];
|
245
|
-
try {
|
246
|
-
const convertedBlocks = pageBlocks.map(NotionUtils_1.convertBlockInput);
|
247
|
-
convertedBlocks.forEach(NotionUtils_1.validateBlock);
|
248
|
-
console.log(`✓ Successfully processed ${convertedBlocks.length} blocks for documentation page`);
|
249
|
-
}
|
250
|
-
catch (error) {
|
251
|
-
console.error('✗ Typical workflow failed:', error);
|
252
|
-
}
|
253
|
-
console.log('✅ Typical Workflow test completed');
|
254
|
-
}
|
255
|
-
// Run all tests
|
256
|
-
function runAllTests() {
|
257
|
-
console.log('🧪 Running Notion Advanced Node Tests...\n');
|
258
|
-
try {
|
259
|
-
testRichTextCreation();
|
260
|
-
testRichTextParsing();
|
261
|
-
testBlockCreation();
|
262
|
-
testBlockInputConversion();
|
263
|
-
testBlockValidation();
|
264
|
-
testTableCreation();
|
265
|
-
testComplexRichText();
|
266
|
-
testAllBlockTypes();
|
267
|
-
testTypicalWorkflow();
|
268
|
-
console.log('\n🎉 All tests completed successfully!');
|
269
|
-
}
|
270
|
-
catch (error) {
|
271
|
-
console.error('\n❌ Tests failed:', error);
|
272
|
-
}
|
273
|
-
}
|
274
|
-
// Export test data for external use
|
275
|
-
exports.testData = {
|
276
|
-
sampleRichText: [
|
277
|
-
(0, NotionUtils_1.createRichText)('Normal text '),
|
278
|
-
(0, NotionUtils_1.createRichText)('bold', { bold: true }),
|
279
|
-
(0, NotionUtils_1.createRichText)(' and '),
|
280
|
-
(0, NotionUtils_1.createRichText)('italic', { italic: true })
|
281
|
-
],
|
282
|
-
sampleBlocks: [
|
283
|
-
(0, NotionUtils_1.createParagraphBlock)('Sample paragraph'),
|
284
|
-
(0, NotionUtils_1.createHeadingBlock)(1, 'Sample heading'),
|
285
|
-
(0, NotionUtils_1.createCodeBlock)('console.log("test");', 'javascript')
|
286
|
-
]
|
287
|
-
};
|
288
|
-
// Export for use as module or run tests directly
|
289
|
-
// Uncomment the following line to run tests when this file is executed:
|
290
|
-
// runAllTests();
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|