n8n-nodes-notion-advanced 1.2.20-beta → 1.2.22-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.
@@ -43,10 +43,13 @@ export declare class NotionAITool implements INodeType {
|
|
43
43
|
}[]): string;
|
44
44
|
static getUtf8BytePosition(str: string, charIndex: number): number;
|
45
45
|
static buildXMLTree(content: string, tagProcessors: any[]): XMLNode[];
|
46
|
-
static processXMLTreeDepthFirst(nodes: XMLNode[], blocks: IDataObject[],
|
46
|
+
static processXMLTreeDepthFirst(nodes: XMLNode[], blocks: IDataObject[], placeholderCounter: {
|
47
|
+
value: number;
|
48
|
+
}): Map<string, string>;
|
47
49
|
static applyHierarchicalReplacements(content: string, nodes: XMLNode[], replacements: Map<string, string>): string;
|
48
50
|
static getAllNodesFromTree(nodes: XMLNode[]): XMLNode[];
|
49
51
|
static processXmlTags(content: string, blocks: IDataObject[]): string;
|
52
|
+
static decodeHtmlEntities(content: string): string;
|
50
53
|
static cleanupRemainingHtml(content: string, placeholderPrefix?: string): string;
|
51
54
|
static processNestedHtmlInListItem(content: string): string;
|
52
55
|
static convertInlineHtmlToMarkdown(content: string): string;
|
@@ -2,7 +2,6 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.NotionAITool = void 0;
|
4
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
5
|
-
const crypto_1 = require("crypto");
|
6
5
|
const NotionUtils_1 = require("./NotionUtils");
|
7
6
|
class NotionAITool {
|
8
7
|
constructor() {
|
@@ -480,8 +479,8 @@ class NotionAITool {
|
|
480
479
|
for (let i = 0; i < lines.length; i++) {
|
481
480
|
const line = lines[i];
|
482
481
|
const trimmedLine = line.trim();
|
483
|
-
// Skip completely empty lines and
|
484
|
-
if (!trimmedLine || /
|
482
|
+
// Skip completely empty lines and placeholder artifacts
|
483
|
+
if (!trimmedLine || /__BLOCK_\d+__/.test(trimmedLine) || /^\d+__$/.test(trimmedLine))
|
485
484
|
continue;
|
486
485
|
// Skip lines that contain XML tag patterns (to prevent double processing)
|
487
486
|
const xmlTagPatterns = [
|
@@ -789,9 +788,8 @@ class NotionAITool {
|
|
789
788
|
return rootNodes;
|
790
789
|
}
|
791
790
|
// Process XML tree depth-first (children before parents)
|
792
|
-
static processXMLTreeDepthFirst(nodes, blocks,
|
791
|
+
static processXMLTreeDepthFirst(nodes, blocks, placeholderCounter) {
|
793
792
|
const replacements = new Map();
|
794
|
-
let blockCounter = 0;
|
795
793
|
const processNode = (node) => {
|
796
794
|
// First, process all children depth-first
|
797
795
|
for (const child of node.children) {
|
@@ -835,14 +833,14 @@ class NotionAITool {
|
|
835
833
|
// Handle special list processors
|
836
834
|
if (node.listProcessor && (node.tagName === 'ul' || node.tagName === 'ol')) {
|
837
835
|
node.listProcessor(innerContent, blocks);
|
838
|
-
return
|
836
|
+
return `__BLOCK_${placeholderCounter.value++}__`;
|
839
837
|
}
|
840
838
|
// Use blockCreator to create the block
|
841
839
|
const block = node.processor(...node.groups);
|
842
840
|
if (block) {
|
843
841
|
blocks.push(block);
|
844
842
|
}
|
845
|
-
return
|
843
|
+
return `__BLOCK_${placeholderCounter.value++}__`;
|
846
844
|
}
|
847
845
|
catch (error) {
|
848
846
|
console.warn(`Error processing XML node ${node.tagName}:`, error);
|
@@ -888,8 +886,10 @@ class NotionAITool {
|
|
888
886
|
// New hierarchical XML-like tag processing function
|
889
887
|
static processXmlTags(content, blocks) {
|
890
888
|
let processedContent = content;
|
891
|
-
//
|
892
|
-
|
889
|
+
// First, decode HTML entities to proper XML tags
|
890
|
+
processedContent = NotionAITool.decodeHtmlEntities(processedContent);
|
891
|
+
// Use simple sequential placeholder format: __BLOCK_N__
|
892
|
+
let placeholderCounter = 1; // Start from 1 for cleaner numbering
|
893
893
|
// Debug mode for development
|
894
894
|
const DEBUG_ORDERING = process.env.NODE_ENV === 'development';
|
895
895
|
// Define all tag processors
|
@@ -1153,11 +1153,12 @@ class NotionAITool {
|
|
1153
1153
|
})));
|
1154
1154
|
}
|
1155
1155
|
// Step 2: Process tree depth-first (children before parents)
|
1156
|
-
const
|
1156
|
+
const counterRef = { value: 1 };
|
1157
|
+
const replacements = NotionAITool.processXMLTreeDepthFirst(xmlTree, blocks, counterRef);
|
1157
1158
|
// Step 3: Apply hierarchical replacements to content
|
1158
1159
|
processedContent = NotionAITool.applyHierarchicalReplacements(processedContent, xmlTree, replacements);
|
1159
1160
|
// Step 4: Clean up any remaining HTML tags
|
1160
|
-
processedContent = NotionAITool.cleanupRemainingHtml(processedContent
|
1161
|
+
processedContent = NotionAITool.cleanupRemainingHtml(processedContent);
|
1161
1162
|
if (DEBUG_ORDERING) {
|
1162
1163
|
console.log(`Processed ${xmlTree.length} root XML nodes hierarchically, created ${blocks.length} blocks`);
|
1163
1164
|
}
|
@@ -1180,7 +1181,7 @@ class NotionAITool {
|
|
1180
1181
|
if (block) {
|
1181
1182
|
blocks.push(block);
|
1182
1183
|
}
|
1183
|
-
return
|
1184
|
+
return `__BLOCK_${placeholderCounter++}__`;
|
1184
1185
|
}
|
1185
1186
|
catch (error) {
|
1186
1187
|
console.warn('Error in fallback processor:', error);
|
@@ -1205,34 +1206,46 @@ class NotionAITool {
|
|
1205
1206
|
if (processedMatches.length > 0) {
|
1206
1207
|
processedContent = NotionAITool.optimizedReplace(processedContent, processedMatches);
|
1207
1208
|
}
|
1208
|
-
processedContent = NotionAITool.cleanupRemainingHtml(processedContent
|
1209
|
+
processedContent = NotionAITool.cleanupRemainingHtml(processedContent);
|
1209
1210
|
}
|
1210
1211
|
return processedContent;
|
1211
1212
|
}
|
1213
|
+
// Helper function to decode HTML entities
|
1214
|
+
static decodeHtmlEntities(content) {
|
1215
|
+
const entityMap = {
|
1216
|
+
'<': '<',
|
1217
|
+
'>': '>',
|
1218
|
+
'&': '&',
|
1219
|
+
'"': '"',
|
1220
|
+
''': "'",
|
1221
|
+
''': "'",
|
1222
|
+
' ': ' ',
|
1223
|
+
};
|
1224
|
+
let decoded = content;
|
1225
|
+
Object.entries(entityMap).forEach(([entity, char]) => {
|
1226
|
+
decoded = decoded.replace(new RegExp(entity, 'g'), char);
|
1227
|
+
});
|
1228
|
+
return decoded;
|
1229
|
+
}
|
1212
1230
|
// Cleanup function to remove remaining HTML tags and XML_BLOCK artifacts
|
1213
1231
|
static cleanupRemainingHtml(content, placeholderPrefix) {
|
1214
1232
|
let cleaned = content;
|
1215
|
-
//
|
1233
|
+
// Simplified placeholder cleanup - use one consistent pattern
|
1216
1234
|
if (placeholderPrefix) {
|
1217
|
-
//
|
1218
|
-
const
|
1219
|
-
|
1220
|
-
|
1221
|
-
new RegExp(`${placeholderPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\d+`, 'g')
|
1222
|
-
];
|
1223
|
-
placeholderPatterns.forEach(pattern => {
|
1224
|
-
cleaned = cleaned.replace(pattern, '');
|
1225
|
-
});
|
1235
|
+
// Clean up our specific placeholder format: __XML_{uuid8}_{number}__
|
1236
|
+
const escapedPrefix = placeholderPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
1237
|
+
const placeholderPattern = new RegExp(`${escapedPrefix}\\d+__`, 'g');
|
1238
|
+
cleaned = cleaned.replace(placeholderPattern, '');
|
1226
1239
|
}
|
1227
1240
|
// Comprehensive fallback cleanup for all possible placeholder formats
|
1228
|
-
const
|
1229
|
-
/
|
1230
|
-
|
1231
|
-
|
1232
|
-
/
|
1233
|
-
/
|
1241
|
+
const placeholderPatterns = [
|
1242
|
+
/__XML_[a-f0-9]{8}_\d+__/g, // Standard format: __XML_abc12345_1__
|
1243
|
+
/\b[A-Z]{2}[a-z0-9]{8,12}_+\b/g, // Variations like "MLb82d670450__"
|
1244
|
+
/\b[A-Za-z]{2,4}[a-f0-9]{6,12}_+\b/g, // More flexible pattern matching
|
1245
|
+
/_[a-f0-9]{8,12}_\d+_*/g, // Underscore variations
|
1246
|
+
/[a-f0-9]{8,12}_\d+__/g, // Without prefix
|
1234
1247
|
];
|
1235
|
-
|
1248
|
+
placeholderPatterns.forEach(pattern => {
|
1236
1249
|
cleaned = cleaned.replace(pattern, '');
|
1237
1250
|
});
|
1238
1251
|
// Remove entire lines containing XML content to prevent double processing
|
@@ -1283,20 +1296,6 @@ class NotionAITool {
|
|
1283
1296
|
cleaned = cleaned.replace(/^\s*[\r\n]/gm, '');
|
1284
1297
|
// Remove multiple consecutive line breaks
|
1285
1298
|
cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
|
1286
|
-
// Remove lines that contain only XML_BLOCK artifacts (more patterns)
|
1287
|
-
const artifactPatterns = [
|
1288
|
-
/^.*__XML_BLOCK_\d+__.*$/gm,
|
1289
|
-
/^.*__XML_[a-f0-9]{8}_\d+__.*$/gm,
|
1290
|
-
/^.*_XML_[a-f0-9]{8}_\d+_.*$/gm,
|
1291
|
-
/^.*__XML_[a-f0-9-]+_\d+__.*$/gm,
|
1292
|
-
/^.*_XML_[a-f0-9-]+_\d+_.*$/gm
|
1293
|
-
];
|
1294
|
-
artifactPatterns.forEach(pattern => {
|
1295
|
-
cleaned = cleaned.replace(pattern, '');
|
1296
|
-
});
|
1297
|
-
// Final cleanup of any remaining isolated placeholder patterns
|
1298
|
-
cleaned = cleaned.replace(/\b_+XML_[a-f0-9-]+_\d+_*\b/g, '');
|
1299
|
-
cleaned = cleaned.replace(/\b_*XML_[a-f0-9-]+_\d+_+\b/g, '');
|
1300
1299
|
return cleaned.trim();
|
1301
1300
|
}
|
1302
1301
|
// Helper function to process nested HTML elements in list items
|
@@ -1365,12 +1364,12 @@ class NotionAITool {
|
|
1365
1364
|
// Helper function to convert inline HTML to markdown
|
1366
1365
|
static convertInlineHtmlToMarkdown(content) {
|
1367
1366
|
let processed = content;
|
1368
|
-
// Convert HTML formatting tags to markdown equivalents
|
1367
|
+
// Convert HTML formatting tags to markdown equivalents - process in order to handle nested tags
|
1369
1368
|
const htmlToMarkdown = [
|
1370
1369
|
{ regex: /<strong\s*[^>]*>(.*?)<\/strong>/gis, replacement: '**$1**' },
|
1371
1370
|
{ regex: /<b\s*[^>]*>(.*?)<\/b>/gis, replacement: '**$1**' },
|
1372
|
-
{ regex: /<em\s*[^>]*>(.*?)<\/em>/gis, replacement: '
|
1373
|
-
{ regex: /<i\s*[^>]*>(.*?)<\/i>/gis, replacement: '
|
1371
|
+
{ regex: /<em\s*[^>]*>(.*?)<\/em>/gis, replacement: '_$1_' }, // Use underscore to avoid conflicts
|
1372
|
+
{ regex: /<i\s*[^>]*>(.*?)<\/i>/gis, replacement: '_$1_' }, // Use underscore to avoid conflicts
|
1374
1373
|
{ regex: /<code\s*[^>]*>(.*?)<\/code>/gis, replacement: '`$1`' },
|
1375
1374
|
{ regex: /<a\s+href="([^"]*)"[^>]*>(.*?)<\/a>/gis, replacement: '[$2]($1)' },
|
1376
1375
|
{ regex: /<u\s*[^>]*>(.*?)<\/u>/gis, replacement: '$1' }, // Notion doesn't support underline
|
@@ -1512,7 +1511,8 @@ class NotionAITool {
|
|
1512
1511
|
{ regex: /\[([^\]]+)\]\(([^)]+)\)/g, type: 'link' }, // [text](url)
|
1513
1512
|
{ regex: /\*\*\*([^*]+)\*\*\*/g, type: 'bold_italic' }, // ***bold italic***
|
1514
1513
|
{ regex: /\*\*([^*]+)\*\*/g, type: 'bold' }, // **bold**
|
1515
|
-
{ regex:
|
1514
|
+
{ regex: /_([^_]+)_/g, type: 'italic' }, // _italic_ (changed from *)
|
1515
|
+
{ regex: /\*([^*]+)\*/g, type: 'italic' }, // *italic* (keep for backward compatibility)
|
1516
1516
|
{ regex: /~~([^~]+)~~/g, type: 'strikethrough' }, // ~~strikethrough~~
|
1517
1517
|
{ regex: /`([^`]+)`/g, type: 'code' }, // `code`
|
1518
1518
|
];
|
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.22-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": [
|