n8n-nodes-notion-advanced 1.2.29-beta → 1.2.31-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.
@@ -22,6 +22,15 @@ interface XMLNode {
|
|
22
22
|
replacement?: string;
|
23
23
|
listProcessor?: (content: string, blocks: IDataObject[]) => void;
|
24
24
|
}
|
25
|
+
interface HierarchyNode {
|
26
|
+
block: IDataObject;
|
27
|
+
children: HierarchyNode[];
|
28
|
+
metadata?: {
|
29
|
+
sourcePosition?: number;
|
30
|
+
xmlNodeId?: string;
|
31
|
+
tagName?: string;
|
32
|
+
};
|
33
|
+
}
|
25
34
|
export declare class NotionAITool implements INodeType {
|
26
35
|
description: INodeTypeDescription;
|
27
36
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
@@ -43,6 +52,8 @@ export declare class NotionAITool implements INodeType {
|
|
43
52
|
}[]): string;
|
44
53
|
static getUtf8BytePosition(str: string, charIndex: number): number;
|
45
54
|
static buildXMLTree(content: string, tagProcessors: any[]): XMLNode[];
|
55
|
+
static xmlTreeToHierarchy(nodes: XMLNode[]): HierarchyNode[];
|
56
|
+
static hierarchyToNotionBlocks(hierarchy: HierarchyNode[]): IDataObject[];
|
46
57
|
static processXMLTreeDepthFirst(nodes: XMLNode[], blocks: IDataObject[], placeholderCounter: {
|
47
58
|
value: number;
|
48
59
|
}): Map<string, string>;
|
@@ -54,7 +65,10 @@ export declare class NotionAITool implements INodeType {
|
|
54
65
|
static cleanupRemainingHtml(content: string, placeholderPrefix?: string): string;
|
55
66
|
static processNestedHtmlInListItem(content: string): string;
|
56
67
|
static convertInlineHtmlToMarkdown(content: string): string;
|
57
|
-
static
|
68
|
+
static buildListHierarchy(listContent: string, listType: 'bulleted_list_item' | 'numbered_list_item', childHierarchyNodes: HierarchyNode[]): HierarchyNode | null;
|
69
|
+
static mapChildBlocksToListItems(listContent: string, childBlocks: IDataObject[], childNodes: XMLNode[]): Map<number, IDataObject[]>;
|
70
|
+
static processNestedListWithChildBlocks(listContent: string, listType: 'bulleted_list_item' | 'numbered_list_item', blocks: IDataObject[], listItemChildBlocks: Map<number, IDataObject[]>): void;
|
71
|
+
static processNestedList(listContent: string, listType: 'bulleted_list_item' | 'numbered_list_item', blocks: IDataObject[], childNodes?: XMLNode[]): void;
|
58
72
|
static extractListItemsWithBranching(content: string): Array<{
|
59
73
|
text: string;
|
60
74
|
children: Array<{
|
@@ -749,67 +749,55 @@ class NotionAITool {
|
|
749
749
|
static buildXMLTree(content, tagProcessors) {
|
750
750
|
var _a;
|
751
751
|
const allMatches = [];
|
752
|
-
// Step 1: Use
|
752
|
+
// Step 1: Use regex-based parsing to properly extract capture groups, then enhance with depth-aware structure
|
753
753
|
tagProcessors.forEach(({ regex, blockCreator, listProcessor }) => {
|
754
754
|
var _a;
|
755
|
-
const
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
if (nextClose === -1)
|
777
|
-
break;
|
778
|
-
if (nextOpen !== -1 && nextOpen < nextClose) {
|
779
|
-
// Found nested opening tag
|
780
|
-
depth++;
|
781
|
-
searchPos = nextOpen + openPattern.length;
|
755
|
+
const globalRegex = new RegExp(regex.source, 'gis');
|
756
|
+
let match;
|
757
|
+
while ((match = globalRegex.exec(content)) !== null) {
|
758
|
+
const fullMatch = match[0];
|
759
|
+
const matchStart = match.index;
|
760
|
+
const matchEnd = match.index + fullMatch.length;
|
761
|
+
// Extract tag name for identification
|
762
|
+
const tagPattern = ((_a = regex.source.match(/<(\w+)/)) === null || _a === void 0 ? void 0 : _a[1]) || 'unknown';
|
763
|
+
// Extract inner content (between opening and closing tags)
|
764
|
+
let innerContent = '';
|
765
|
+
try {
|
766
|
+
const openTagRegex = new RegExp(`^<${tagPattern}[^>]*>`, 'i');
|
767
|
+
const closeTagRegex = new RegExp(`</${tagPattern}>$`, 'i');
|
768
|
+
const openMatch = fullMatch.match(openTagRegex);
|
769
|
+
const closeMatch = fullMatch.match(closeTagRegex);
|
770
|
+
if (openMatch && closeMatch) {
|
771
|
+
const openTag = openMatch[0];
|
772
|
+
const closeTag = closeMatch[0];
|
773
|
+
const startIndex = openTag.length;
|
774
|
+
const endIndex = fullMatch.length - closeTag.length;
|
775
|
+
innerContent = fullMatch.substring(startIndex, endIndex);
|
782
776
|
}
|
783
777
|
else {
|
784
|
-
//
|
785
|
-
|
786
|
-
if (depth === 0) {
|
787
|
-
closeTagStart = nextClose;
|
788
|
-
break;
|
789
|
-
}
|
790
|
-
searchPos = nextClose + closePattern.length;
|
778
|
+
// Fallback for self-closing or malformed tags
|
779
|
+
innerContent = fullMatch.replace(/^<[^>]*>/, '').replace(/<\/[^>]*>$/, '');
|
791
780
|
}
|
792
781
|
}
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
const xmlNode = {
|
797
|
-
id: `${tagPattern}_${openTagStart}_${Date.now()}_${Math.random()}`,
|
798
|
-
tagName: tagPattern,
|
799
|
-
start: openTagStart,
|
800
|
-
end: closeTagStart + closePattern.length,
|
801
|
-
match: fullMatch,
|
802
|
-
processor: blockCreator,
|
803
|
-
groups: [innerContent], // For list processors, group[0] is the inner content
|
804
|
-
children: [],
|
805
|
-
depth: 0,
|
806
|
-
innerContent,
|
807
|
-
replacement: undefined,
|
808
|
-
listProcessor
|
809
|
-
};
|
810
|
-
allMatches.push(xmlNode);
|
782
|
+
catch (error) {
|
783
|
+
console.warn(`Error extracting inner content for ${tagPattern}:`, error);
|
784
|
+
innerContent = fullMatch;
|
811
785
|
}
|
812
|
-
|
786
|
+
const xmlNode = {
|
787
|
+
id: `${tagPattern}_${matchStart}_${Date.now()}_${Math.random()}`,
|
788
|
+
tagName: tagPattern,
|
789
|
+
start: matchStart,
|
790
|
+
end: matchEnd,
|
791
|
+
match: fullMatch,
|
792
|
+
processor: blockCreator,
|
793
|
+
groups: match.slice(1), // Proper regex capture groups (excluding full match)
|
794
|
+
children: [],
|
795
|
+
depth: 0,
|
796
|
+
innerContent,
|
797
|
+
replacement: undefined,
|
798
|
+
listProcessor
|
799
|
+
};
|
800
|
+
allMatches.push(xmlNode);
|
813
801
|
}
|
814
802
|
});
|
815
803
|
// Step 2: Catch ANY remaining XML/HTML tags that weren't processed by specific processors
|
@@ -869,92 +857,126 @@ class NotionAITool {
|
|
869
857
|
}
|
870
858
|
return rootNodes;
|
871
859
|
}
|
872
|
-
//
|
873
|
-
static
|
874
|
-
const
|
875
|
-
const processNode = (
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
860
|
+
// Convert XML tree to HierarchyNode structure for cleaner processing
|
861
|
+
static xmlTreeToHierarchy(nodes) {
|
862
|
+
const hierarchyNodes = [];
|
863
|
+
const processNode = (xmlNode) => {
|
864
|
+
try {
|
865
|
+
// Process children first
|
866
|
+
const childHierarchyNodes = [];
|
867
|
+
for (const child of xmlNode.children) {
|
868
|
+
const childHierarchy = processNode(child);
|
869
|
+
if (childHierarchy) {
|
870
|
+
childHierarchyNodes.push(childHierarchy);
|
871
|
+
}
|
872
|
+
}
|
873
|
+
// For list processors, handle them specially
|
874
|
+
if (xmlNode.listProcessor && (xmlNode.tagName === 'ul' || xmlNode.tagName === 'ol')) {
|
875
|
+
// Extract inner content
|
876
|
+
const tagName = xmlNode.tagName.toLowerCase();
|
882
877
|
const openTagRegex = new RegExp(`^<${tagName}[^>]*>`, 'i');
|
883
878
|
const closeTagRegex = new RegExp(`</${tagName}>$`, 'i');
|
884
|
-
let innerContent =
|
885
|
-
const openMatch =
|
886
|
-
const closeMatch =
|
879
|
+
let innerContent = xmlNode.match;
|
880
|
+
const openMatch = xmlNode.match.match(openTagRegex);
|
881
|
+
const closeMatch = xmlNode.match.match(closeTagRegex);
|
887
882
|
if (openMatch && closeMatch) {
|
888
883
|
const openTag = openMatch[0];
|
889
884
|
const closeTag = closeMatch[0];
|
890
885
|
const startIndex = openTag.length;
|
891
|
-
const endIndex =
|
892
|
-
innerContent =
|
886
|
+
const endIndex = xmlNode.match.length - closeTag.length;
|
887
|
+
innerContent = xmlNode.match.substring(startIndex, endIndex);
|
893
888
|
}
|
894
|
-
//
|
895
|
-
|
896
|
-
return
|
897
|
-
}
|
898
|
-
catch (error) {
|
899
|
-
console.warn(`Error processing list node ${node.tagName}:`, error);
|
900
|
-
return ''; // Remove even on error to prevent artifacts
|
901
|
-
}
|
902
|
-
}
|
903
|
-
// For non-list nodes, process children first (normal hierarchical processing)
|
904
|
-
for (const child of node.children) {
|
905
|
-
const childReplacement = processNode(child);
|
906
|
-
replacements.set(child.id, childReplacement);
|
907
|
-
}
|
908
|
-
// Extract inner content (content between opening and closing tags)
|
909
|
-
let innerContent = '';
|
910
|
-
try {
|
911
|
-
// More robust inner content extraction
|
912
|
-
const tagName = node.tagName.toLowerCase();
|
913
|
-
const openTagRegex = new RegExp(`^<${tagName}[^>]*>`, 'i');
|
914
|
-
const closeTagRegex = new RegExp(`</${tagName}>$`, 'i');
|
915
|
-
const openMatch = node.match.match(openTagRegex);
|
916
|
-
const closeMatch = node.match.match(closeTagRegex);
|
917
|
-
if (openMatch && closeMatch) {
|
918
|
-
const openTag = openMatch[0];
|
919
|
-
const closeTag = closeMatch[0];
|
920
|
-
const startIndex = openTag.length;
|
921
|
-
const endIndex = node.match.length - closeTag.length;
|
922
|
-
innerContent = node.match.substring(startIndex, endIndex);
|
889
|
+
// Build hierarchy structure for the list
|
890
|
+
const listHierarchy = NotionAITool.buildListHierarchy(innerContent, xmlNode.tagName === 'ul' ? 'bulleted_list_item' : 'numbered_list_item', childHierarchyNodes);
|
891
|
+
return listHierarchy;
|
923
892
|
}
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
893
|
+
// For regular nodes, create block and attach children
|
894
|
+
const block = xmlNode.processor(...xmlNode.groups);
|
895
|
+
if (!block)
|
896
|
+
return null;
|
897
|
+
const hierarchyNode = {
|
898
|
+
block,
|
899
|
+
children: childHierarchyNodes,
|
900
|
+
metadata: {
|
901
|
+
sourcePosition: xmlNode.start,
|
902
|
+
xmlNodeId: xmlNode.id,
|
903
|
+
tagName: xmlNode.tagName
|
933
904
|
}
|
934
|
-
}
|
935
|
-
|
936
|
-
catch (error) {
|
937
|
-
console.warn(`Error extracting inner content for ${node.tagName}:`, error);
|
938
|
-
innerContent = node.match;
|
939
|
-
}
|
940
|
-
// Process this node with updated inner content
|
941
|
-
try {
|
942
|
-
// Use blockCreator to create the block
|
943
|
-
const block = node.processor(...node.groups);
|
944
|
-
if (block) {
|
945
|
-
blocks.push(block);
|
946
|
-
}
|
947
|
-
return ''; // Remove completely - no placeholder needed
|
905
|
+
};
|
906
|
+
return hierarchyNode;
|
948
907
|
}
|
949
908
|
catch (error) {
|
950
|
-
console.warn(`Error processing XML node ${
|
951
|
-
return
|
909
|
+
console.warn(`Error processing XML node ${xmlNode.tagName}:`, error);
|
910
|
+
return null;
|
952
911
|
}
|
953
912
|
};
|
954
913
|
// Process all root nodes
|
955
914
|
for (const rootNode of nodes) {
|
956
|
-
const
|
957
|
-
|
915
|
+
const hierarchyNode = processNode(rootNode);
|
916
|
+
if (hierarchyNode) {
|
917
|
+
if (hierarchyNode.block) {
|
918
|
+
hierarchyNodes.push(hierarchyNode);
|
919
|
+
}
|
920
|
+
else if (hierarchyNode.children.length > 0) {
|
921
|
+
// If it's a list container, add its children directly
|
922
|
+
hierarchyNodes.push(...hierarchyNode.children);
|
923
|
+
}
|
924
|
+
}
|
925
|
+
}
|
926
|
+
return hierarchyNodes;
|
927
|
+
}
|
928
|
+
// Convert HierarchyNode structure to final Notion blocks
|
929
|
+
static hierarchyToNotionBlocks(hierarchy) {
|
930
|
+
return hierarchy.map(node => {
|
931
|
+
const block = { ...node.block };
|
932
|
+
if (node.children.length > 0) {
|
933
|
+
const blockData = block[block.type];
|
934
|
+
if (blockData && typeof blockData === 'object') {
|
935
|
+
// Check if this block type can have children
|
936
|
+
const childSupportingTypes = ['bulleted_list_item', 'numbered_list_item', 'toggle', 'quote', 'callout'];
|
937
|
+
if (childSupportingTypes.includes(block.type)) {
|
938
|
+
blockData.children = NotionAITool.hierarchyToNotionBlocks(node.children);
|
939
|
+
}
|
940
|
+
}
|
941
|
+
}
|
942
|
+
return block;
|
943
|
+
});
|
944
|
+
}
|
945
|
+
// Process XML tree using the new hierarchy system
|
946
|
+
static processXMLTreeDepthFirst(nodes, blocks, placeholderCounter) {
|
947
|
+
const replacements = new Map();
|
948
|
+
try {
|
949
|
+
// Convert XML tree to hierarchy structure
|
950
|
+
const hierarchy = NotionAITool.xmlTreeToHierarchy(nodes);
|
951
|
+
// Convert hierarchy to final Notion blocks
|
952
|
+
const finalBlocks = NotionAITool.hierarchyToNotionBlocks(hierarchy);
|
953
|
+
// Add all blocks to the output
|
954
|
+
blocks.push(...finalBlocks);
|
955
|
+
// Mark all nodes as processed (empty replacement)
|
956
|
+
const markProcessed = (nodeList) => {
|
957
|
+
nodeList.forEach(node => {
|
958
|
+
replacements.set(node.id, '');
|
959
|
+
markProcessed(node.children);
|
960
|
+
});
|
961
|
+
};
|
962
|
+
markProcessed(nodes);
|
963
|
+
}
|
964
|
+
catch (error) {
|
965
|
+
console.warn('Error in hierarchy processing, falling back to legacy processing:', error);
|
966
|
+
// Fallback to simple processing if hierarchy fails
|
967
|
+
nodes.forEach(node => {
|
968
|
+
try {
|
969
|
+
const block = node.processor(...node.groups);
|
970
|
+
if (block) {
|
971
|
+
blocks.push(block);
|
972
|
+
}
|
973
|
+
replacements.set(node.id, '');
|
974
|
+
}
|
975
|
+
catch (nodeError) {
|
976
|
+
console.warn(`Error processing fallback node ${node.tagName}:`, nodeError);
|
977
|
+
replacements.set(node.id, '');
|
978
|
+
}
|
979
|
+
});
|
958
980
|
}
|
959
981
|
return replacements;
|
960
982
|
}
|
@@ -1499,46 +1521,189 @@ class NotionAITool {
|
|
1499
1521
|
processed = processed.replace(/\s+/g, ' ').trim();
|
1500
1522
|
return processed;
|
1501
1523
|
}
|
1502
|
-
//
|
1503
|
-
|
1504
|
-
|
1524
|
+
// Build hierarchy structure for lists using HierarchyNode approach
|
1525
|
+
static buildListHierarchy(listContent, listType, childHierarchyNodes) {
|
1526
|
+
try {
|
1527
|
+
// Process each <li> element and build hierarchy
|
1528
|
+
const listItems = NotionAITool.extractListItemsWithBranching(listContent);
|
1529
|
+
const listItemHierarchyNodes = [];
|
1530
|
+
// Map child hierarchy nodes to list items based on position
|
1531
|
+
let childNodeIndex = 0;
|
1532
|
+
for (let i = 0; i < listItems.length; i++) {
|
1533
|
+
const item = listItems[i];
|
1534
|
+
if (!item.text && !item.children.length)
|
1535
|
+
continue;
|
1536
|
+
// Create list item block
|
1537
|
+
const listItemBlock = {
|
1538
|
+
type: listType,
|
1539
|
+
[listType]: {
|
1540
|
+
rich_text: [],
|
1541
|
+
},
|
1542
|
+
};
|
1543
|
+
// Add parent text if present
|
1544
|
+
if (item.text && item.text.trim()) {
|
1545
|
+
const cleanText = NotionAITool.processNestedHtmlInListItem(item.text);
|
1546
|
+
if (cleanText) {
|
1547
|
+
listItemBlock[listType].rich_text = NotionAITool.parseBasicMarkdown(cleanText);
|
1548
|
+
}
|
1549
|
+
}
|
1550
|
+
// Collect child hierarchy nodes for this list item
|
1551
|
+
const itemChildNodes = [];
|
1552
|
+
// Add child hierarchy nodes that belong to this list item
|
1553
|
+
// For now, distribute them evenly - this could be improved with position mapping
|
1554
|
+
const childrenPerItem = Math.floor(childHierarchyNodes.length / listItems.length);
|
1555
|
+
const startIndex = i * childrenPerItem;
|
1556
|
+
const endIndex = i === listItems.length - 1 ? childHierarchyNodes.length : startIndex + childrenPerItem;
|
1557
|
+
for (let j = startIndex; j < endIndex; j++) {
|
1558
|
+
if (j < childHierarchyNodes.length) {
|
1559
|
+
itemChildNodes.push(childHierarchyNodes[j]);
|
1560
|
+
}
|
1561
|
+
}
|
1562
|
+
// Process nested list children (traditional nested lists)
|
1563
|
+
if (item.children.length > 0) {
|
1564
|
+
for (const child of item.children) {
|
1565
|
+
const childListType = child.type === 'ul' ? 'bulleted_list_item' : 'numbered_list_item';
|
1566
|
+
const childListHierarchy = NotionAITool.buildListHierarchy(child.content, childListType, []);
|
1567
|
+
if (childListHierarchy && childListHierarchy.children) {
|
1568
|
+
itemChildNodes.push(...childListHierarchy.children);
|
1569
|
+
}
|
1570
|
+
}
|
1571
|
+
}
|
1572
|
+
// Create hierarchy node for this list item
|
1573
|
+
const listItemHierarchyNode = {
|
1574
|
+
block: listItemBlock,
|
1575
|
+
children: itemChildNodes,
|
1576
|
+
metadata: {
|
1577
|
+
sourcePosition: i,
|
1578
|
+
tagName: listType
|
1579
|
+
}
|
1580
|
+
};
|
1581
|
+
// Only add if it has content or children
|
1582
|
+
const listData = listItemBlock[listType];
|
1583
|
+
if ((listData.rich_text && listData.rich_text.length > 0) || itemChildNodes.length > 0) {
|
1584
|
+
listItemHierarchyNodes.push(listItemHierarchyNode);
|
1585
|
+
}
|
1586
|
+
}
|
1587
|
+
// Return a container that holds all list items
|
1588
|
+
return {
|
1589
|
+
block: null, // No container block needed
|
1590
|
+
children: listItemHierarchyNodes,
|
1591
|
+
metadata: {
|
1592
|
+
tagName: listType === 'bulleted_list_item' ? 'ul' : 'ol'
|
1593
|
+
}
|
1594
|
+
};
|
1595
|
+
}
|
1596
|
+
catch (error) {
|
1597
|
+
console.warn('Error building list hierarchy:', error);
|
1598
|
+
// Fallback: create a simple text block
|
1599
|
+
return {
|
1600
|
+
block: {
|
1601
|
+
type: 'paragraph',
|
1602
|
+
paragraph: {
|
1603
|
+
rich_text: [{ type: 'text', text: { content: 'Error processing list content' } }],
|
1604
|
+
},
|
1605
|
+
},
|
1606
|
+
children: [],
|
1607
|
+
metadata: { tagName: 'paragraph' }
|
1608
|
+
};
|
1609
|
+
}
|
1610
|
+
}
|
1611
|
+
// Helper function to map child blocks to specific list items (legacy support)
|
1612
|
+
static mapChildBlocksToListItems(listContent, childBlocks, childNodes) {
|
1613
|
+
const listItemChildBlocks = new Map();
|
1614
|
+
// Find all <li> positions in the content
|
1615
|
+
const liPositions = [];
|
1616
|
+
let pos = 0;
|
1617
|
+
while (pos < listContent.length) {
|
1618
|
+
const liStart = listContent.indexOf('<li', pos);
|
1619
|
+
if (liStart === -1)
|
1620
|
+
break;
|
1621
|
+
liPositions.push(liStart);
|
1622
|
+
pos = liStart + 3;
|
1623
|
+
}
|
1624
|
+
// Map child nodes to their corresponding list items
|
1625
|
+
childNodes.forEach((childNode, index) => {
|
1626
|
+
// Find which <li> this child node belongs to
|
1627
|
+
let liIndex = -1;
|
1628
|
+
for (let i = 0; i < liPositions.length; i++) {
|
1629
|
+
const liStart = liPositions[i];
|
1630
|
+
const nextLiStart = i + 1 < liPositions.length ? liPositions[i + 1] : listContent.length;
|
1631
|
+
if (childNode.start >= liStart && childNode.start < nextLiStart) {
|
1632
|
+
liIndex = i;
|
1633
|
+
break;
|
1634
|
+
}
|
1635
|
+
}
|
1636
|
+
if (liIndex >= 0 && index < childBlocks.length) {
|
1637
|
+
if (!listItemChildBlocks.has(liIndex)) {
|
1638
|
+
listItemChildBlocks.set(liIndex, []);
|
1639
|
+
}
|
1640
|
+
listItemChildBlocks.get(liIndex).push(childBlocks[index]);
|
1641
|
+
}
|
1642
|
+
});
|
1643
|
+
return listItemChildBlocks;
|
1644
|
+
}
|
1645
|
+
// Enhanced list processor that handles child blocks (legacy support)
|
1646
|
+
static processNestedListWithChildBlocks(listContent, listType, blocks, listItemChildBlocks) {
|
1505
1647
|
try {
|
1506
1648
|
// Process each <li> element as a potential branch point
|
1507
1649
|
const listItems = NotionAITool.extractListItemsWithBranching(listContent);
|
1508
|
-
for (
|
1650
|
+
for (let i = 0; i < listItems.length; i++) {
|
1651
|
+
const item = listItems[i];
|
1509
1652
|
if (!item.text && !item.children.length)
|
1510
1653
|
continue;
|
1511
|
-
// Create list item
|
1654
|
+
// Create list item block
|
1655
|
+
const listItemBlock = {
|
1656
|
+
type: listType,
|
1657
|
+
[listType]: {
|
1658
|
+
rich_text: [],
|
1659
|
+
},
|
1660
|
+
};
|
1661
|
+
// Add parent text if present
|
1512
1662
|
if (item.text && item.text.trim()) {
|
1513
1663
|
const cleanText = NotionAITool.processNestedHtmlInListItem(item.text);
|
1514
1664
|
if (cleanText) {
|
1515
|
-
|
1516
|
-
type: listType,
|
1517
|
-
[listType]: {
|
1518
|
-
rich_text: NotionAITool.parseBasicMarkdown(cleanText),
|
1519
|
-
},
|
1520
|
-
});
|
1665
|
+
listItemBlock[listType].rich_text = NotionAITool.parseBasicMarkdown(cleanText);
|
1521
1666
|
}
|
1522
1667
|
}
|
1523
|
-
//
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1668
|
+
// Collect all child blocks
|
1669
|
+
const allChildBlocks = [];
|
1670
|
+
// Add child blocks from hierarchical processing
|
1671
|
+
const childBlocks = listItemChildBlocks.get(i) || [];
|
1672
|
+
allChildBlocks.push(...childBlocks);
|
1673
|
+
// Process nested list children (traditional nested lists)
|
1674
|
+
if (item.children.length > 0) {
|
1675
|
+
for (const child of item.children) {
|
1676
|
+
const childListType = child.type === 'ul' ? 'bulleted_list_item' : 'numbered_list_item';
|
1677
|
+
NotionAITool.processNestedList(child.content, childListType, allChildBlocks);
|
1678
|
+
}
|
1679
|
+
}
|
1680
|
+
// Add children to the parent block
|
1681
|
+
if (allChildBlocks.length > 0) {
|
1682
|
+
listItemBlock[listType].children = allChildBlocks;
|
1683
|
+
}
|
1684
|
+
// Only add the block if it has text or children
|
1685
|
+
const listData = listItemBlock[listType];
|
1686
|
+
if ((listData.rich_text && listData.rich_text.length > 0) || listData.children) {
|
1687
|
+
blocks.push(listItemBlock);
|
1527
1688
|
}
|
1528
1689
|
}
|
1529
1690
|
}
|
1530
1691
|
catch (error) {
|
1531
|
-
console.warn('Error processing nested list:', error);
|
1692
|
+
console.warn('Error processing nested list with child blocks:', error);
|
1532
1693
|
// Fallback: create a simple text block with the content
|
1533
1694
|
blocks.push({
|
1534
1695
|
type: 'paragraph',
|
1535
1696
|
paragraph: {
|
1536
|
-
rich_text: [{ type: 'text', text: { content: 'Error processing list content' } }],
|
1697
|
+
rich_text: [{ type: 'text', text: { content: 'Error processing list content with child blocks' } }],
|
1537
1698
|
},
|
1538
1699
|
});
|
1539
1700
|
}
|
1540
1701
|
}
|
1541
|
-
//
|
1702
|
+
// Legacy function for backward compatibility
|
1703
|
+
static processNestedList(listContent, listType, blocks, childNodes) {
|
1704
|
+
NotionAITool.processNestedListWithChildBlocks(listContent, listType, blocks, new Map());
|
1705
|
+
}
|
1706
|
+
// Extract list items with proper branching structure - simplified for hierarchical processing
|
1542
1707
|
static extractListItemsWithBranching(content) {
|
1543
1708
|
const items = [];
|
1544
1709
|
let pos = 0;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "n8n-nodes-notion-advanced",
|
3
|
-
"version": "1.2.
|
3
|
+
"version": "1.2.31-beta",
|
4
4
|
"description": "Advanced n8n Notion nodes: Full-featured workflow node + AI Agent Tool for intelligent Notion automation with 25+ block types (BETA)",
|
5
5
|
"scripts": {},
|
6
6
|
"files": [
|