seo-generator-server/lib/ContentAssembly.js
2025-09-03 15:29:19 +08:00

202 lines
7.4 KiB
JavaScript

// ========================================
// FICHIER: ContentAssembly.js
// Description: Assemblage et nettoyage du contenu XML
// ========================================
const { logSh } = require('./ErrorReporting'); // Using unified logSh from ErrorReporting
/**
* Nettoie les balises <strong> du template XML
* @param {string} xmlString - Le contenu XML à nettoyer
* @returns {string} - XML nettoyé
*/
function cleanStrongTags(xmlString) {
logSh('Nettoyage balises <strong> du template...', 'DEBUG');
// Enlever toutes les balises <strong> et </strong>
let cleaned = xmlString.replace(/<\/?strong>/g, '');
// Log du nettoyage
const strongCount = (xmlString.match(/<\/?strong>/g) || []).length;
if (strongCount > 0) {
logSh(`${strongCount} balises <strong> supprimées`, 'INFO');
}
return cleaned;
}
/**
* Remplace toutes les variables CSV dans le XML
* @param {string} xmlString - Le contenu XML
* @param {object} csvData - Les données CSV
* @returns {string} - XML avec variables remplacées
*/
function replaceAllCSVVariables(xmlString, csvData) {
logSh('Remplacement variables CSV...', 'DEBUG');
let result = xmlString;
// Variables simples
result = result.replace(/\{\{T0\}\}/g, csvData.t0 || '');
result = result.replace(/\{\{MC0\}\}/g, csvData.mc0 || '');
result = result.replace(/\{\{T-1\}\}/g, csvData.tMinus1 || '');
result = result.replace(/\{\{L-1\}\}/g, csvData.lMinus1 || '');
logSh(`Variables simples remplacées: T0="${csvData.t0}", MC0="${csvData.mc0}"`, 'DEBUG');
// Variables multiples
const mcPlus1 = (csvData.mcPlus1 || '').split(',').map(s => s.trim());
const tPlus1 = (csvData.tPlus1 || '').split(',').map(s => s.trim());
const lPlus1 = (csvData.lPlus1 || '').split(',').map(s => s.trim());
logSh(`Variables multiples: MC+1[${mcPlus1.length}], T+1[${tPlus1.length}], L+1[${lPlus1.length}]`, 'DEBUG');
// Remplacer MC+1_1, MC+1_2, etc.
for (let i = 1; i <= 6; i++) {
const mcValue = mcPlus1[i-1] || `[MC+1_${i} non défini]`;
const tValue = tPlus1[i-1] || `[T+1_${i} non défini]`;
const lValue = lPlus1[i-1] || `[L+1_${i} non défini]`;
result = result.replace(new RegExp(`\\{\\{MC\\+1_${i}\\}\\}`, 'g'), mcValue);
result = result.replace(new RegExp(`\\{\\{T\\+1_${i}\\}\\}`, 'g'), tValue);
result = result.replace(new RegExp(`\\{\\{L\\+1_${i}\\}\\}`, 'g'), lValue);
if (mcPlus1[i-1]) {
logSh(`MC+1_${i} = "${mcValue}"`, 'DEBUG');
}
}
// Vérifier qu'il ne reste pas de variables non remplacées
const remainingVars = (result.match(/\{\{[^}]+\}\}/g) || []);
if (remainingVars.length > 0) {
logSh(`ATTENTION: Variables non remplacées: ${remainingVars.join(', ')}`, 'WARNING');
}
logSh('Toutes les variables CSV remplacées', 'INFO');
return result;
}
/**
* Injecte le contenu généré dans le XML final
* @param {string} cleanXML - XML nettoyé
* @param {object} generatedContent - Contenu généré par tag
* @param {array} elements - Éléments extraits
* @returns {string} - XML final avec contenu injecté
*/
function injectGeneratedContent(cleanXML, generatedContent, elements) {
logSh('🔍 === DEBUG INJECTION MAPPING ===', 'DEBUG');
logSh(`XML reçu: ${cleanXML.length} caractères`, 'DEBUG');
logSh(`Contenu généré: ${Object.keys(generatedContent).length} éléments`, 'DEBUG');
logSh(`Éléments fournis: ${elements.length} éléments`, 'DEBUG');
// Debug: montrer le XML
logSh(`🔍 XML début: ${cleanXML}`, 'DEBUG');
// Debug: montrer le contenu généré
Object.keys(generatedContent).forEach(key => {
logSh(`🔍 Généré [${key}]: "${generatedContent[key]}"`, 'DEBUG');
});
// Debug: montrer les éléments
elements.forEach((element, i) => {
logSh(`🔍 Element ${i+1}: originalTag="${element.originalTag}", originalFullMatch="${element.originalFullMatch}"`, 'DEBUG');
});
let finalXML = cleanXML;
// Créer un mapping tag pur → tag original complet
const tagMapping = {};
elements.forEach(element => {
tagMapping[element.originalTag] = element.originalFullMatch || element.originalTag;
});
logSh(`🔍 TagMapping créé: ${JSON.stringify(tagMapping, null, 2)}`, 'DEBUG');
// Remplacer en utilisant les tags originaux complets
Object.keys(generatedContent).forEach(pureTag => {
const content = generatedContent[pureTag];
logSh(`🔍 === TRAITEMENT TAG: ${pureTag} ===`, 'DEBUG');
logSh(`🔍 Contenu à injecter: "${content}"`, 'DEBUG');
// Trouver le tag original complet dans le XML
const originalTag = findOriginalTagInXML(finalXML, pureTag);
logSh(`🔍 Tag original trouvé: ${originalTag ? originalTag : 'AUCUN'}`, 'DEBUG');
if (originalTag) {
const beforeLength = finalXML.length;
finalXML = finalXML.replace(originalTag, content);
const afterLength = finalXML.length;
if (beforeLength !== afterLength) {
logSh(`✅ SUCCÈS: Remplacé ${originalTag} par contenu (${afterLength - beforeLength + originalTag.length} chars)`, 'DEBUG');
} else {
logSh(`❌ ÉCHEC: Replace n'a pas fonctionné pour ${originalTag}`, 'DEBUG');
}
} else {
// Fallback : essayer avec le tag pur
const beforeLength = finalXML.length;
finalXML = finalXML.replace(pureTag, content);
const afterLength = finalXML.length;
logSh(`⚠ FALLBACK ${pureTag}: remplacement ${beforeLength !== afterLength ? 'RÉUSSI' : 'ÉCHOUÉ'}`, 'DEBUG');
logSh(`⚠ Contenu fallback: "${content}"`, 'DEBUG');
}
});
// Vérifier les tags restants
const remainingTags = (finalXML.match(/\|[^|]*\|/g) || []);
if (remainingTags.length > 0) {
logSh(`ATTENTION: ${remainingTags.length} tags non remplacés: ${remainingTags.slice(0, 3).join(', ')}...`, 'WARNING');
}
logSh('Injection terminée', 'INFO');
return finalXML;
}
/**
* Helper pour trouver le tag original complet dans le XML
* @param {string} xmlString - Contenu XML
* @param {string} pureTag - Tag pur à rechercher
* @returns {string|null} - Tag original trouvé ou null
*/
function findOriginalTagInXML(xmlString, pureTag) {
logSh(`🔍 === RECHERCHE TAG DANS XML ===`, 'DEBUG');
logSh(`🔍 Tag pur recherché: "${pureTag}"`, 'DEBUG');
// Extraire le nom du tag pur : |Titre_H1_1| → Titre_H1_1
const tagName = pureTag.replace(/\|/g, '');
logSh(`🔍 Nom tag extrait: "${tagName}"`, 'DEBUG');
// Chercher tous les tags qui commencent par ce nom (avec espaces optionnels)
const regex = new RegExp(`\\|\\s*${tagName}[^|]*\\|`, 'g');
logSh(`🔍 Regex utilisée: ${regex}`, 'DEBUG');
// Debug: montrer tous les tags présents dans le XML
const allTags = xmlString.match(/\|[^|]*\|/g) || [];
logSh(`🔍 Tags présents dans XML: ${allTags.length}`, 'DEBUG');
allTags.forEach((tag, i) => {
logSh(`🔍 ${i+1}. "${tag}"`, 'DEBUG');
});
const matches = xmlString.match(regex);
logSh(`🔍 Matches trouvés: ${matches ? matches.length : 0}`, 'DEBUG');
if (matches && matches.length > 0) {
logSh(`🔍 Premier match: "${matches[0]}"`, 'DEBUG');
logSh(`✅ Tag original trouvé pour ${pureTag}: ${matches[0]}`, 'DEBUG');
return matches[0];
}
logSh(`❌ Aucun tag original trouvé pour ${pureTag}`, 'DEBUG');
return null;
}
// ============= EXPORTS =============
module.exports = {
cleanStrongTags,
replaceAllCSVVariables,
injectGeneratedContent,
findOriginalTagInXML
};