Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no-install lint-staged
# npx --no-install lint-staged
84 changes: 84 additions & 0 deletions example/comprehensive-svg-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* eslint-disable no-console */
const fs = require('fs');
const HTMLtoDOCX = require('../dist/html-to-docx.umd');

async function testVariousSVGs() {
console.log('🔬 Testing various SVG scenarios with verbose logging...\n');

// Test 1: Simple SVG with xmlns
const test1 = `
<h3>Test 1: Simple SVG with xmlns</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<circle cx="50" cy="50" r="40" fill="#3498db" />
</svg>
`;

// Test 2: Simple SVG without xmlns (should be added automatically)
const test2 = `
<h3>Test 2: Simple SVG without xmlns</h3>
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" fill="#e74c3c" />
</svg>
`;

// Test 3: Complex nested SVG
const test3 = `
<h3>Test 3: Complex nested SVG</h3>
<svg width="200" height="150" viewBox="0 0 200 150">
<g class="group1">
<rect x="10" y="10" width="80" height="60" fill="#2ecc71" />
<g class="nested">
<circle cx="150" cy="40" r="30" fill="#f39c12" />
</g>
</g>
<line x1="10" y1="100" x2="190" y2="100" stroke="#34495e" stroke-width="3" />
</svg>
`;

// Test 4: SVG with text elements
const test4 = `
<h3>Test 4: SVG with text</h3>
<svg width="200" height="100" viewBox="0 0 200 100">
<text x="100" y="50" text-anchor="middle" font-size="20" fill="#2c3e50">Hello SVG</text>
</svg>
`;

// Test 5: Radar chart style SVG (like from test.html)
const test5 = `
<h3>Test 5: Radar chart style SVG</h3>
<svg width="400" height="300" viewBox="0 0 400 300">
<g tabindex="-1" id="layer1">
<g class="polar-grid">
<path stroke="#06233F" fill="none" d="M 200,150L 200,90L 250,120L 280,150L 250,180L 200,210L 150,180L 120,150Z"></path>
<path stroke="#06233F" fill="#44C8F5" fill-opacity="0.6" stroke-width="2" d="M200,110L230,125L255,150L230,175L200,190L170,175L145,150L170,125L200,110Z"></path>
</g>
</g>
</svg>
`;

const allTests = test1 + test2 + test3 + test4 + test5;

try {
console.log('📄 Generating comprehensive test document with verbose logging...\n');
const docx = await HTMLtoDOCX(allTests, null, {
orientation: 'portrait',
title: 'SVG Test Suite',
imageProcessing: {
svgHandling: 'native',
verboseLogging: true,
},
});

fs.writeFileSync('./comprehensive-svg-test.docx', docx);
console.log('\n✅ Created: comprehensive-svg-test.docx');
console.log(' → Document with 5 different SVG test cases\n');

console.log('✨ Success! Open the file to verify all SVGs render correctly.');
} catch (error) {
console.error('❌ Error:', error.message);
console.error(error.stack);
process.exit(1);
}
}

testVariousSVGs();
93 changes: 93 additions & 0 deletions example/example-inline-svg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const fs = require('fs');
// Use the built version, or install via: npm install @turbodocx/html-to-docx
// const HTMLtoDOCX = require('@turbodocx/html-to-docx');
const HTMLtoDOCX = require('../dist/html-to-docx.umd');

// Simple HTML with inline SVG element
const htmlContent = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Inline SVG Test</title>
</head>
<body>
<h1>Testing Inline SVG Elements</h1>

<p>This document tests inline SVG elements (not img tags with SVG sources).</p>

<h2>1. Simple Inline SVG Circle</h2>
<p>A basic SVG shape:</p>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="#3498db" />
</svg>

<h2>2. Inline SVG with Multiple Elements</h2>
<p>A more complex SVG:</p>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="150" viewBox="0 0 200 150">
<rect x="10" y="10" width="80" height="60" fill="#e74c3c" />
<circle cx="150" cy="40" r="30" fill="#2ecc71" />
<line x1="10" y1="100" x2="190" y2="100" stroke="#34495e" stroke-width="3" />
</svg>

<h2>3. SVG from test.html</h2>
<p>Testing with a radar chart SVG:</p>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300" viewBox="0 0 400 300">
<g>
<path stroke="#06233F" fill="none" d="M 200,150L 200,90L 250,120L 280,150L 250,180L 200,210L 150,180L 120,150Z"></path>
<path stroke="#06233F" fill="#44C8F5" fill-opacity="0.6" stroke-width="2" d="M200,110L230,125L255,150L230,175L200,190L170,175L145,150L170,125L200,110Z"></path>
</g>
</svg>

<p>End of inline SVG test document.</p>
</body>
</html>
`;

async function generateDocument() {
console.log('🚀 Generating inline SVG example document...\n');

try {
// Test with SVG→PNG conversion (default, requires sharp)
console.log('📄 Generating document with SVG→PNG conversion...');
const docx = await HTMLtoDOCX(htmlContent, null, {
orientation: 'portrait',
title: 'Inline SVG Test',
creator: '@turbodocx/html-to-docx',
imageProcessing: {
svgHandling: 'convert', // Convert SVG to PNG
verboseLogging: true,
},
});

fs.writeFileSync('./example-inline-svg-convert.docx', docx);
console.log('✅ Created: example-inline-svg-convert.docx');
console.log(' → Inline SVGs converted to PNG\n');

// Test with native SVG support
console.log('📄 Generating document with native SVG support...');
const docxNative = await HTMLtoDOCX(htmlContent, null, {
orientation: 'portrait',
title: 'Inline SVG Test - Native',
creator: '@turbodocx/html-to-docx',
imageProcessing: {
svgHandling: 'native', // Use native SVG
verboseLogging: true,
},
});

fs.writeFileSync('./example-inline-svg-native.docx', docxNative);
console.log('✅ Created: example-inline-svg-native.docx');
console.log(' → Inline SVGs embedded as native SVG\n');

console.log('✨ Success! Open the generated .docx files to view inline SVGs.');
console.log('\nNote:');
console.log('- PNG conversion version works in all Word versions');
console.log('- Native SVG version requires Office 2019+ or Microsoft 365');
} catch (error) {
console.error('❌ Error generating document:', error);
process.exit(1);
}
}

generateDocument();
46 changes: 23 additions & 23 deletions example/example-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ const htmlString = `<!DOCTYPE html>
src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
alt="Test image with color and font-family styles"
/>

<p>Testing images with mixed dimensional and non-dimensional styles:</p>
<img
style="width: 100px; font-family: Arial; color: blue;"
src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
alt="Test image with mixed styles"
/>

<p>Testing images with various non-dimensional styles:</p>
<img
style="text-align: center; background-color: yellow;"
Expand Down Expand Up @@ -1696,7 +1696,7 @@ const htmlString = `<!DOCTYPE html>
</ul>
</li>
<li style="font-family: arial, helvetica, sans-serif; font-size: 12pt; line-height: 1.15;"><span style="font-family: arial, helvetica, sans-serif; font-size: 12pt;">Heading 3</span></li>
</ul>
</ul>
<div>
<p>One More test case</p>
<p style="margin: 0in; line-height: normal; font-size: 11pt; font-family: Calibri, sans-serif;"><strong><span style="font-size: 10.0pt; font-family: Arial, sans-serif;">PHASE ONE</span></strong><br /><strong><span style="font-size: 10.0pt; font-family: Arial, sans-serif; color: red;">CONFIDENTIAL <br />HOURS: 1 – 2</span></strong></p>
Expand Down Expand Up @@ -1841,7 +1841,7 @@ const htmlString = `<!DOCTYPE html>
</p>
</div>
</div>

<!-- Image edge case tests covering aspect ratio safety, MIME validation, and error handling -->
<div>
<p>Testing aspect ratio safety with zero/invalid dimensions:</p>
Expand All @@ -1855,7 +1855,7 @@ const htmlString = `<!DOCTYPE html>
src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
alt="Test image with zero width"
/>

<p>Testing extreme aspect ratios:</p>
<img
style="width: 500px; height: 1px;"
Expand All @@ -1867,14 +1867,14 @@ const htmlString = `<!DOCTYPE html>
src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
alt="Very tall image"
/>

<p>Testing auto dimensions with CSS styles:</p>
<img
style="width: auto; height: auto; font-family: serif;"
src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
alt="Auto dimensions with non-dimensional styles"
/>

<p>Testing images in figures (lineRule attribute fix):</p>
<figure>
<img
Expand All @@ -1884,14 +1884,14 @@ const htmlString = `<!DOCTYPE html>
/>
<figcaption>Image with consistent lineRule processing</figcaption>
</figure>

<p>Testing images with max-width/max-height constraints:</p>
<img
style="max-width: 200px; max-height: 150px;"
src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
alt="Image with max constraints"
/>

<p>Testing images exceeding maximum document width (auto-scaling):</p>
<img
style="width: 2000px; height: 1500px;"
Expand Down Expand Up @@ -1928,37 +1928,37 @@ const htmlString = `<!DOCTYPE html>
</tr>
</tbody>
</table>

<!-- Test cases for PR #100 - TinyMCE image dimensions fix -->
<!-- Test image: Porsche 992 Turbo S - Original size: 5,807 × 2,817 pixels, 8.35 MB JPEG -->
<div class="page-break" style="page-break-after: always"></div>
<div>
<h2>Testing Image Width/Height Attribute Handling (Fix for TinyMCE dimensions)</h2>
<p>These test cases verify that width and height HTML attributes are properly honored in DOCX generation:</p>
<p><em>Test image original size: 5,807 × 2,817 pixels (8.35 MB JPEG)</em></p>

<p><strong>Test 1:</strong> Image with explicit width and height attributes (should render as 100x100):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
width="100"
height="100"
alt="100x100 dimensions test"
/>

<p><strong>Test 2:</strong> Image with only width attribute (height should maintain aspect ratio):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
width="150"
alt="Width only test"
/>

<p><strong>Test 3:</strong> Image with only height attribute (width should maintain aspect ratio):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
height="80"
alt="Height only test"
/>

<p><strong>Test 4:</strong> Image with width/height and additional styles (TinyMCE scenario):</p>
<img
style="font-family: Calibri Light;"
Expand All @@ -1967,21 +1967,21 @@ const htmlString = `<!DOCTYPE html>
height="60"
alt="TinyMCE style with dimensions"
/>

<p><strong>Test 5:</strong> Image without dimensions (should use original image size - fallback behavior):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
alt="No dimensions - fallback test"
/>

<p><strong>Test 6:</strong> Larger image with custom dimensions (demonstrates actual resize):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
width="200"
height="100"
alt="Large image resized to 200x100"
/>

<h3>Unit Support Tests</h3>
<p><strong>Test 7:</strong> Image with pixel units (explicit px):</p>
<img
Expand All @@ -1990,39 +1990,39 @@ const htmlString = `<!DOCTYPE html>
height="90px"
alt="180px x 90px image"
/>

<p><strong>Test 8:</strong> Image with point units (pt):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
width="144pt"
height="72pt"
alt="144pt x 72pt image (192px x 96px equivalent)"
/>

<p><strong>Test 9:</strong> Image with centimeter units (cm):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
width="4cm"
height="2cm"
alt="4cm x 2cm image"
/>

<p><strong>Test 10:</strong> Image with inch units (in):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
width="1.5in"
height="0.75in"
alt="1.5in x 0.75in image"
/>

<p><strong>Test 11:</strong> Image with percentage units (% of original size):</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
width="10%"
height="10%"
alt="10% x 10% of original size"
/>

<p><strong>Test 12:</strong> Mixed units - width in cm, height in inches:</p>
<img
src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Porsche_992_Turbo_S_1X7A0413.jpg"
Expand All @@ -2046,7 +2046,7 @@ const htmlString = `<!DOCTYPE html>
imageProcessing: {
// By default, shows a warning when sharp is not installed
// Uncomment to suppress the warning (useful for intentional native SVG mode):
// suppressSharpWarning: true,
// suppressSharpWarning: true,
},
// ===================================================================
// WARNING: deterministicIds is ONLY for CI/CD testing purposes.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading