Document Header
"; + const docx = await HtmlToDocx(htmlString, headerHtml); +} + +// With document options +async function withOptions() { + const docx = await HtmlToDocx(htmlString, null, { + orientation: "landscape", + title: "TypeScript Example", + creator: "TurboDocx", + table: { + row: { + cantSplit: true, + }, + borderOptions: { + size: 1, + color: "000000" + } + }, + pageNumber: true, + footer: true + }); +} + +// With image processing options +async function withImageOptions() { + const htmlWithImages = `
+ Document Header
"; + const footerHtml = "Page Footer
"; + + const docx = await HtmlToDocx( + htmlString, + headerHtml, + { + orientation: "landscape", + pageSize: { + width: 12240, + height: 15840 + }, + margins: { + top: 1440, + right: 1800, + bottom: 1440, + left: 1800 + }, + title: "Complete Example", + creator: "TurboDocx", + }, + footerHtml + ); +} +``` + +For more comprehensive TypeScript examples, check out the following files in the `example/typescript` directory: + +- `typescript-example.ts` - A complete example showing how to generate and save DOCX files using TypeScript +- `type-test.ts` - Demonstrates the type checking capabilities provided by the TypeScript definitions + +### Running the TypeScript Examples + +To run the TypeScript examples: + +```bash +# Navigate to the example directory +cd example/typescript + +# Install ts-node globally (if not already installed) +npm install -g ts-node typescript + +# Ensure @turbodocx/html-to-docx is built and accessible +# From the root directory of the project: +# npm install +# npm run build + +# Run the TypeScript example directly +ts-node typescript-example.ts +``` + +This will generate two DOCX files in the `example/typescript` directory: +- `basic-example.docx` - A simple document with minimal configuration +- `advanced-example.docx` - A document with headers, footers, and advanced formatting options + ## Usage ```js @@ -66,6 +210,7 @@ full fledged examples can be found under `example/` - `size` [Number]> denotes the border size. Defaults to `0`. - `stroke` [String]> denotes the style of the borderStrike. Defaults to `nil`. - `color` [String]> determines the border color. Defaults to `000000`. + - `addSpacingAfter` [Boolean]> flag to add an empty paragraph after tables for spacing. Defaults to `true`. - `pageNumber` [Boolean]> flag to enable page number in footer. Defaults to `false`. Page number works only if footer flag is set as `true`. - `skipFirstHeaderFooter` [Boolean]> flag to skip first page header and footer. Defaults to `false`. - `lineNumber` [Boolean]> flag to enable line numbering. Defaults to `false`. @@ -75,8 +220,36 @@ full fledged examples can be found under `example/` - `restart` <"continuous"|"newPage"|"newSection"> numbering restart strategy. Defaults to `continuous`. - `numbering` [Object]> - `defaultOrderedListStyleType` [String]> default ordered list style type. Defaults to `decimal`. + - `heading` [Object]> custom heading styles configuration + - `heading1`-`heading6` [Object]> heading style configuration + - `font` [String]> font family + - `fontSize` [Number]> font size in half-points + - `bold` [Boolean]> whether text is bold. Defaults to `true` + - `spacing` [Object]> paragraph spacing configuration + - `before` [Number]> spacing before heading in twips + - `after` [Number]> spacing after heading in twips + - `keepLines` [Boolean]> keep lines together. Defaults to `true` + - `keepNext` [Boolean]> keep with next paragraph. Defaults to `true` + - `outlineLevel` [Number]> outline level (0-5) - `decodeUnicode` [Boolean]> flag to enable unicode decoding of header, body and footer. Defaults to `false`. - `lang` [String]> language localization code for spell checker to work properly. Defaults to `en-US`. + - `direction` [String]> text direction for RTL (right-to-left) languages. Set to `'rtl'` for Arabic, Hebrew, etc. Defaults to `'ltr'`. + - `preProcessing` [Object]> + - `skipHTMLMinify` [Boolean]> flag to skip minification of HTML. Defaults to `false`. + - `imageProcessing` [Object]> + - `maxRetries` [Number]> maximum number of retry attempts for failed image downloads. Defaults to `2`. + - `verboseLogging` [Boolean]> flag to enable detailed logging of image processing operations. Defaults to `false`. + - `downloadTimeout` [Number]> timeout in milliseconds for each image download attempt. Defaults to `5000` (5 seconds). + - `maxImageSize` [Number]> maximum allowed image size in bytes. Defaults to `10485760` (10MB). + - `retryDelayBase` [Number]> base delay in milliseconds for exponential backoff between retries. Defaults to `500` (500ms). + - `minTimeout` [Number]> minimum timeout in milliseconds. Defaults to `1000` (1 second). + - `maxTimeout` [Number]> maximum timeout in milliseconds. Defaults to `30000` (30 seconds). + - `minImageSize` [Number]> minimum image size in bytes. Defaults to `1024` (1KB). + - `maxCacheSize` [Number]> maximum total cache size in bytes (LRU cache limit to prevent OOM). Defaults to `20971520` (20MB). + - `maxCacheEntries` [Number]> maximum number of unique images in cache (LRU eviction). Defaults to `100`. + - `svgHandling` [String]> strategy for handling SVG images. Defaults to `'convert'`. Options: + - `'convert'` - Converts SVG to PNG for maximum compatibility with all Word versions (requires `sharp` package) + - `'native'` - Embeds SVG natively for Office 2019+ (preserves vector quality) - `footerHTMLString` <[String]> clean html string equivalent of footer. Defaults to `` if footer flag is `true`. ### Returns @@ -110,6 +283,151 @@ Also you could add attribute `data-start="n"` to start the numbering from the n- `هذا نص تجريبي باللغة العربية ليظهر من اليمين إلى اليسار
+`; + +const docx = await HTMLtoDOCX(htmlString, null, { + direction: 'rtl', // Enable RTL text direction + lang: 'ar-SA', // Arabic locale (or 'he-IL' for Hebrew) + font: 'Arial', // Use a font that supports RTL characters +}); +``` + +For more RTL examples, check `example/react-example/src/example-rtl.js`. + +## Font Compatibility + Font family doesnt work consistently for all word processor softwares - Word Desktop work as intended @@ -156,4 +474,8 @@ MITThis heading uses a custom Arial font at 72pt (36pt in half-points) with extra spacing.
+ +This heading uses Georgia font at 40pt with custom spacing before and after.
+ +This heading uses a smaller font size and is not bold (unlike default).
+ +This heading uses the default styling to show the difference.
+ +This heading has minimal spacing and a specific outline level.
+ +This heading also uses default styling.
+ +All H1 tags will use the same custom style defined in the configuration.
+ +All H2 tags will use the same custom style.
+ +Demonstrating consistent styling across multiple headings of the same level.
+ +`; + +(async () => { + console.log('🎨 Creating DOCX with customizable heading styles...\n'); + + // Define custom heading styles + const customHeadingOptions = { + heading1: { + font: 'Arial', + fontSize: 72, // 36pt in Word (OOXML uses half-points: 72 / 2 = 36pt) + bold: true, + spacing: { + before: 600, // Spacing in twips (1/20 of a point) + after: 200, + }, + keepLines: true, + keepNext: true, + outlineLevel: 0, + }, + heading2: { + font: 'Georgia', + fontSize: 40, // 20pt in Word (40 / 2 = 20pt) + bold: true, + spacing: { + before: 400, + after: 150, + }, + keepLines: true, + keepNext: true, + outlineLevel: 1, + }, + heading3: { + font: 'Calibri', + fontSize: 26, // 13pt in Word (26 / 2 = 13pt) + bold: false, // Not bold (different from default) + spacing: { + before: 240, + after: 100, + }, + keepLines: true, + keepNext: true, + outlineLevel: 2, + }, + // heading4, heading5, heading6 will use default styles + heading5: { + font: 'Times New Roman', + fontSize: 20, // 10pt in Word (20 / 2 = 10pt) + bold: true, + spacing: { + before: 120, + after: 60, + }, + keepLines: false, // Allow splits + keepNext: false, + outlineLevel: 4, + }, + }; + + console.log('📋 Custom Heading Configuration:'); + console.log(' H1: Arial, 36pt, bold, extra spacing'); + console.log(' H2: Georgia, 20pt, bold, custom spacing'); + console.log(' H3: Calibri, 13pt, NOT bold, custom spacing'); + console.log(' H4: (using defaults)'); + console.log(' H5: Times New Roman, 10pt, bold, minimal spacing'); + console.log(' H6: (using defaults)\n'); + + try { + const fileBuffer = await HTMLtoDOCX(htmlString, null, { + heading: customHeadingOptions, + title: 'Customizable Heading Styles Demo', + subject: 'Demonstrating PR #129 - Customizable Heading Styles', + creator: 'TurboDocx Example', + description: 'This document showcases the customizable heading styles feature', + }); + + fs.writeFile(filePath, fileBuffer, (error) => { + if (error) { + console.log('❌ Docx file creation failed'); + console.error(error); + return; + } + console.log('✅ Docx file created successfully: ' + filePath); + console.log('\n📖 Open the file to see:'); + console.log(' • Custom fonts for different heading levels'); + console.log(' • Custom font sizes'); + console.log(' • Custom spacing before/after headings'); + console.log(' • H3 without bold (customized)'); + console.log(' • H4 and H6 with default styles (for comparison)'); + }); + } catch (error) { + console.log('❌ Error generating document'); + console.error(error); + } +})(); diff --git a/example/example-node.js b/example/example-node.js index fee93a0..6488115 100644 --- a/example/example-node.js +++ b/example/example-node.js @@ -4,7 +4,7 @@ const fs = require('fs'); // const HTMLtoDOCX = require('html-to-docx'); const HTMLtoDOCX = require('../dist/html-to-docx.umd'); -const filePath = './example.docx'; +const filePath = './example-node.docx'; const htmlString = ` @@ -23,6 +23,73 @@ const htmlString = ` src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" alt="Red dot" /> + +Testing images with non-dimensional CSS styles (font-family, color):
+Testing images with mixed dimensional and non-dimensional styles:
+Testing images with various non-dimensional styles:
+Testing SVG images (automatically converted to PNG for maximum compatibility):
+ +Simple SVG circle:
+SVG with different sizes:
+Inline SVG icon: SVG works inline too!
SVG bar chart:
+
+ + paragraph temporary lorem test tag +
+ Inside em tag
@@ -1642,21 +1724,345 @@ const htmlString = `
Table with empty row that could corrupt
+| Task | +Frequency | +
|---|---|
| Showroom | +|
| Wipe down display cars | +Daily | +
| Clean glass walls & windows | +Daily | +
| Mop & polish floors | +Daily | +
| Dust furniture & charging stations | +Daily | +
| Service Bay | +|
| Sweep & mop floors | +Daily | +
| Empty trash & oil disposal bins | +Daily | +
| Clean workbenches & tool areas | +Daily | +
| Wipe down customer drop-off zone | +Daily | +
| Waiting Area | +|
| Vacuum carpets & seating | +Daily | +
| Sanitize coffee station & touchscreens | +Daily | +
| Restock magazines & charging cables | +Daily | +
| Restrooms | +|
| Refill soap & paper products | +Daily | +
| Disinfect sinks & counters | +Daily | +
| Mop floors | +Daily | +
| Employee Lounge | +|
| Wipe tables & kitchen counters | +Daily | +
Testing for paragraph after table spacing if addSpacingAfterTable is true or false
+| Row 1, Col 1 | +Row 1, Col 2 | +
| Row 2, Col 1 | +Row 2, Col 2 | +
+ Mid Merge Border (No Space After Table) +
+Testing aspect ratio safety with zero/invalid dimensions:
+Testing extreme aspect ratios:
+Testing auto dimensions with CSS styles:
+Testing images in figures (lineRule attribute fix):
+Testing images with max-width/max-height constraints:
+Testing images exceeding maximum document width (auto-scaling):
+|
+ testset + |
+
+ test + |
+ |
|---|---|---|
|
+ data1 + |
+
+ data2 + |
+
+ data3 + |
+
These test cases verify that width and height HTML attributes are properly honored in DOCX generation:
+Test image original size: 5,807 × 2,817 pixels (8.35 MB JPEG)
+ +Test 1: Image with explicit width and height attributes (should render as 100x100):
+
+
+ Test 2: Image with only width attribute (height should maintain aspect ratio):
+
+
+ Test 3: Image with only height attribute (width should maintain aspect ratio):
+
+
+ Test 4: Image with width/height and additional styles (TinyMCE scenario):
+
+
+ Test 5: Image without dimensions (should use original image size - fallback behavior):
+
+
+ Test 6: Larger image with custom dimensions (demonstrates actual resize):
+
+
+ Test 7: Image with pixel units (explicit px):
+
+
+ Test 8: Image with point units (pt):
+
+
+ Test 9: Image with centimeter units (cm):
+
+
+ Test 10: Image with inch units (in):
+
+
+ Test 11: Image with percentage units (% of original size):
+
+
+ Test 12: Mixed units - width in cm, height in inches:
+
+