/** * Script de test pour vérifier que tous les partials Handlebars sont correctement préchargés * Exécuter avec : node test-templates.js */ const fs = require('fs'); const path = require('path'); // Fonction pour simuler le chargement des templates function loadTemplates(templatePaths) { const loaded = []; const errors = []; for (const templatePath of templatePaths) { // Remplacer le préfixe systems/ par le chemin réel const realPath = templatePath.replace('systems/fvtt-mournblade-cyd-2-0/templates/', 'templates/'); const fullPath = path.join(__dirname, realPath); // Vérifier si le fichier existe if (fs.existsSync(fullPath)) { loaded.push(templatePath); } else { errors.push(`Template introuvable: ${templatePath} (cherché: ${fullPath})`); } } return { loaded, errors }; } // Fonction pour extraire les partials utilisés dans les templates function extractPartialsFromTemplate(content, basePath) { const partialRegex = /{{\s*>[\s\S]*?systems\/fvtt-mournblade-cyd-2-0\/templates\/([^\s]+\.hbs)\s*}}/g; const partials = new Set(); let match; while ((match = partialRegex.exec(content)) !== null) { partials.add(match[1]); } return Array.from(partials); } // Fonction pour scanner tous les templates et trouver les partials utilisés function scanAllTemplates() { const templatesDir = path.join(__dirname, 'templates'); const files = fs.readdirSync(templatesDir).filter(f => f.endsWith('.hbs')); const allPartials = new Set(); for (const file of files) { const filePath = path.join(templatesDir, file); const content = fs.readFileSync(filePath, 'utf8'); const partials = extractPartialsFromTemplate(content); partials.forEach(p => allPartials.add(p)); } return Array.from(allPartials); } // Liste actuelle des templates préchargés const currentPreloadedTemplates = [ 'systems/fvtt-mournblade-cyd-2-0/templates/editor-notes-gm.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-active-effects.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-effects.hbs', 'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs', ]; // Exécuter le test console.log('=== Test de chargement des templates Handlebars ===\n'); // 1. Vérifier que tous les templates préchargés existent console.log('1. Vérification des templates préchargés :'); const { loaded, errors } = loadTemplates(currentPreloadedTemplates); if (errors.length > 0) { console.log(' ❌ Erreurs trouvées :'); errors.forEach(err => console.log(` - ${err}`)); } else { console.log(' ✅ Tous les templates préchargés existent'); loaded.forEach(t => console.log(` ✓ ${t}`)); } // 2. Scanner tous les templates pour trouver les partials utilisés console.log('\n2. Scan des partials utilisés dans les templates :'); const usedPartials = scanAllTemplates(); usedPartials.forEach(p => console.log(` - ${p}`)); // 3. Vérifier que tous les partials utilisés sont préchargés console.log('\n3. Vérification que tous les partials utilisés sont préchargés :'); const preloadedPartials = currentPreloadedTemplates.map(p => path.basename(p)); const missingPartials = usedPartials.filter(p => !preloadedPartials.includes(p)); if (missingPartials.length > 0) { console.log(' ❌ Partials manquants dans le préchargement :'); missingPartials.forEach(p => console.log(` - ${p}`)); } else { console.log(' ✅ Tous les partials utilisés sont préchargés'); } // 4. Vérification JSON console.log('\n4. Vérification du fichier lang/fr.json :'); try { const frJson = require('./lang/fr.json'); console.log(' ✅ Le fichier lang/fr.json est valide'); } catch (err) { console.log(' ❌ Erreur dans lang/fr.json :', err.message); } // 5. Vérification des appels API dépréciés console.log('\n5. Vérification des appels API dépréciés (ActiveEffectDialog) :'); const deprecatedPattern = /foundry\.applications\.api\.ActiveEffectDialog/g; const jsFiles = [ 'modules/applications/sheets/base-actor-sheet.mjs', 'modules/applications/sheets/base-item-sheet.mjs' ]; let deprecatedFound = false; for (const file of jsFiles) { try { const content = fs.readFileSync(path.join(__dirname, file), 'utf8'); if (deprecatedPattern.test(content)) { console.log(` ❌ Fichier ${file} contient ActiveEffectDialog (déprécié)`); deprecatedFound = true; } } catch (err) { // Fichier introuvable, ignorer } } if (!deprecatedFound) { console.log(' ✅ Aucun appel à ActiveEffectDialog (API dépréciée) trouvé'); } // 6. Vérification des références à l'icône manquante effect.webp console.log('\n6. Vérification des références à effect.webp (icône manquante) :'); const effectWebpPattern = /effect\.webp/g; const allJsFiles = [ 'modules/applications/sheets/base-actor-sheet.mjs', 'modules/applications/sheets/base-item-sheet.mjs', 'modules/mournblade-cyd2-effects.js' ]; const hbsFiles = [ 'templates/partial-active-effects.hbs', 'templates/partial-item-effects.hbs' ]; let effectWebpFound = false; [...allJsFiles, ...hbsFiles].forEach(file => { try { const content = fs.readFileSync(path.join(__dirname, file), 'utf8'); if (effectWebpPattern.test(content)) { console.log(` ❌ Fichier ${file} contient une référence à effect.webp`); effectWebpFound = true; } } catch (err) { // Fichier introuvable, ignorer } }); if (!effectWebpFound) { console.log(' ✅ Aucune référence à effect.webp (icône manquante) trouvée'); } // 7. Vérification de la propriété dépréciée duration.type console.log('\n7. Vérification de l\'utilisation de duration.type (déprécié en v14) :'); const durationTypePattern = /duration\.type/g; const allHbsFiles = [ 'templates/partial-active-effects.hbs', 'templates/partial-item-effects.hbs', 'templates/item-arme-sheet.hbs' ]; let durationTypeFound = false; allHbsFiles.forEach(file => { try { const content = fs.readFileSync(path.join(__dirname, file), 'utf8'); if (durationTypePattern.test(content)) { console.log(` ❌ Fichier ${file} utilise duration.type (déprécié)`); durationTypeFound = true; } } catch (err) { // Fichier introuvable, ignorer } }); if (!durationTypeFound) { console.log(' ✅ Aucune utilisation de duration.type (utilise duration.units)'); } // 8. Vérification des clés i18n EFFECT dans lang/fr.json console.log('\n8. Vérification des clés i18n EFFECT :'); const frJson = require('./lang/fr.json'); const effectKeys = Object.keys(frJson.EFFECT || {}); const requiredEffectKeys = [ 'new', 'edit', 'delete', 'deleteConfirm', 'deleteConfirmText', 'deleteError', 'create', 'createError', 'applyError', 'applyItemError', 'selectActor', 'toggleError', 'name', 'icon', 'description', 'changes', 'addChange', 'duration', 'durationType', 'durationValue', 'disabled', 'transfer', 'noDuration', 'rounds', 'turns', 'seconds', 'combat', 'scene', 'attribute', 'value', 'mode', 'modeAdd', 'modeMultiply', 'modeOverride', 'modeUpgrade', 'modeDowngrade', 'activeEffects', 'noActiveEffects', 'effectSummary', 'toggleEffect' ]; let missingKeys = []; for (const key of requiredEffectKeys) { if (!effectKeys.includes(key)) { missingKeys.push(key); } } if (missingKeys.length === 0) { console.log(` ✅ Toutes les clés EFFECT sont présentes (${effectKeys.length} clés)`); } else { console.log(` ❌ Clés EFFECT manquantes : ${missingKeys.join(', ')}`); } // 9. Vérification de l'utilisation du helper subtract console.log('\n9. Vérification de l\'utilisation du helper subtract :'); const subtractPattern = /subtract/g; const subtractFiles = [ 'templates/partial-active-effects.hbs', 'templates/partial-item-effects.hbs' ]; let subtractUsed = false; let subtractRegistered = false; // Vérifier que le helper est utilisé dans les templates subtractFiles.forEach(file => { try { const content = fs.readFileSync(path.join(__dirname, file), 'utf8'); if (subtractPattern.test(content)) { subtractUsed = true; } } catch (err) { // Fichier introuvable, ignorer } }); // Vérifier que le helper est enregistré try { const utilityContent = fs.readFileSync(path.join(__dirname, 'modules/mournblade-cyd2-utility.js'), 'utf8'); if (/Handlebars\.registerHelper\('subtract'/g.test(utilityContent)) { subtractRegistered = true; } } catch (err) { // Fichier introuvable, ignorer } if (subtractUsed && subtractRegistered) { console.log(' ✅ Helper subtract est enregistré et utilisé'); } else if (subtractUsed && !subtractRegistered) { console.log(' ❌ Helper subtract est utilisé mais pas enregistré'); } else if (!subtractUsed) { console.log(' ✅ Helper subtract n\'est pas utilisé (ou plus utilisé)'); } // Résumé console.log('\n=== Résumé ==='); console.log(`Templates préchargés: ${loaded.length}`); console.log(`Partials utilisés: ${usedPartials.length}`); console.log(`Partials manquants: ${missingPartials.length}`); console.log(`Fichier JSON valide: ${errors.length === 0 ? 'Oui' : 'Non'}`); console.log(`API dépréciée utilisée: ${deprecatedFound ? 'Oui' : 'Non'}`); console.log(`Référence à effect.webp: ${effectWebpFound ? 'Oui' : 'Non'}`); console.log(`Utilisation de duration.type: ${durationTypeFound ? 'Oui' : 'Non'}`); console.log(`Clés i18n EFFECT: ${missingKeys.length === 0 ? 'Complet' : 'Manquantes'}`); console.log(`Helper subtract: ${(subtractUsed && subtractRegistered) ? 'OK' : (subtractUsed ? 'Manquant' : 'Non utilisé')}`); if (errors.length === 0 && missingPartials.length === 0 && !deprecatedFound && !effectWebpFound && !durationTypeFound && missingKeys.length === 0 && (subtractUsed ? subtractRegistered : true)) { console.log('\n✅ Toutes les vérifications ont réussi !'); process.exit(0); } else { console.log('\n❌ Certaines vérifications ont échoué !'); process.exit(1); }