Added plan.md with complete architecture for format-agnostic content generation: - Support for Markdown, HTML, Plain Text, JSON formats - New FormatExporter module with neutral data structure - Integration strategy with existing ContentAssembly and ArticleStorage - Bonus features: SEO metadata generation, readability scoring, WordPress Gutenberg format - Implementation roadmap with 4 phases (6h total estimated) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
202 lines
7.6 KiB
JavaScript
202 lines
7.6 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
|
|
}; |