n8n-nodes-notion-advanced 1.2.33-beta → 1.2.34-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.
@@ -1544,7 +1544,6 @@ class NotionAITool {
|
|
1544
1544
|
}
|
1545
1545
|
// Build hierarchy structure for lists using HierarchyNode approach
|
1546
1546
|
static buildListHierarchy(listContent, listType, childHierarchyNodes) {
|
1547
|
-
var _a;
|
1548
1547
|
try {
|
1549
1548
|
// Process each <li> element and build hierarchy
|
1550
1549
|
const listItems = NotionAITool.extractListItemsWithBranching(listContent);
|
@@ -1553,7 +1552,7 @@ class NotionAITool {
|
|
1553
1552
|
const listItemPositions = NotionAITool.getListItemPositions(listContent);
|
1554
1553
|
for (let i = 0; i < listItems.length; i++) {
|
1555
1554
|
const item = listItems[i];
|
1556
|
-
if (!item.text && !item.children.length)
|
1555
|
+
if (!item.text && !item.children.length && !(item.extractedChildBlocks && item.extractedChildBlocks.length > 0))
|
1557
1556
|
continue;
|
1558
1557
|
// Create list item block
|
1559
1558
|
const listItemBlock = {
|
@@ -1571,19 +1570,24 @@ class NotionAITool {
|
|
1571
1570
|
}
|
1572
1571
|
// Collect child hierarchy nodes for this list item based on position mapping
|
1573
1572
|
const itemChildNodes = [];
|
1574
|
-
//
|
1575
|
-
|
1576
|
-
|
1577
|
-
const
|
1578
|
-
for (const
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1573
|
+
// Add extracted child blocks (from XML tags within list items)
|
1574
|
+
// These are the primary source for child blocks in list items
|
1575
|
+
if (item.extractedChildBlocks && Array.isArray(item.extractedChildBlocks)) {
|
1576
|
+
const extractedBlocks = item.extractedChildBlocks;
|
1577
|
+
for (const block of extractedBlocks) {
|
1578
|
+
itemChildNodes.push({
|
1579
|
+
block,
|
1580
|
+
children: [],
|
1581
|
+
metadata: {
|
1582
|
+
sourcePosition: i,
|
1583
|
+
tagName: block.type
|
1584
|
+
}
|
1585
|
+
});
|
1585
1586
|
}
|
1586
1587
|
}
|
1588
|
+
// Note: We prioritize extractedChildBlocks over childHierarchyNodes for list items
|
1589
|
+
// since list-specific processing in extractListItemsWithBranching is more accurate
|
1590
|
+
// for handling child blocks within <li> elements
|
1587
1591
|
// Process nested list children (traditional nested lists)
|
1588
1592
|
if (item.children.length > 0) {
|
1589
1593
|
for (const child of item.children) {
|
@@ -1603,7 +1607,7 @@ class NotionAITool {
|
|
1603
1607
|
tagName: listType
|
1604
1608
|
}
|
1605
1609
|
};
|
1606
|
-
// Only add if it has content or children
|
1610
|
+
// Only add if it has content or children (including extracted child blocks)
|
1607
1611
|
const listData = listItemBlock[listType];
|
1608
1612
|
if ((listData.rich_text && listData.rich_text.length > 0) || itemChildNodes.length > 0) {
|
1609
1613
|
listItemHierarchyNodes.push(listItemHierarchyNode);
|
@@ -1830,8 +1834,9 @@ class NotionAITool {
|
|
1830
1834
|
continue;
|
1831
1835
|
}
|
1832
1836
|
const item = { text: '', children: [] };
|
1833
|
-
// STEP 1:
|
1837
|
+
// STEP 1: Extract and convert child block XML to actual blocks before removing from parent text
|
1834
1838
|
let parentTextContent = fullItemContent;
|
1839
|
+
const extractedChildBlocks = [];
|
1835
1840
|
// List of XML tags that create child blocks (these should be removed from parent text)
|
1836
1841
|
const childBlockTags = [
|
1837
1842
|
'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
@@ -1839,14 +1844,181 @@ class NotionAITool {
|
|
1839
1844
|
'todo', 'toggle', 'image', 'embed', 'bookmark',
|
1840
1845
|
'equation', 'divider'
|
1841
1846
|
];
|
1842
|
-
//
|
1847
|
+
// Extract child blocks first, then remove from parent text
|
1843
1848
|
childBlockTags.forEach(tag => {
|
1844
|
-
//
|
1849
|
+
// Extract and process paired tags first
|
1850
|
+
const pairedRegex = new RegExp(`<${tag}[^>]*>(.*?)<\\/${tag}>`, 'gis');
|
1851
|
+
let match;
|
1852
|
+
while ((match = pairedRegex.exec(parentTextContent)) !== null) {
|
1853
|
+
const fullMatch = match[0];
|
1854
|
+
const content = match[1];
|
1855
|
+
// Create child block based on tag type
|
1856
|
+
try {
|
1857
|
+
let childBlock = null;
|
1858
|
+
switch (tag) {
|
1859
|
+
case 'embed':
|
1860
|
+
childBlock = {
|
1861
|
+
type: 'embed',
|
1862
|
+
embed: { url: content.trim() }
|
1863
|
+
};
|
1864
|
+
break;
|
1865
|
+
case 'bookmark':
|
1866
|
+
childBlock = {
|
1867
|
+
type: 'bookmark',
|
1868
|
+
bookmark: { url: content.trim() }
|
1869
|
+
};
|
1870
|
+
break;
|
1871
|
+
case 'p':
|
1872
|
+
const markdownContent = NotionAITool.convertInlineHtmlToMarkdown(content.trim());
|
1873
|
+
childBlock = {
|
1874
|
+
type: 'paragraph',
|
1875
|
+
paragraph: { rich_text: NotionAITool.parseBasicMarkdown(markdownContent) }
|
1876
|
+
};
|
1877
|
+
break;
|
1878
|
+
case 'h1':
|
1879
|
+
case 'h2':
|
1880
|
+
case 'h3':
|
1881
|
+
const headingType = `heading_${tag.charAt(1)}`;
|
1882
|
+
childBlock = {
|
1883
|
+
type: headingType,
|
1884
|
+
[headingType]: { rich_text: [{ type: 'text', text: { content: content.trim() } }] }
|
1885
|
+
};
|
1886
|
+
break;
|
1887
|
+
case 'quote':
|
1888
|
+
case 'blockquote':
|
1889
|
+
childBlock = {
|
1890
|
+
type: 'quote',
|
1891
|
+
quote: { rich_text: NotionAITool.parseBasicMarkdown(content.trim()) }
|
1892
|
+
};
|
1893
|
+
break;
|
1894
|
+
case 'callout':
|
1895
|
+
// Extract type attribute if present
|
1896
|
+
const typeMatch = fullMatch.match(/type="([^"]*)"/);
|
1897
|
+
const calloutType = typeMatch ? typeMatch[1] : 'info';
|
1898
|
+
const emoji = NotionAITool.getCalloutEmoji(calloutType.toLowerCase());
|
1899
|
+
const color = NotionAITool.getCalloutColor(calloutType.toLowerCase());
|
1900
|
+
childBlock = {
|
1901
|
+
type: 'callout',
|
1902
|
+
callout: {
|
1903
|
+
rich_text: NotionAITool.parseBasicMarkdown(content.trim()),
|
1904
|
+
icon: { type: 'emoji', emoji },
|
1905
|
+
color: color
|
1906
|
+
}
|
1907
|
+
};
|
1908
|
+
break;
|
1909
|
+
case 'code':
|
1910
|
+
case 'pre':
|
1911
|
+
// Extract language attribute if present
|
1912
|
+
const langMatch = fullMatch.match(/language="([^"]*)"/);
|
1913
|
+
const language = langMatch ? langMatch[1] : 'plain_text';
|
1914
|
+
childBlock = {
|
1915
|
+
type: 'code',
|
1916
|
+
code: {
|
1917
|
+
rich_text: [{ type: 'text', text: { content: content.trim() } }],
|
1918
|
+
language: language === 'plain text' ? 'plain_text' : language
|
1919
|
+
}
|
1920
|
+
};
|
1921
|
+
break;
|
1922
|
+
case 'todo':
|
1923
|
+
// Extract checked attribute if present
|
1924
|
+
const checkedMatch = fullMatch.match(/checked="([^"]*)"/);
|
1925
|
+
const isChecked = checkedMatch ? checkedMatch[1].toLowerCase() === 'true' : false;
|
1926
|
+
childBlock = {
|
1927
|
+
type: 'to_do',
|
1928
|
+
to_do: {
|
1929
|
+
rich_text: NotionAITool.parseBasicMarkdown(content.trim()),
|
1930
|
+
checked: isChecked
|
1931
|
+
}
|
1932
|
+
};
|
1933
|
+
break;
|
1934
|
+
case 'toggle':
|
1935
|
+
childBlock = {
|
1936
|
+
type: 'toggle',
|
1937
|
+
toggle: {
|
1938
|
+
rich_text: NotionAITool.parseBasicMarkdown(content.trim()),
|
1939
|
+
children: []
|
1940
|
+
}
|
1941
|
+
};
|
1942
|
+
break;
|
1943
|
+
case 'equation':
|
1944
|
+
childBlock = {
|
1945
|
+
type: 'equation',
|
1946
|
+
equation: { expression: content.trim() }
|
1947
|
+
};
|
1948
|
+
break;
|
1949
|
+
case 'image':
|
1950
|
+
// Extract src and alt attributes
|
1951
|
+
const srcMatch = fullMatch.match(/src="([^"]*)"/);
|
1952
|
+
const altMatch = fullMatch.match(/alt="([^"]*)"/);
|
1953
|
+
const src = srcMatch ? srcMatch[1] : '';
|
1954
|
+
const alt = altMatch ? altMatch[1] : '';
|
1955
|
+
const caption = content.trim() || alt;
|
1956
|
+
childBlock = {
|
1957
|
+
type: 'image',
|
1958
|
+
image: {
|
1959
|
+
type: 'external',
|
1960
|
+
external: { url: src },
|
1961
|
+
caption: caption ? NotionAITool.parseBasicMarkdown(caption) : []
|
1962
|
+
}
|
1963
|
+
};
|
1964
|
+
break;
|
1965
|
+
case 'divider':
|
1966
|
+
childBlock = {
|
1967
|
+
type: 'divider',
|
1968
|
+
divider: {}
|
1969
|
+
};
|
1970
|
+
break;
|
1971
|
+
}
|
1972
|
+
if (childBlock) {
|
1973
|
+
extractedChildBlocks.push(childBlock);
|
1974
|
+
}
|
1975
|
+
}
|
1976
|
+
catch (error) {
|
1977
|
+
console.warn(`Error creating child block for tag ${tag}:`, error);
|
1978
|
+
}
|
1979
|
+
}
|
1980
|
+
// Handle self-closing tags (mainly for divider, image)
|
1845
1981
|
const selfClosingRegex = new RegExp(`<${tag}[^>]*\\/>`, 'gis');
|
1846
|
-
|
1982
|
+
let selfMatch;
|
1983
|
+
while ((selfMatch = selfClosingRegex.exec(parentTextContent)) !== null) {
|
1984
|
+
const fullMatch = selfMatch[0];
|
1985
|
+
try {
|
1986
|
+
let childBlock = null;
|
1987
|
+
if (tag === 'divider') {
|
1988
|
+
childBlock = {
|
1989
|
+
type: 'divider',
|
1990
|
+
divider: {}
|
1991
|
+
};
|
1992
|
+
}
|
1993
|
+
else if (tag === 'image') {
|
1994
|
+
// Extract src and alt attributes
|
1995
|
+
const srcMatch = fullMatch.match(/src="([^"]*)"/);
|
1996
|
+
const altMatch = fullMatch.match(/alt="([^"]*)"/);
|
1997
|
+
const src = srcMatch ? srcMatch[1] : '';
|
1998
|
+
const alt = altMatch ? altMatch[1] : '';
|
1999
|
+
childBlock = {
|
2000
|
+
type: 'image',
|
2001
|
+
image: {
|
2002
|
+
type: 'external',
|
2003
|
+
external: { url: src },
|
2004
|
+
caption: alt ? NotionAITool.parseBasicMarkdown(alt) : []
|
2005
|
+
}
|
2006
|
+
};
|
2007
|
+
}
|
2008
|
+
if (childBlock) {
|
2009
|
+
extractedChildBlocks.push(childBlock);
|
2010
|
+
}
|
2011
|
+
}
|
2012
|
+
catch (error) {
|
2013
|
+
console.warn(`Error creating self-closing child block for tag ${tag}:`, error);
|
2014
|
+
}
|
2015
|
+
}
|
2016
|
+
// Now remove both paired and self-closing tags from parent text
|
1847
2017
|
parentTextContent = parentTextContent.replace(pairedRegex, '');
|
1848
2018
|
parentTextContent = parentTextContent.replace(selfClosingRegex, '');
|
1849
2019
|
});
|
2020
|
+
// Store extracted child blocks in the item for later use
|
2021
|
+
item.extractedChildBlocks = extractedChildBlocks;
|
1850
2022
|
// STEP 2: Process the content to separate remaining text from nested lists
|
1851
2023
|
let contentPos = 0;
|
1852
2024
|
let textParts = [];
|
@@ -1932,8 +2104,8 @@ class NotionAITool {
|
|
1932
2104
|
item.text = cleanText;
|
1933
2105
|
}
|
1934
2106
|
}
|
1935
|
-
// Only add items that have either text or
|
1936
|
-
if (item.text.trim() || item.children.length > 0) {
|
2107
|
+
// Only add items that have either text, children, or extracted child blocks
|
2108
|
+
if (item.text.trim() || item.children.length > 0 || (item.extractedChildBlocks && item.extractedChildBlocks.length > 0)) {
|
1937
2109
|
items.push(item);
|
1938
2110
|
}
|
1939
2111
|
pos = liEnd + 5; // Move past </li>
|
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.34-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": [
|