File size: 5,424 Bytes
bbfde3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
const fs = require('fs');
const path = require('path');
const JSZip = require('jszip');

// Enhanced shadow detection to find ALL possible shadow variants
function findAllShadowTypes(xmlContent) {
  const patterns = [
    /<w:shadow[^>]*>/gi,
    /<w14:shadow[^>]*>/gi,
    /<w15:shadow[^>]*>/gi,
    /<a:shadow[^>]*>/gi,
    /<a14:shadow[^>]*>/gi,
    /<a15:shadow[^>]*>/gi,
    /shadow\w*\s*=\s*"[^"]*"/gi,
    /<[^>]*\s+shadow[^>]*>/gi,
  ];
  
  const allMatches = [];
  patterns.forEach((pattern, index) => {
    const matches = xmlContent.match(pattern) || [];
    if (matches.length > 0) {
      allMatches.push({
        pattern: pattern.toString(),
        matches: matches
      });
    }
  });
  
  return allMatches;
}

// Enhanced shadow removal function
function enhancedShadowRemoval(xmlContent) {
  let fixedXml = xmlContent;
  
  console.log('Before removal, shadow analysis:');
  const beforeShadows = findAllShadowTypes(fixedXml);
  beforeShadows.forEach(shadowType => {
    console.log(`  Pattern ${shadowType.pattern}: ${shadowType.matches.length} matches`);
    shadowType.matches.slice(0, 3).forEach(match => console.log(`    "${match}"`));
  });
  
  // Remove all shadow variants
  const removalPatterns = [
    /<w:shadow\s*\/>/gi,
    /<w:shadow[^>]*>.*?<\/w:shadow>/gi,
    /<w14:shadow\s*\/>/gi,
    /<w14:shadow[^>]*>.*?<\/w14:shadow>/gi,
    /<w15:shadow\s*\/>/gi,
    /<w15:shadow[^>]*>.*?<\/w15:shadow>/gi,
    /<a:shadow\s*\/>/gi,
    /<a:shadow[^>]*>.*?<\/a:shadow>/gi,
    /<a14:shadow\s*\/>/gi,
    /<a14:shadow[^>]*>.*?<\/a14:shadow>/gi,
    /<a15:shadow\s*\/>/gi,
    /<a15:shadow[^>]*>.*?<\/a15:shadow>/gi,
    /\s+\w*shadow\w*\s*=\s*"[^"]*"/gi,
  ];
  
  removalPatterns.forEach(pattern => {
    const before = (fixedXml.match(/<[^>]*shadow[^>]*>/gi) || []).length;
    fixedXml = fixedXml.replace(pattern, '');
    const after = (fixedXml.match(/<[^>]*shadow[^>]*>/gi) || []).length;
    if (before !== after) {
      console.log(`  Removed ${before - after} shadows with pattern: ${pattern}`);
    }
  });
  
  console.log('After removal, remaining shadows:');
  const afterShadows = findAllShadowTypes(fixedXml);
  afterShadows.forEach(shadowType => {
    console.log(`  Pattern ${shadowType.pattern}: ${shadowType.matches.length} matches`);
    shadowType.matches.slice(0, 3).forEach(match => console.log(`    "${match}"`));
  });
  
  return fixedXml;
}

async function comprehensiveShadowTest() {
  console.log('=== Comprehensive Shadow Detection and Removal Test ===\n');
  
  // Test with our known test file
  const testFile = 'tests/fixtures/test_problematic.docx';
  
  if (!fs.existsSync(testFile)) {
    console.log('❌ Test file not found:', testFile);
    return;
  }
  
  try {
    const buffer = fs.readFileSync(testFile);
    const zip = new JSZip();
    await zip.loadAsync(buffer);
    
    // Check all XML files in the document for shadows
    const xmlFiles = ['word/document.xml', 'word/styles.xml', 'word/numbering.xml', 'word/settings.xml'];
    
    for (const fileName of xmlFiles) {
      const file = zip.file(fileName);
      if (file) {
        console.log(`\n--- Testing ${fileName} ---`);
        const xmlContent = await file.async('string');
        
        // Enhanced shadow detection
        const shadows = findAllShadowTypes(xmlContent);
        if (shadows.length === 0) {
          console.log('βœ… No shadows found');
        } else {
          console.log('πŸ” Shadows detected:');
          shadows.forEach(shadowType => {
            console.log(`  ${shadowType.pattern}: ${shadowType.matches.length} matches`);
            shadowType.matches.slice(0, 2).forEach(match => console.log(`    "${match}"`));
          });
          
          // Test removal
          console.log('\nπŸ”§ Testing shadow removal:');
          const cleaned = enhancedShadowRemoval(xmlContent);
          
          const remainingShadows = findAllShadowTypes(cleaned);
          if (remainingShadows.length === 0) {
            console.log('βœ… All shadows successfully removed');
          } else {
            console.log('❌ Some shadows remain:');
            remainingShadows.forEach(shadowType => {
              console.log(`  ${shadowType.pattern}: ${shadowType.matches.length} matches`);
            });
          }
        }
      }
    }
    
    // Create a fully remediated version for user testing
    console.log('\n=== Creating Fully Remediated File ===');
    const docXml = await zip.file('word/document.xml').async('string');
    const stylesXml = await zip.file('word/styles.xml').async('string');
    
    const cleanedDoc = enhancedShadowRemoval(docXml);
    const cleanedStyles = enhancedShadowRemoval(stylesXml);
    
    zip.file('word/document.xml', cleanedDoc);
    zip.file('word/styles.xml', cleanedStyles);
    
    const outputBuffer = await zip.generateAsync({ type: 'nodebuffer' });
    const outputFile = 'tests/fixtures/test_fully_remediated.docx';
    fs.writeFileSync(outputFile, outputBuffer);
    
    console.log(`\nπŸ“ Fully remediated file created: ${outputFile}`);
    console.log('πŸ‘€ Please test this file to see if shadows are truly removed.');
    
  } catch (error) {
    console.error('❌ Error:', error.message);
  }
}

comprehensiveShadowTest();