n8n-nodes-notion-advanced 1.2.30-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
|
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;
|
897
892
|
}
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
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);
|
923
|
-
}
|
924
|
-
else {
|
925
|
-
// Fallback for self-closing or malformed tags
|
926
|
-
innerContent = node.match.replace(/^<[^>]*>/, '').replace(/<\/[^>]*>$/, '');
|
927
|
-
}
|
928
|
-
// Replace child nodes in inner content with their processed content
|
929
|
-
for (const child of node.children) {
|
930
|
-
const childReplacement = replacements.get(child.id) || '';
|
931
|
-
if (childReplacement !== undefined && innerContent.includes(child.match)) {
|
932
|
-
innerContent = innerContent.replace(child.match, childReplacement);
|
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,13 +1521,16 @@ class NotionAITool {
|
|
1499
1521
|
processed = processed.replace(/\s+/g, ' ').trim();
|
1500
1522
|
return processed;
|
1501
1523
|
}
|
1502
|
-
//
|
1503
|
-
|
1504
|
-
static processNestedList(listContent, listType, blocks) {
|
1524
|
+
// Build hierarchy structure for lists using HierarchyNode approach
|
1525
|
+
static buildListHierarchy(listContent, listType, childHierarchyNodes) {
|
1505
1526
|
try {
|
1506
|
-
// Process each <li> element
|
1527
|
+
// Process each <li> element and build hierarchy
|
1507
1528
|
const listItems = NotionAITool.extractListItemsWithBranching(listContent);
|
1508
|
-
|
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];
|
1509
1534
|
if (!item.text && !item.children.length)
|
1510
1535
|
continue;
|
1511
1536
|
// Create list item block
|
@@ -1522,18 +1547,140 @@ class NotionAITool {
|
|
1522
1547
|
listItemBlock[listType].rich_text = NotionAITool.parseBasicMarkdown(cleanText);
|
1523
1548
|
}
|
1524
1549
|
}
|
1525
|
-
//
|
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)
|
1526
1563
|
if (item.children.length > 0) {
|
1527
|
-
const childBlocks = [];
|
1528
1564
|
for (const child of item.children) {
|
1529
1565
|
const childListType = child.type === 'ul' ? 'bulleted_list_item' : 'numbered_list_item';
|
1530
|
-
NotionAITool.
|
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) {
|
1647
|
+
try {
|
1648
|
+
// Process each <li> element as a potential branch point
|
1649
|
+
const listItems = NotionAITool.extractListItemsWithBranching(listContent);
|
1650
|
+
for (let i = 0; i < listItems.length; i++) {
|
1651
|
+
const item = listItems[i];
|
1652
|
+
if (!item.text && !item.children.length)
|
1653
|
+
continue;
|
1654
|
+
// Create list item block
|
1655
|
+
const listItemBlock = {
|
1656
|
+
type: listType,
|
1657
|
+
[listType]: {
|
1658
|
+
rich_text: [],
|
1659
|
+
},
|
1660
|
+
};
|
1661
|
+
// Add parent text if present
|
1662
|
+
if (item.text && item.text.trim()) {
|
1663
|
+
const cleanText = NotionAITool.processNestedHtmlInListItem(item.text);
|
1664
|
+
if (cleanText) {
|
1665
|
+
listItemBlock[listType].rich_text = NotionAITool.parseBasicMarkdown(cleanText);
|
1531
1666
|
}
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1667
|
+
}
|
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);
|
1535
1678
|
}
|
1536
1679
|
}
|
1680
|
+
// Add children to the parent block
|
1681
|
+
if (allChildBlocks.length > 0) {
|
1682
|
+
listItemBlock[listType].children = allChildBlocks;
|
1683
|
+
}
|
1537
1684
|
// Only add the block if it has text or children
|
1538
1685
|
const listData = listItemBlock[listType];
|
1539
1686
|
if ((listData.rich_text && listData.rich_text.length > 0) || listData.children) {
|
@@ -1542,17 +1689,21 @@ class NotionAITool {
|
|
1542
1689
|
}
|
1543
1690
|
}
|
1544
1691
|
catch (error) {
|
1545
|
-
console.warn('Error processing nested list:', error);
|
1692
|
+
console.warn('Error processing nested list with child blocks:', error);
|
1546
1693
|
// Fallback: create a simple text block with the content
|
1547
1694
|
blocks.push({
|
1548
1695
|
type: 'paragraph',
|
1549
1696
|
paragraph: {
|
1550
|
-
rich_text: [{ type: 'text', text: { content: 'Error processing list content' } }],
|
1697
|
+
rich_text: [{ type: 'text', text: { content: 'Error processing list content with child blocks' } }],
|
1551
1698
|
},
|
1552
1699
|
});
|
1553
1700
|
}
|
1554
1701
|
}
|
1555
|
-
//
|
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
|
1556
1707
|
static extractListItemsWithBranching(content) {
|
1557
1708
|
const items = [];
|
1558
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": [
|