const fs = require('fs'); const path = require('path'); const JSZip = require('jszip'); // Import the remediation function from the actual endpoint function removeShadowsAndNormalizeFonts(xmlContent) { let fixedXml = xmlContent; // 1. Remove text shadows fixedXml = fixedXml.replace(//g, ''); fixedXml = fixedXml.replace(/]*>.*?<\/w:shadow>/g, ''); fixedXml = fixedXml.replace(/\s+\w*shadow\w*\s*=\s*"[^"]*"/g, ''); // 2. Normalize fonts to Arial (sans-serif) fixedXml = fixedXml.replace( /]*\/?>/g, '' ); // 3. Ensure minimum font size of 22 half-points (11pt) fixedXml = fixedXml.replace( //g, (match, size) => { const sizeNum = parseInt(size); if (sizeNum < 22) { return ''; } return match; } ); // 4. Same for complex script font sizes fixedXml = fixedXml.replace( //g, (match, size) => { const sizeNum = parseInt(size); if (sizeNum < 22) { return ''; } return match; } ); return fixedXml; } async function testShadowRemoval() { const testFilePath = 'tests/fixtures/test_problematic.docx'; console.log('=== Testing Shadow Removal End-to-End ==='); try { // Read the test file const buffer = fs.readFileSync(testFilePath); const zip = new JSZip(); await zip.loadAsync(buffer); // Check original shadow count const originalDocXml = await zip.file('word/document.xml').async('string'); const originalStylesXml = await zip.file('word/styles.xml').async('string'); const originalDocShadows = (originalDocXml.match(/<[^>]*shadow[^>]*>/gi) || []).length; const originalStylesShadows = (originalStylesXml.match(/<[^>]*shadow[^>]*>/gi) || []).length; console.log(`Original document.xml shadows: ${originalDocShadows}`); console.log(`Original styles.xml shadows: ${originalStylesShadows}`); // Apply remediation (same logic as in download-document.js) let fixedDocXml = removeShadowsAndNormalizeFonts(originalDocXml); let fixedStylesXml = removeShadowsAndNormalizeFonts(originalStylesXml); // Check fixed shadow count const fixedDocShadows = (fixedDocXml.match(/<[^>]*shadow[^>]*>/gi) || []).length; const fixedStylesShadows = (fixedStylesXml.match(/<[^>]*shadow[^>]*>/gi) || []).length; console.log(`Fixed document.xml shadows: ${fixedDocShadows}`); console.log(`Fixed styles.xml shadows: ${fixedStylesShadows}`); // Update the zip with fixed content zip.file('word/document.xml', fixedDocXml); zip.file('word/styles.xml', fixedStylesXml); // Generate output file const outputBuffer = await zip.generateAsync({ type: 'nodebuffer' }); const outputPath = 'tests/fixtures/test_remediated.docx'; fs.writeFileSync(outputPath, outputBuffer); console.log(`Remediated file saved to: ${outputPath}`); // Verify the output file const outputZip = new JSZip(); await outputZip.loadAsync(outputBuffer); const verifyDocXml = await outputZip.file('word/document.xml').async('string'); const verifyStylesXml = await outputZip.file('word/styles.xml').async('string'); const verifyDocShadows = (verifyDocXml.match(/<[^>]*shadow[^>]*>/gi) || []).length; const verifyStylesShadows = (verifyStylesXml.match(/<[^>]*shadow[^>]*>/gi) || []).length; console.log(`Verification - document.xml shadows: ${verifyDocShadows}`); console.log(`Verification - styles.xml shadows: ${verifyStylesShadows}`); // Show font changes const originalTimesFonts = (originalDocXml.match(/Times New Roman/g) || []).length; const fixedTimesFonts = (verifyDocXml.match(/Times New Roman/g) || []).length; console.log(`Times New Roman occurrences: ${originalTimesFonts} → ${fixedTimesFonts}`); // Show size changes const originalSmallSizes = (originalDocXml.match(/