You are currently offline, serving cached version

HTML Module

This module only supports docx (Word documents), not pptx, see the html-pptx module if you want to include HTML inside Powerpoint presentations. Also see the html-xlsx module to include HTML into Excel Spreadsheets.

Using the HTML module, you can include dynamic formatted text in the output Document by passing HTML as a field value.

To achieve that, simply add ~~ as a prefix to your field name. The final syntax should be: {~~myField}

Then, use following code :

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule({})],
});
doc.render({ myField: "<b>Hello</b>, Foo !" });

Usage

Usage (nodejs)

const HTMLModule = require("docxtemplater-html-module");
const fs = require("fs");
const path = require("path");

// Load the docx file as binary content
const content = fs.readFileSync(
    path.resolve(__dirname, "input.docx"),
    "binary"
);

const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule({})],
}).render({ html: "<b>Hello</b>, Foo !" });

const buffer = doc.getZip().generate({
    type: "nodebuffer",
    compression: "DEFLATE",
});

fs.writeFile("test.docx", buffer);

Usage (browser)

<html>
    <script src="node_modules/docxtemplater/build/docxtemplater.js"></script>
    <script src="node_modules/pizzip/dist/pizzip.js"></script>
    <script src="node_modules/pizzip/vendor/FileSaver.js"></script>
    <script src="node_modules/pizzip/dist/pizzip-utils.js"></script>
    <script src="build/html-module.js"></script>
    <script>
        PizZipUtils.getBinaryContent(
            "examples/html-block-example.docx",
            function (error, content) {
                if (error) {
                    console.error(error);
                    return;
                }

                const zip = new PizZip(content);
                const doc = new docxtemplater(zip, {
                    modules: [new DocxtemplaterHtmlModule({})],
                });

                doc.render({
                    html: "<p>Hello <b>John</b></p>",
                });
                const out = doc.getZip().generate({
                    type: "blob",
                    mimeType:
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                });
                saveAs(out, "generated.docx");
            }
        );
    </script>
</html>

Syntax

Tag Types

  1. Inline HTML Tags: Start with a single ~

    • Example: {~html} or {~inlineComment}
    • Uses the corresponding data (e.g., "inlineComment" data)
  2. Block HTML Tags: Start with double ~~

    • Example: {~~html} or {~~styledTable}
    • Uses the corresponding data (e.g., "styledTable" data)

Detailed Explanation

Inline Tags: {~inline}
  • Used to replace part of a paragraph
  • Example: My product is {~blueText} and costs ...
  • Only use inline HTML elements (<span>, <b>, <i>, <u>, etc.)
Block Tags: {~~block}
  • Used to replace an entire paragraph
  • Example: {~~block}
  • Only use block HTML elements (<p>, <ul>, <table>, <ol>, <h1>, etc.)

The HTML block tag {~~html} works only with paragraphs, not with line breaks. See this tip in the FAQ to understand how to view and replace line breaks.

Supported HTML tags

The HTML module currently supports following tags :

<p> (paragraphs)
<h1-h6> // <h1> translates to "Title",
// <h2> translates to "Header1"
// <h3> translates to "Header2",
<b> (bold)
<i> (italic)
<u> (underline)
<ul>, <ol> and <li> for ordered and unordered lists
<span>
<small>
<s> (strikethrough)
<ins> and <del>
<strong> (bold)
<em> (italic)
<code> (gray highlight)
<table>, <tr>, <td>, <tbody>, <thead>, <tfoot>, <th> tags
<col> and <colgroup> to specify column sizes
<a href="URL">Linktext</a> (links)
<input type="checkbox"> and <input type="checkbox" checked> (Checkboxes)
<sub> and <sup> (exponents)
<pre>, by using Courrier font and retaining all spaces
<mark> (for highlighting text parts)
<br> (line-breaks)
<hr> (horizontal-breaks)
<img> only if including the imageModule too, by using base64 src
<svg> only if including the imageModule too
<center> tag to place a paragraph to the center
<template>,<script> tag to ignore some part of the HTML

For SVG, the generated document will only be readable on newer Word version : Microsoft Word, PowerPoint, Outlook, and Excel 2016 on Windows, Mac, Android and Windows Mobile. See this article for details about this feature

We support the following CSS properties :

color: #bbbbbb;
font-size: 30px;
font-family: 'Times New Roman';
background-color: blue; /* (or with rgb codes) */
text-decoration: underline;
padding-left: 30px;
padding-bottom: 30px;
padding-top: 30px;
width:33%; height: 50%; /* (on td only) */
text-align:justify;
vertical-align: bottom; /* (on td) */
border: none; /* (on tables) */
break-after:page;
break-after:avoid;
break-after:unset|initial|auto;
break-before:page;
white-space:pre;
line-height: 1.3; /* (or with percentages, or fixed values such as `20px`) */
margin-top: 30px;
margin-bottom: 30px;
margin-left: 30px;

Options

You can configure options for the htmlModule.

  • ignoreUnknownTags [default=false]: If this option is set to true, and the module finds an HTML tag that it doesn't handle, it will not fail but instead make as if the tag was of type <span>;
  • ignoreCssErrors [default=false]: If this option is set to true, all CSS errors are ignored and the library tries to parse the CSS with a best-effort algorithm;
  • styleTransformer makes it possible to rewrite the styles that are used by the HTML module, and allows to create new HTML tags, see below for an example;
  • sizeConverters makes it possible to change the ratio between px and dxa for different tags;
  • styleSheet makes it possible to add style to all HTML tags that are inserted.
  • customTags makes it possible to create HTML tags that then will return the XML that you specify in a function.

ignoreUnknownTags

To ignore all unknown tags:

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            ignoreUnknownTags: true,
        }),
    ],
});
doc.render(data);

styleTransformer

To remap the styles so that h1 maps to Heading1 (instead of the default Title)

function styleTransformer(tags, docStyles) {
    tags.h1 = docStyles.Heading1;
    tags.h2 = docStyles.Heading2;
    tags.h3 = docStyles.Heading3;
    tags.h4 = docStyles.Heading4;
    tags.h5 = docStyles.Heading5;

    /* Note that docStyles.Heading1 is a hardcoded value in the docxtemplater
     * html code, it is exactly the same as writing :
     *
     * tags.h1 = {
     *     type: "block",
     *     data: {
     *         pStyle: "Heading",
     *         props: [],
     *     },
     * }
     */
    return tags;
}

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            styleTransformer,
        }),
    ],
});
doc.render(data);

If you want to remap h1 to an other paragraphStyle (w:styleId property in styles.xml), you can do the following :

function styleTransformer(tags, docStyles, opts) {
    if (opts.styleIds.indexOf("Titre1") !== -1) {
        tags.h1.data.pStyle = "Titre1";
    }
    return tags;
}
const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            styleTransformer,
        }),
    ],
});
doc.render(data);

You can also create new HTMLtags with the styleTransformer api, for example :

function styleTransformer(tags) {
    tags.p2 = { type: "block", data: {} };
    tags.highlight = {
        type: "inline",
        data: {
            props: [
                {
                    type: "string",
                    tag: "w:b",
                    value: "<w:b/>",
                },
                {
                    type: "string",
                    tag: "w:highlight",
                    value: '<w:highlight w:val="yellow"/>',
                },
            ],
        },
    };
    return tags;
}
const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            styleTransformer,
        }),
    ],
});
doc.render({
    html: "<p2>Hello <highlight>Foobar</highlight></p2>",
});

sizeConverters

To change the size of "padding-left":

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            sizeConverters: {
                paddingLeft: 20,
            },
        }),
    ],
});
doc.render(data);

This will make paddingLeft a little bit larger on word than the default (which is 15).

styleSheet

To add a global stylesheet

const htmlModuleOptions = {
    styleSheet: `
        h1 {
            font-size: 60px;
        }
        span#foo {
            font-size: 30px;
            color: red;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlModuleOptions)],
});
doc.render(data);

customTags

Please note that this API should only be utilized when you need to generate a unique type of tag that cannot be achieved using the styleTransformer API. With the styleTransformer API, you have the capability to craft new tag types and assign certain XML properties to them.
The customTags API was introduced for scenarios where direct manipulation of XML is necessary, moving away from relying on the HTML module function to handle HTML children and similar tasks.

It is possible to create a new handler for an HTML tag to create your own XML.

For example, if you want to add some specific element in your HTML that you want to render from your code, you could do the following:

  1. First find a name for your new element, in our case we will use the tag <mytag>.

  2. In your code, you can then return the XML that you want to render, like this :

const htmlModuleOptions = {
    customTags: {
        mycheckbox: {
            type: "inline",
            value(element, { getText }) {
                const text = getText(element);
                console.log(text);
                // text="inner text"
                // Return OpenXML with some formatting (bold here)
                return {
                    type: "inline",
                    data: `<w:r><w:rPr><w:b/></w:rPr><w:t>[✓]</w:t></w:r>`,
                };
            },
        },
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlModuleOptions)],
});
doc.render({
    html: "<p>Hello, here is <mycheckbox/></p>",
});

You can either configure your tag to be "inline" or "block", and can customize how it is going to be rendered in the value function.

Reasons for not supporting pptx

This module handles only docx documents, not pptx.

The reason for that is that HTML maps well to docx because they use the same linear flow, eg elements are placed one after the other in the document. However PPTX documents have multiple slides, which are stored in different files, and each element is positioned absolutely in the slide. For example, in PPTX if you have a table element and a paragraph in the same slide, they need to be placed in two "different" blocks.

There is the HTML-pptx-module that handles HTML insertion for PPTX.

Support for images with <img>

To be able to replace the <img> tag, you have to also have access to the Image Module.

Then, you can do :

const HTMLModule = require("docxtemplater-html-module");
const ImageModule = require("docxtemplater-image-module");

const htmlModuleOptions = {
    img: {
        Module: ImageModule,
        /*
         * By default getSize returns the width and height attributes
         * if both are present, or 200x200px as a default value.
         */
        getSize(img, b, c, d) {
            /* The html element, for example, if the data is :
             * '<img width="20" src="...">'
             * you will have :
             *
             * img.element.attribs.width = '20'
             *
             */

            /* If the data is '<img style="width:200px;" src="...">'
             * '<img width="20" src="...">'
             * you will have
             *
             * img.parsedStyle = [
             *   { property: "width", value: "200px"}
             * ]
             *
             * on which you could do :
             *
             * for ({property, value} of img.parsedStyle) {
             *     if (property === "width") {
             *          width = parseInt(value.replace(/px$/, ""), 10);
             *     }
             * }
             */
            console.log(img.element);
            /* data.src is the arraybuffer of your image
             * (you could use the image-size library to to calculate the size)
             * (https://github.com/image-size/image-size)
             */
            console.log(img.src);
            // data.part.value is 'myTag' if your tag is {~myTag}
            console.log(img.part.value);

            let width, height;

            console.log(b, c, d);
            if (img.element.attribs.style) {
                const style = img.element.attribs.style;
                const widthMatch = style.match(
                    /width:\s*(\d+(\.\d+)?)(px)?/
                );
                const heightMatch = style.match(
                    /height:\s*(\d+(\.\d+)?)(px)?/
                );
                width = widthMatch
                    ? parseFloat(widthMatch[1])
                    : 200;
                height = heightMatch
                    ? parseFloat(heightMatch[1])
                    : 200;
            } else {
                width = 200;
                height = 200;
            }
            // This is to handle the fact that when an img is inside a table,
            // the width of the image should not exceed the width of the table.
            if (typeof d.part.containerWidth === "number") {
                if (d.part.containerWidth > width) {
                    const ratio = width / d.part.containerWidth;
                    width *= ratio;
                    height *= ratio;
                }
            }

            // You return an array in pixel
            // width:50px,height:100px
            return [width, height];
        },
    },
};

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlModuleOptions)],
});
doc.render(data);

The <img> tag supports base64 and also urls, so for example, you can do :

<p>Hello</p>
<img
    src="data:image/gif;base64,R0lGODlhDAAMAIQZAAAAAAEBAQICAgMDAwQEBCIiIiMjIyQkJCUlJSYmJigoKC0tLaSkpKampqenp6ioqKurq66urrCwsPb29vr6+vv7+/z8/P39/f7+/v///////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAADAAMAAAFSiCWjRmViVVmZRWWjiurXrBI2uMkFcdjrRfaJQIQCAKQTDBmKAYACAwuswAABoBEDMUgYAkOpWiFeRgUDZIKNnqpLaJLXM2KjaYhADs="
    alt=""
/>

Note that HTTP URLs in src will not work by default, you have to configure docxtemplater in async mode to do so.

You can use the following getSize function if you would like to use the same width and height as the image source.

import sizeOf from "image-size";
function getSize(img) {
    const buffer = new Buffer(img.src);
    const sizeObj = sizeOf(buffer);
    return [sizeObj.width, sizeObj.height];
}
const htmlModuleOptions = {
    img: {
        Module: ImageModule,
        // By default getSize returns the width and height attributes if both
        // are present, or 200x200px as a default value.
        getSize,
    },
};

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlModuleOptions)],
});
doc.render(data);

You can also add a caption to the image if using image module 3.7.0 or above, and use the following :

const HTMLModule = require("docxtemplater-html-module");
const ImageModule = require("docxtemplater-image-module");

const htmlModuleOptions = {
    img: {
        Module: ImageModule,
        // By default getSize returns the width and height attributes if both
        // are present, or 200x200px as a default value.
        getProps(data) {
            return {
                caption: {
                    text: `: ${data.element.attribs.title}`,
                },
            };
        },
    },
};

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlModuleOptions)],
});
doc.render(data);

Support for loading images asynchronously (urls)

It is possible to add images with src="http://......" by using async docxtemplater.

You can customize the image resolver with the getValue function.

Here is an example showing how to retrieve the data from https://avatars3.githubusercontent.com/u/2071336?v=3&s=100 :

const fs = require("fs");
const https = require("https");
const http = require("http");
const url = require("url");
const Docxtemplater = require("docxtemplater");
const ImageModule = require("docxtemplater-image-module");
const HTMLModule = require("docxtemplater-html-module");
const PizZip = require("pizzip");

function base64DataURLToArrayBuffer(dataURL) {
    const stringBase64 = dataURL.replace(
        /^data:image\/([a-z]+);base64,/,
        ""
    );
    let binaryString;
    if (typeof window !== "undefined") {
        binaryString = window.atob(stringBase64);
    } else {
        binaryString = Buffer.from(
            stringBase64,
            "base64"
        ).toString("binary");
    }
    const len = binaryString.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
        const ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    return bytes.buffer;
}
const defaultImage = base64DataURLToArrayBuffer(
    "data:image/gif;base64,R0lGODlhDAAMAIQZAAAAAAEBAQICAgMDAwQEBCIiIiMjIyQkJCUlJSYmJigoKC0tLaSkpKampqenp6ioqKurq66urrCwsPb29vr6+vv7+/z8/P39/f7+/v///////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAADAAMAAAFSiCWjRmViVVmZRWWjiurXrBI2uMkFcdjrRfaJQIQCAKQTDBmKAYACAwuswAABoBEDMUgYAkOpWiFeRgUDZIKNnqpLaJLXM2KjaYhADs="
);

const base64Regex =
    /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;
const htmlOptions = {
    img: {
        Module: ImageModule,
        getValue: (el) => {
            const src = el.attribs.src;
            return new Promise(function (resolve) {
                // You should handle any errors here, if the promise rejects,
                // the rendering will fail with that error.
                // This is to continue to handle base64 images
                if (base64Regex.test(src)) {
                    resolve(base64DataURLToArrayBuffer(src));
                    return;
                }

                let parsedUrl;
                try {
                    parsedUrl = url.parse(src);
                } catch {
                    resolve(defaultImage);
                    return;
                }

                let client;
                if (parsedUrl.protocol === "https:") {
                    client = https;
                }
                if (parsedUrl.protocol === "http:") {
                    client = http;
                }
                if (!client) {
                    resolve(defaultImage);
                    return;
                }

                client
                    .get(parsedUrl, function (res) {
                        const data = [];

                        res.on("error", function (err) {
                            console.error(
                                "Error during HTTP request",
                                err
                            );
                            resolve(defaultImage);
                        });

                        res.on("data", function (chunk) {
                            data.push(chunk);
                        }).on("end", function () {
                            resolve(Buffer.concat(data));
                        });
                    })
                    .on("error", () => {
                        resolve(defaultImage);
                    });
            });
        },
    },
};

const content = fs.readFileSync("demo_template.docx");
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.renderAsync({
    html: '<img width="30" height="30" src="https://avatars3.githubusercontent.com/u/2071336?v=3&s=100"/>',
}).then(function () {
    const buffer = doc.getZip().generate({
        compression: "DEFLATE",
        type: "nodebuffer",
    });
    fs.writeFileSync("demo_generated.docx", buffer);
});

Align images to the center, left or right.

By default, images use "inline-block", which means that you can insert multiple images in a given paragraph.

Images can also use the "block" mode, in that case only one image will be present per paragraph. Images can then be set to be left, right, or center aligned.

Center alignment :

const htmlOptions = {
    styleSheet: `
        img {
            display: block;
            margin-left: auto;
            margin-right: auto;
            width: 30px;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({ html: "<img src='.....'>" });

Left alignment :

const htmlOptions = {
    styleSheet: `
        img {
            display: block;
            margin-right: auto;
            width: 30px;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({ html: "<img src='.....'>" });

Right alignment :

const htmlOptions = {
    styleSheet: `
        img {
            display: block;
            margin-left: auto;
            width: 30px;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({ html: "<img src='.....'>" });

How are pixels converted to word ?

The dpi option will allow you to convert a pixel into one inch.

By default, the dpi is set to 75, which means that 75px will be converted to 1 inch.

In previous versions (3.31.x and earlier), the deviceWidth and getDxaWidth existed, but they now are ignored in favor of the dpi option.

Customize paragraph styles with classes

For block elements (p, h1,h2,h3,h4,h5,h6, ul, ol, and table), it is now possible to customize the style of paragraphs. It can be used to customize them for example depending on the html class of that element.

const htmlOptions = {
    elementCustomizer(element) {
        if (
            element.classNames.indexOf("my-heading-class") !==
                -1 &&
            element.name === "p"
        ) {
            return { pStyle: "Heading" };
        }
        // element.part.value will be the string "html1" if the tag used is {~~html1}
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

The following HTML :

<p>Paragraph</p>
<p class="my-heading-class">Paragraph - heading</p>
<p>Normal paragraph</p>

will have the second paragraph rendered by using the Heading type.

Of course, you can use any docx style that you have defined in your docx template.

CSS Selectors

It is possible to add CSS style using CSS selectors.

For example, if you want to change the font size with the CSS selector : h4, th p.important

const htmlOptions = {
    elementCustomizer(element) {
        if (element.matches("h4, th p.important")) {
            return {
                // htmlStyle must be valid CSS style
                htmlStyle: "font-size: 30px;",
            };
        }
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

You can use following selectors currently :

SelectorExampleExample description
.class.introElements with class="intro"
#id#firstnameElement with id="firstname"
**All elements
elementp<p> elements
element, elementdiv, pAll <div> elements and all <p> elements
element elementdiv p<p> elements inside <div> elements
element > elementdiv > p<p> elements where the direct parent is a <div> element
element + elementdiv + p<p> elements that are placed immediately after <div> elements
[attribute][target]Elements with a target attribute
[attribute=value][target=_blank]Elements with target="_blank"

Customize bullets

It is possible to customize bullets with the elementCustomizer API

For example, you can write :

const htmlOptions = {
    elementCustomizer(element) {
        if (element.matches("ul")) {
            return {
                bullets: ["·", "-", "+"],
            };
        }
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

It is also possible to customize the color, font and text with the elementCustomizer API :

const htmlOptions = {
    elementCustomizer(element) {
        if (element.matches("ul")) {
            return {
                bullets: [
                    {
                        text: " ",
                        font: "Wingdings",
                        color: "FF0000",
                    },
                    {
                        text: "-",
                        color: "00FF00",
                    },
                    {
                        text: "+",
                        size: 30,
                        color: "0000FF",
                    },
                ],
            };
        }
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

Bullet margin / text-indent

Docxtemplater as such doesn't support the "list-style-position" attribute.

If you want to put the bullets aligned with the text (and not indented to the right), you have to use the following :

const htmlOptions = {
    styleSheet: `
        ul, ol {
            margin-bottom: 0;
            margin-top: 0;
            padding-left: 0;
        }
        li {
            margin-bottom: 0;
            margin-top: 0;
        }
        ul li {
            margin-left: 1em;
            text-indent: -1em;
            list-style-position: outside;
        }
        ol li {
            margin-left: 1em;
            text-indent: -1em;
            list-style-position: outside;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({
    html: `
        <p>Hello</p>
        <ol>
            <li>L1</li>
            <li>L2</li>
            <li>L3</li>
        </ol>
        <ul>
            <li>L1</li>
            <li>L2</li>
            <li>L3</li>
        </ul>
    `,
});

Limitations

For tables, there is no difference between table-layout:fixed and table-layout:auto.

Also, unlike the auto algorithm, the width of the column does not depend on the content of the table, but just on the width applied in the CSS style.

This means that if you want to have columns of different sizes in your generated document, you should specify the width in the first column on all tr elements.

Adding page breaks

It is possible to use the break-after: page or break-before: page styles.

Here is an example :

const htmlOptions = {
    styleSheet: `
        .pba { break-after: page; }
        .pbb { break-before: page; }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({
    html: `<p>Hello</p>
           <p class="pba">Hi</p>
           <p class="pba">Hello</p>
           <p>Bye</p>
           <p>Bye</p>
           <p>Bye</p>
           <p>Bye</p>
           <p class="pbb">Good bye</p>
           `,
});

This will put a pagebreak after "Hi", after "Hello", and before "Good bye".

Add links using angular parser (from label + url)

It is possible to include links using one simple tag using a label and url data, like this.

In your template :

Header 1
{~~url | link:label}

Install following modules :

npm install --save lodash he angular-expressions

In your code, use the angular-parser and define a link filter.

const he = require("he");
const expressionParser = require("docxtemplater/expressions.js");

expressionParser.filters.link = function (url, label) {
    // This condition should be used to make sure that if your url is
    // undefined, your output will be undefined as well and will not
    // throw an error
    if (!url) {
        return url;
    }
    return `<a href="${he.decode(url)}">${he.decode(label)}</a>`;
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule()],
    parser: expressionParser,
});
doc.render(data);

Adding tabstops

With the -xt-tab-stop CSS property, which value can be tabstop, it is now possible to add a tabstop to the paragraph of a Word document

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            ignoreUnknownTags: true,
            styleSheet: `
                t {
                    -xt-tab-stop: tabstop;
                }
            `,
        }),
    ],
});
doc.render({ html: "<p>Hello<t/>Foo<t/>Bar</p>" });

Unsupported properties

Here is a list of properties that cannot be supported, and I explain a bit why :

  • display: inline-block; or other "display" properties : In Word, everything is just simply a paragraph, or a table or an image (or some other things such as graphs, smartarts, …). And all these elements always behave like block elements. They can be positioned relatively, but inline-block, flex, grid, do not have any translation in the docx format. The only exception is for the <img> tag which allows either display: block or display: inline-block.
  • position: absolute; or position: fixed properties : There is no translation of this property into the docx format that would render anything near this.
  • width/height on div elements : div's do not exist in the docx format as well, only paragraphs, tables, and images, and putting constraints on the width and height is not feasible except for tables and table cells.

Block placeholders inside paragraphs

If you place a block placeholder in a paragraph, like this

{~~block} some other text

The behavior of this is controlled by the option onInvalidBlock.

The value can be set like this :

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule({ onInvalidBlock: "block" })],
    paragraphLoop: true,
    linebreaks: true,
});
doc.render({
    /* data */
});

The possible values are the following :

  • "block" (default), which will remove the rest of the paragraph, and render the HTML tag.
  • "inline", which will automatially convert that HTML tag into an HTML tag. In that case, HTML block tags such as <table> will not be shown as real tables.
  • "error", which will raise a template error.

Error : Unexpected token in htmlparser2

You might get the following error :

Module parse failed: Unexpected token (59:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See [webpack.js.org/concepts#loaders](https://webpack.js.org/concepts#loaders)

Since htmlparser2 version 8.x, the package.json of htmlparser2 defines multiple exports fields :

Webpack will by default use the "module" entry of the package.json : View htmlparser2 package.json on Github

This means that it will load the file from "lib/esm/index.js".

In your webpack configuration, you need to have the appropriate loader to be able to parse the "export" statement (and other ESM specific syntax)

You most probably currently have something like this in your webpack.config.js :

const config = {
    loaders: [
        {
            test: /\.js$/,
            loader: "babel",
            exclude: /node_modules/,
            query: {
                presets: ["es2015", "stage-0"],
            },
        },
    ],
};
module.exports = config;

Instead you should rather use the include property like this :

const path = require("path");
const config = {
    loaders: [
        {
            test: /\.js$/,
            loader: "babel",
            include: [
                /node_modules\/(htmlparser2)/,
                path.join(__dirname, "./app"), // assuming that your config and app are in the same folder.
            ],
            query: {
                presets: ["es2015", "stage-0"],
            },
        },
    ],
};
module.exports = config;

This answer was inspired by this webpack issue.

Warnings

The HTML module is forgiving : if an image cannot be parsed, the module will not crash. It will instead continue processing the rest of the HTML normally.

Since version 3.38.0 of the HTML module, if something in the HTML is off, the HTML module will call the warnFn function, or by default, log the warning.

For example, if you try to include an image as base64 and the base64 is invalid, now the warnFn will be called.

Example :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            ignoreCssErrors: true,
            // the styleSheet is invalid, it has only an opening tag
            styleSheet: `
                p {
            `,
            warnFn(errors) {
                console.log("My errors :");
                for (const error of errors) {
                    console.log(error.message);
                }
            },
        }),
    ],
});
doc.render({
    html: `<img src="data:image/webp;base64,UklGRhwDAABXRUJQVlA4WAoAAAAgAAAACQAACQAASUNDUKACAAAAAAKgbGNtcwQwAABtbnRyUkdCIFhZWiAH5wAHAAoACQAxABRhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1kZXNjAAABIAAAAEBjcHJ0AAABYAAAADZ3dHB0AAABmAAAABRjaGFkAAABrAAAACxyWFlaAAAB2AAAABRiWFlaAAAB7AAAABRnWFlaAAACAAAAABRyVFJDAAACFAAAACBnVFJDAAACFAAAACBiVFJDAAACFAAAACBjaHJtAAACNAAAACRkbW5kAAACWAAAACRkbWRkAAACfAAAACRtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACQAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABzAFIARwBCbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA9tYAAQAAAADTLXNmMzIAAAAAAAEMQgAABd7///MlAAAHkwAA/ZD///uh///9ogAAA9wAAMBuWFlaIAAAAAAAAG+gAAA49QAAA5BYWVogAAAAAAAAJJ8AAA+EAAC2xFhZWiAAAAAAAABilwAAt4cAABjZcGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACltjaHJtAAAAAAADAAAAAKPXAABUfAAATM0AAJmaAAAmZwAAD1xtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAEcASQBNAFBtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJWUDggVgAAAJACAJ0BKgoACgAAwBIlsAJ0ugH4AUYAC3ve1rUAAP72kROQfTn/HwYkM//0NVFtX+v8fKV/9sG3BvM23w+f7/9K+bmHirW/Pe/+eUk/WCfHX/+eKAAA">`,
});

This will show the two following warnings in the console :

global-style:1:14: missing '}'
webp images are not supported

Use HTML module with normal tags

It is possible to configure the HTML module to work when using tags with no prefix, as in the following template :

Hello {name}

With following code :

const doc = new Docxtemplater({
    paragraphLoop: true,
    linebreaks: true,
    modules: [new HTMLModule({ prefix: "" })],
    // When you set the prefix to "~", the HTML inline tags will be : {~html}
    // When you set the prefix to "*", the HTML inline tags will be : {*html}
    // When you set the prefix to "", the HTML inline tags will be : {html}
});
doc.render({
    name: "<b>John</b>",
});

Will render

Hello John

Will Render

Highlight null values in yellow

It is possible to highlight tags that were not replaced.

The following template, when having no "age" property :

Hello {name}, age {age}

Will render :

Hello John, age {age}

function surroundHighlight(text) {
    return `<mark>${surround(text)}</mark>`;
}
function surround(text) {
    return `{${text}}`;
}
const doc = new Docxtemplater({
    paragraphLoop: true,
    linebreaks: true,
    modules: [new HTMLModule({ prefix: "" })],
    nullGetter(part) {
        if (!part.module) {
            return surround(part.value);
        }
        if (
            part.module ===
            "pro-xml-templating/html-module-inline"
        ) {
            return surroundHighlight(`${part.value}`);
        }
        if (
            part.module ===
            "pro-xml-templating/html-module-block"
        ) {
            return surroundHighlight(`~~${part.value}`);
        }
        if (part.module === "rawxml") {
            return "";
        }
        return "";
    },
});

doc.render({
    first_name: "John",
});

Highlight all replaced values in yellow

It is possible to highlight all replaced tags.

The following template

Hello {name}, age {age}

Will render :

Hello John, age 12

Using following code :

const doc = new Docxtemplater({
    paragraphLoop: true,
    linebreaks: true,
    modules: [
        new HTMLModule({
            prefix: "",
            styleSheet: `
                * {
                    background-color: yellow;
                }
            `,
        }),
    ],
});

doc.render({
    name: "John",
    age: "12",
});

Markdown to HTML

It is possible to use markdown instead of HTML in your data passed to docxtemplater using the marked library.

First install it with :

npm install marked

In your code, use a custom parser that will translate your markdown to HTML :

const { marked } = require("marked");
function parser(tag) {
    return {
        get(scope, context) {
            let result;
            // in our example above, scope is `{ "name": "John" }`
            // because that is the data passed to docxtemplater
            if (tag === ".") {
                result = scope;
            } else {
                // return the property "name" of the scope object.
                result = scope[tag];
            }
            if (
                [
                    "pro-xml-templating/html-module-block",
                    "pro-xml-templating/html-module-inline",
                ].indexOf(context.meta.part.module) !== -1
            ) {
                result = marked.parse(result.toString());
            }

            return result;
        },
    };
}
const doc = new Docxtemplater(zip, {
    parser,
    paragraphLoop: true,
    linebreaks: true,
    modules: [new HTMLModule()],
});
doc.render({
    htmlDescription:
        "Hello **John**, did you hear about [duckduckgo](https://ddg.gg) ?",
});

Does the HTMLModule use altchunks ?

The HTML module does not use altchunks, because those do not support all kind of tags, and also, not all Word readers can read alt chunks (WPS Office, Google Docs, Libreoffice do not support altchunks.

This is why we've implemented our own conversion system, that really converts HTML into OpenXML.

Keeping a table on the same page

Since version 3.54.0, it is possible to use the CSS property : break-inside:avoid on <table> elements in order to avoid breaking the page inside the table.

It is possible to specify that a table should not break across multiple pages using following setting (available since 3.49.1).

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            styleSheet: `
                table {
                    break-inside: avoid;
                }
            `,
        }),
    ],
});

doc.render({
    html: `
        ${"<p>Hello</p>".repeat(15)}
        <table>
          ${"<tr><td>Ho</td><td>Ho</td></tr>".repeat(20)}
        </table>
    `,
});

CHANGELOG

3.55.1

The italic tag now creates both <w:i/> and <w:iCs/>. This is because some software (PDFTron) doesn't respect the italic setting if using just <w:i/>.

3.55.0

When setting the "blockPrefix" and the "prefix" to "", the library will now automatically use docxtemplater html block tags or docxtemplater html inline tags depending on whether there is some other content in the same paragraph.

This allows to write all HTML tags with just {name}, by using following configuration :

const htmlOptions = {
    prefix: "",
    blockPrefix: "",
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({
    html: "Text",
});
  • Bugfix issue when having
    tag right before a font tag, like this :

    <p>
    <font>
        <font>
            XX
        </font>
    </font>
    <br>
    <font>
        <font>
            XX
        </font>
    </font>
    </p>
    

    The br tag would in this case be ignored

  • Add support for <font color="713ffe"> tag. Previously, using a font tag caused an error.

3.54.0

Add support for break-inside: avoid; on tables (which uses keepNext setting).

3.53.2

Update default warnFn to avoid showing duplicated errors.

3.53.1

Add support for async mode when using img.getSrcSize.

3.53.0

When using lists (ordered or unordered lists), the paragraph style of the HTML tag will now be kept if it exists.

Previously, the pstyle called "TextBody" was always used, which is incorret.

The module now also apply the <w:keepNext> parameter on list items if it is set.

If the text that contains the {~~html} tag has the following set as a run property : <w:spacing w:after="200" w:before="0">, this value will be used as the default value for spacing for paragraphs, lists, and all other tags.

3.52.0

Add support for margin-top and margin-bottom on list containers (<ul> and <ol>).

3.51.0

Add support for padding-top and padding-bottom on paragraphs.

3.50.0

Correctly handle <ins> and <del> around <ul> and <ol>

The following will now work correctly :

<del>
    <ul>
        <li>List which is deleted</li>
    </ul>
</del>
<ins>
    <ul>
        <li>List which is inserted</li>
    </ul>
</ins>

Previously the "underline" or the "strikethrough" would be ignored in this case.

3.49.5

Bugfix to work correctly with * selector even on block tags.

The following will work :

{~~html}
const htmlOptions = {
    styleSheet: `
        * {
            color: blue;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});

doc.render({
    html: "Text",
});

3.49.4

Make it possible to use prefix from the constructor

3.49.3

Add typescript typings to be able to change the module prefix

3.49.2

Bugfix to improve keepNext support (added in 3.49.1)

Even when having empty cells, keepNext is still applied.

The following code previously did not apply keepNext to empty cells, but now iit works :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            elementCustomizer(element) {
                // note that you could also add a more complex CSS selector, such as td.keepnext
                if (element.matches("td")) {
                    return { keepNext: true };
                }
            },
        }),
    ],
});

doc.render({
    html: `    <p>Hello</p>
    <table>
        <tr>
            <td>Title1</td>
            <td>Title2</td>
        </tr>
        <tr>
            <td></td>
            <td>
            </td>
        </tr>
        <tr>
            <td>C1</td>
            <td>C2</td>
        </tr>
    </table>`,
});

3.49.1

Add support for setting keepNext to be able to avoid breaking pages in a table or in a group of paragraphs.

3.49.0

Add support for :

  • <center> tag to place a paragraph to the center
  • <template> tag to ignore some part of the HTML
  • <p hidden>Hidden</p> to hide a given element

3.48.3

Bugfix when having multiple colspan, like this :

<table border="1">
<tbody>
<tr>
<td colspan='8'>ABC</td>
</tr>
<tr>
<td colspan='8'>DEF</td>
</tr>
<tr>
<td colspan='4'>GHI</td>
<td colspan='4'>KLM</td>
</tr>
</tbody>
</table>

Previously, some cells would have a width of 0, which meant that some cells were completly hidden.

Now, the cells width are equally distributed in this case.

3.48.2

Make it possible to use block images and align the image to the left or to the right.

In order to do this (align to the right), you have to use the following in your code :

const htmlOptions = {
    styleSheet: `
        img {
            display: block;
            margin-left: auto;
            width: 30px;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({ html: "<img src='.....'>" });

You can align to the left with the following styleSheet :

const htmlOptions = {
    styleSheet: `
        img {
            display: block;
            margin-right: auto;
            width: 30px;
        }
    `,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({ html: "<img src='.....'>" });

3.48.1

Add support for text-transform: uppercase.

Also, when using font-variant: normal, both small caps and all caps style will be overwritten correctly (previously only small caps was overwritten).

3.48.0

Add containerType key to each part, which contains one of the following string :

  • if the container is a textbox, "textbox"
  • if the container is a table cell, "table-cell"
  • if the container is a picture, "picture"
  • if the container is a page, "page"

Correctly calculate the width of each table cell, even when using colGrid and when having merged cells.

3.47.1

Allow to customize tblStyle from styleTransformer :

const htmlOptions = {
    styleTransformer(tags) {
        tags.table.data.tblStyle = ["TableGrid1"];
        return tags;
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(/* data */);

Note that this will change the tblStyle for each table.

It is also possible to match a class by using the more powerful elementCustomizer method :

const htmlOptions = {
    elementCustomizer({ classNames, name }) {
        if (
            classNames.indexOf("newtable") !== -1 &&
            name === "table"
        ) {
            return {
                tblStyle: "Grid1",
            };
        }
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(/* data */);

3.47.0

  • Make it possible to control how block placeholders, such as :
{~~block} some other text

Should be handled when some other text is present in the paragraph.

3.46.4

  • When including the module using webpack, throw specific error if cssParser could not be loaded.

See this Create React App issue and this @adobe/css-tools issue.

3.46.3

  • Bugfix when using line-height attribute on a paragraph that has no pStyle (this now uses the "w:docDefaults" default font size.

3.46.2

  • Add support for "min-width" on table element
  • Apply default width if having table without width and colgroup with pct width

3.46.1

Add support for <figure> and <figcaption> tag (which renders exactly like a div).

3.46.0

Add support for <hr> tag.

3.45.0

  • Allow to set props in styleTransformer, to create new tags, such as this :

    const htmlOptions = {
        styleTransformer(tags) {
            tags.highlight = {
                type: "inline",
                data: {
                    props: [
                        {
                            type: "string",
                            tag: "w:b",
                            value: "<w:b/>",
                        },
                        {
                            type: "string",
                            tag: "w:highlight",
                            value: '<w:highlight w:val="yellow"/>',
                        },
                    ],
                },
            };
            return tags;
        },
    };
    
  • Allow to create customTag and render all children using handleChildren.

  • Add support for <mark> tag (for highlighting text in yellow).

3.44.0

Add support for "customTags" API to create new handlers for some HTML tags.

3.43.2

Avoid stacktrace if setting line-height to 0, like this :

doc.render({
    html: '<p style="line-height: 0">Test</p>',
});

The following error was thrown previously :

Error: lineHeight === 0
at js/add-style.js
at js/style.js
at Array.forEach (<anonymous>)
at forEachStyleDeclaration (js/style.js)
at addParagraphStyle (js/add-style.js)
at Object.getParagraphs (js/paragraph.js)
at js/html-transformer.js
at Array.map (<anonymous>)
at HtmlTransformer.getBlockContent (js/html-transformer.js)
at HtmlTransformer.transformBlock (js/html-transformer.js)
at HtmlModule.render (js/index.js)
at moduleRender (docxtemplater/js/render.js)
at docxtemplater/js/render.js
at Array.map (<anonymous>)
at render (docxtemplater/js/render.js)
at XmlTemplater.render (docxtemplater/js/xml-templater.js)
at docxtemplater/js/docxtemplater.js
at Array.forEach (<anonymous>)
at Docxtemplater.render (docxtemplater/js/docxtemplater.js)
at docxtemplater/js/docxtemplater.js

Now, the document will be generated with a small line-height in this case.

3.43.1

On some versions of Word (on the Microsoft Word version in Windows), following "border"-like elements would sometimes appear :

Bug before version 3.43.1
Bug before version 3.43.1

(See lines between x-A-B,D-E)

This was happening when using the padding property.

This issue should no more occur again.

3.43.0

Bugfix issue with line-height when using font-size in rem, like in this example :

doc.render({
    html: '<p style="font-size: 2rem; line-height: 1.4">Test</p>',
});

The following stacktrace was shown :

Error: lineHeight === 0
at js/add-style.js
at js/style.js
at Array.forEach (<anonymous>)
at forEachStyleDeclaration (js/style.js)
at addParagraphStyle (js/add-style.js)
at Object.getParagraphs (js/paragraph.js)
at js/html-transformer.js
at Array.map (<anonymous>)
at HtmlTransformer.getBlockContent (js/html-transformer.js)
at HtmlTransformer.transformBlock (js/html-transformer.js)
at HtmlModule.render (js/index.js)
at moduleRender (docxtemplater/js/render.js)
at docxtemplater/js/render.js
at Array.map (<anonymous>)
at render (docxtemplater/js/render.js)
at XmlTemplater.render (docxtemplater/js/xml-templater.js)
at docxtemplater/js/docxtemplater.js
at Array.forEach (<anonymous>)
at Docxtemplater.render (docxtemplater/js/docxtemplater.js)
at docxtemplater/js/docxtemplater.js

Now the document is rendered correctly.

More generally, support for the units "rem" and "em" has been added.

Also, support for the "%" unit on font-size has been added, like in this example :

doc.render({
    html: '<p style="font-size: 30px;">30-<span style="font-size: 50%;">15</span></p>',
});

3.42.4

Upgrade module to use NodeNext moduleResolution setting. See explanation here

3.42.3

Bugfix issue when using a document that contains a <w:sectPrChange> (which is a tracked "section" change, ie a tracked "header" or "footer" change :

TypeError: Cannot read properties of null (reading 'map')
at collectSectionsWidth (get-dimensions.js)
at Object.collect (es6/get-dimensions.js)
at HtmlModule.preparse (es6/index.js)
at docxtemplater/js/parser.js
at Array.forEach (<anonymous>)
at preparse (docxtemplater/js/parser.js)
at Object.preparse (docxtemplater/js/parser.js)
at XmlTemplater.preparse (docxtemplater/js/xml-templater.js)
at Docxtemplater.precompileFile (docxtemplater/js/docxtemplater.js)
at docxtemplater/js/docxtemplater.js
at Array.forEach (<anonymous>)
at Docxtemplater.compile (docxtemplater/js/docxtemplater.js)
at new Docxtemplater (docxtemplater/js/docxtemplater.js)
at createDocV4 (docxtemplater/js/tests/utils.js)
at Context.loadAndCompile (es6/test.js)
at Context.loadAndRender (es6/test.js)
at Context.<anonymous> (es6/test.js)
at process.processImmediate (node:internal/timers)

3.42.2

Use new resolvedId API => requires docxtemplater@3.43.0

3.42.1

Bugfix when using pagebreak before inside div, like this :

doc.render({
    html: `
<div>
    <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    </p>
    <p style='break-before: page'>
        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    </p>
    <p>
        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    </p>
    <p>
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
    <p>
        Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
    </p>
</div>`,
});

Previously, all paragraphs would have the break-before page propert set.

Now, only the correct paragraph has that property set.

3.42.0

  1. When using styleSheet option with "inline" tag, such as {~html}, the following stylesheet would not correctly apply.

    const htmlOptions = {
        styleSheet: `
            * {
                color: red;
            }
        `,
    };
    const doc = new Docxtemplater(zip, {
        modules: [new HTMLModule(htmlOptions)],
    });
    doc.render({ html: "My Text" });
    

    Now, even in inline mode, simple text will use the style defined by the * selector.

  2. Add support for changing font-variant (to set some text to be in "small-caps").

    Like this :

    const htmlOptions = {
        styleSheet: `
            * {
                font-variant: small-caps;
            }
        `,
    };
    const doc = new Docxtemplater(zip, {
        modules: [new HTMLModule(htmlOptions)],
    });
    doc.render({
        html: "<span>Foobar</span>",
    });
    

    This also allows to remove the "small-caps" variant by using * { font-variant: normal; }.

3.41.9

Fix bug when using renderAsync and parser compilation fails : the error should now be shown inside a multierror. To to this, we know use sm.getValueAsync in resolve instead of sm.getValue

3.41.8

Bugfix to set or get xml attributes correctly, even when using tabs instead of spaces in tags attributes

3.41.7

Set module.priority in order to have no more issues related to module ordering

3.41.6

Multiple bugfixes when used in async mode (for some templates/data only) :

this.buffers[0].slice is not a function
this.buffer.charCodeAt is not a function
Cannot read properties of undefined (reading 'replace')

3.41.5

Avoid corruption because of duplicate link to "numbering.xml".

This issue would appear only in certain cases on certain particular word versions.

It would appear if your template contained list items, and the HTML data also contained list items.

3.41.4

When having following HTML :

<ol>
    <li style="font-size: 40px;">Big list</li>
    <li style="font-size: 8px;">Small list</li>
</ol>

In previous versions, the bullet was not resized in the resulting docx.

Now, the bullet (or numbering element) will also be resized, not just the text in the list item.

This also works now with other run properties such as text color, italic, bold, …

Before version 3.41.4
Before version 3.41.4

Version 3.41.4
Version 3.41.4

3.41.3

Make html module compatible with the image module version 3.23.6

If you don't upgrade your HTML module to 3.41.3, you will see that images are missing when you use the <img> tag

3.41.2

Add support for nth-child(3n+1), and nth-child(0n+3) and nth-child(-n+3).

3.41.1

Add correct support for nth-child(even) and nth-chld(odd).

Correctly inherit background-color from thead into td.

3.41.0

Add correct support for line-height

Previously there was a bug : line-height was working only when also setting the margin-top or margin-bottom property.

Now, the line-height alsow works with percentages or numbers (acts as multiplier to the fontsize), as in :

p {
    line-height: 200%;
    line-height: 1.3;
    line-height: 20pt;
    font-size: 12px;
}

3.40.4

  • Correctly calculate pageHeight by removing marginTop and marginBottom

  • Add pageWidth

3.40.3

This release needs version 3.40.1 of docxtemplater open-source.

When the docx document is the following

{#loop}
{~~html}
{/}

The pageHeight was not correctly added to the "part".

Now, the pageHeight should always be present, inside loops, outside loops, and in async and sync mode.

3.40.2

Add correct typings for part.section

3.40.1

Add support for text-align: justify on <li> elements.

3.40.0

Add support to retrieve the pageHeight of the section that contains the current tag.

(The value is in pixels)

const imageOptions = {
    // getImage: as usual
    getSize(img, value, tagName, context) {
        const pageHeight = context.part.pageHeight;
        console.log(pageHeight); // will log 1112
        return [100, 100];
        // or return anything you like
    },
};

It is also now possible to view the context.part.section for more information about the current section (number of columns, …).

3.39.13

Bugfix when using following HTML :

doc.render({
    html: '<h2><strong style="color: rgb(0, 0, 0); background-color: transparent;">General</strong></h2>',
});

Previously, the background was rendered to black in this case.

3.39.12

Add customization to be able to remove list style, when using the following template for example :

1. XXX
2. YYY
3. {~~html}
4. ZZZ

With following code :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            elementCustomizer(element) {
                if (element.matches("td")) {
                    return { resetList: true };
                }
            },
        }),
    ],
});
doc.render({
    html: "<table><tr><td>Foobar</td></tr></table>",
});

This will now output a table without any list items

3.39.11

Update module.clone() internal to make module work well with subsegment module (passthrough module.prefix)

3.39.10

Add support for list-style: none to completely hide bullets.

3.39.9

Add correct typescript typings for element.parsedStyle.

const htmlOptions = {
    getProps({ element }) {
        // the parsedStyle has following shape :
        element.parsedStyle = [
            {
                property: "width",
                value: "100px",
            },
            {
                property: "text-align",
                value: "center",
            },
        ];
    },
};

3.39.8

Bugfix : Correctly calculate "parsedStyle" inside "getSize" function of image module even in async mode.

3.39.7

Correctly render <ol> when tag is present inside a list, even when the list is referenced by a pStyle.

1. XXX
2. YYY
3. {~~.}
4. ZZZ

Now the HTML will keep the existing style

3.39.6

Remove css dependency which is no more updated since 2020.

We replace it by @adobe/css-tools which gets regular updates.

3.39.5

Add support to have a shape that contains some drawing + HTML inside the shape.

Previously, if the shape contained {~~html},

Then the result would contain the string "~~html", followed by the rendered value of the html

Now, the string "~~html" is no more present in the output.

3.39.4

Add support for percent values in colgroup, like this :

<table>
    <colgroup>
        <col style="width: 25.9%;" />
        <col style="width: 74.1%;" />
    </colgroup>
    <tbody>
        <tr>
            <td>A</td>
            <td>B</td>
        </tr>
    </tbody>
</table>

3.39.3

Show warning if using element of type <table>, or of type block (<p>, <h1>, …) inside an inline HTML tag such as {~html}.

You have to use block html tags : {~~html} to include block elements.

3.39.2

Do not throw Error when having "colgroup" tag inside "inline" element : {~inline}

3.39.1

Add support for passing array of strings to the HTMLModule.

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule({})],
});
doc.render({
    html: [
        `
        <p>Foobar</p>
    `,
        `
        <p>Foobar</p>
       `,
    ],
});

This allows to simplify the template in some cases from :

{#html}
{~~.}
{/}

into :

{~~html}

3.39.0

Add support for CSS specificity.

Now, style rules will follow CSS specificity : #id is more specific to .class, and .class is more specific than p, so the rules are applied in the same order than in browsers now.

Add support for break-after: avoid;

This can be used to make sure that multiple paragraphs of text will be kept on the same page. Thus the Word engine will break in order to keep the paragraphs together.

One common use case would be to write the following :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            styleSheet: `
                p, h1 { break-after: avoid; }
                p:last-child { break-after: unset; }
            `,
        }),
    ],
});
doc.render({
    html: `
        <p>Foobar</p>
        <p>Foobar</p>
        <p>Foobar</p>
        <p>Foobar</p>
    `,
});

3.38.0

Add warnFn to be able to catch warnings.

The HTML module is like HTML in the real world : forgiving.

Now, it is possible to catch warnings in a warning function, and by default warnings will be printed to the console using console.error();

3.37.8

Bugfix when using following template :

{#loop}
{ . }
{/}

The following error would be thrown when using the angular expressions parser :

HTMLData should be a string (given Object)

3.37.7

Bugfix when having the following HTML :

<table style="width:100%;border-style:none;break-after:page">
    <thead>
        <tr style="background-color:#0057ab;color:white">
            <th>Bang</th>
        </tr>
    </thead>
</table>

Previously, this would throw the following error :

Cannot read properties of undefined (reading 'tag')

Now, the break-after:page property is properly parsed.

3.37.6

Allow HTML data to be an integer (it will then be autoconverted into a string).

When the HTML data is not a string nor an integer, it will now error and show the type of the passed object ("Object", "Promise", "Array", …)

(This improves a change that was added in 3.37.4).

The message will now be, for example :

HTMLData should be a string (given Promise)

If you get this message with type Promise, it probably means that you should be using "doc.renderAsync()" instead of doc.render(), see this page for docs about async mode.

If you get this message with some other type, check your dataset, or the expressionFilters that you have defined, they are probably returning an object instead of a string.

3.37.5

Take into account max-width of table even when using colGroup. Take into account width of table even when using colGroup.

3.37.4

Throw specific error if the data passed to the HTML module is not a string.

Previously, with following code :

const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule()],
});
doc.render({
    html: { foo: "bar" },
});

The stacktrace would be :

this.buffers[0].slice is not a function
at Parser.getSlice (node_modules/htmlparser2/lib/Parser.js:433:37)

3.37.3

Bugfix, to make it possible to customize getProps of the image module when used together with the HTML module.

This release also needs version Image module 3.21.1 or later

3.37.2

Call nullGetter function if the resolved value is null.

This allows to set some default value for the HTML tags if the value is null.

3.37.1

Make list items : <li> <ol> <ul> work correctly for dotx templates and other less common : docm, …

3.37.0

It is now possible to add a tabstop using the "-xt-tab-stop" CSS property, see sample code in the Docs.

3.36.2

Fix a corruption that would happen when using a table with the vertical-align: inherit property.

Now the document is no more corrupt.

3.36.1

Bugfix a corruption that would happen when placing an HTML tag in the header of a document.

Previously, the image would become corrupt.

Now, the image is correctly kept.

3.36.0

When writing {~~html} inside a bullet list, the generated paragraph will use the bullet list.

3.35.5

Bugfix to avoid corruption when having textbox with image on the same paragraph as some HTML data

3.35.4

Add support for setting the pStyle for block images, using the following code :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            elementCustomizer(element) {
                if (element.name === "img") {
                    return {
                        pStyle: "Image",
                    };
                }
            },
        }),
    ],
});
doc.render(data);

3.35.3

Correctly work if using img.getValue function that returns null : in this case, the module will not return a <w:r></w:r>, but instead it will return ""

3.35.2

Bugfix when using the following code :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            elementCustomizer({ name }) {
                if (name === "li") {
                    return {
                        pStyle: "Heading1",
                    };
                }
            },
        }),
    ],
});
doc.render({
    html: `
        <ul>
        <li style="margin: 0;">HiHo</li>
        <li style="margin-top: 0; margin-bottom: 0px;">HiHo</li>
        <li style="margin-top: 0px; margin-bottom: 0px;">HiHo</li>
        </ul>
    `,
});

This was failing with following stacktrace :

TypeError: (customProperties || []).forEach is not a function
at addLiStyle (docxtemplater-html-module/js/paragraph.js:310:28)

Now the document is generated correctly

3.35.1

Bugfix when input docx did not contain any "word/styles.xml" file, the following stacktrace was shown :

TypeError: Cannot read properties of undefined (reading 'getElementsByTagName')
at new StyleManager (style-manager.js:15:32)

Now, the docx file is generated without any Error

3.35.0

Add support for colgroup tag to define width of table.

3.34.0

Bugfix to work correctly with files that have tp/document-orig.xml.

Requires version 3.34.0 of docxtemplater core

3.33.2

Bugfix to avoid adding styles with w:default="1".

3.33.1

Fix getSize function to call it with 4 parameters instead of one.

3.33.0

Add support for <span style="white-space:pre">Hello Foo</span>

3.32.1

Bugfix of duplicate decoding of string.

When passing following data :

const html = "<p>&amp;lt;</p>";
doc.render({ html });

The following would be shown in the template <, but this should instead show &lt;.

3.32.0

Remove deviceWidth option.

If you were not using the deviceWidth option or the getDxaWidth, then this change won't affect you.

Instead, you should now use the dpi option.

The default deviceWidth was previously : 470.10416666666663

The now default dpi is now 75.

If you were previously setting the deviceWidth to 1000, than, to calculate, the dpi, you have to use the formula : dpi = deviceWidth / 470.10416666666663 * 75.

For example, here are the deviceWidth to dpi mapping

deviceWidth = 1000 => dpi = 159.53
deviceWidth = 750 => dpi = 119.65
deviceWidth = 500 => dpi = 79.76

3.31.5

Allow to set the size of checkboxes using following style :

doc.render({
    html: `<input type="checkbox" style="height: 7px; width: 7px;" />`,
});

3.31.4

Keep existing text boxes that are contained in paragraphs that contain an {~~html} tag.

Previously such templates would fail with the following error :

TypeError: Cannot read properties of undefined (reading 'parts')

This also means that in that particular case, the paragraph will be kept if the HTML data value is empty.

3.31.3

Avoid possible issue of "Maximum call stack size exceeded"

3.31.2

Simplify internal generation of lists.

3.31.1

Improve support for nested lists together with divs.

Even li>div>div>ol should work correctly now.

<div>
    testing list
    <ol>
        <li>
            <div>first level</div>
            <div>
                <div>
                    <ol>
                        <li>
                            <div>second level</div>
                            <div>
                                <ol>
                                    <li>
                                        <div>third level</div>
                                    </li>
                                </ol>
                            </div>
                        </li>
                    </ol>
                </div>
            </div>
        </li>
    </ol>
</div>

3.31.0

Improve support for setting tableStyle of a table.

When using the tableStyle option, now the colors of the used table will be correctly copied from word/styles.xml, taking into account the "firstRow", "lastRow", "firstCol", …

3.30.5

Avoid corruption when having a <table> tag inside a Word table that results in a width of 0 in async mode, which corrupts the document

3.30.4

Fix error when using a loop that contains some inline HTML tag.

Raw tag not in paragraph error

This would fail when using the following template (on some occasions when the tag was written in the same run, <w:r>) :

{#html}The html is {~html}{/}

3.30.3

Bugfix to take into account img { display: block; margin:auto; } when using docxtemplater in async mode.

3.30.2

Avoid corruption when using img { display: block; margin:auto; } with images inside <li> elements.

See : Github Issue #655

Now, <img> tags that are inside <li> tags will always be rendered as "inline-block" elements.

3.30.1

Bugfix to stop adding empty paragraphs after tables.

Please update the main docxtemplater library to 3.29.4 to fix this problem correctly

3.30.0

Do not add an empty paragraph after each <table>

Make it possible to specify table { margin-bottom: 20px; } to add a margin after tables.

3.29.9

Bugfix to make it possible to have a Promise returned in the getSize function.

Previously the message shown was :

"Uncaught (in promise) Error: Size for image is not valid (it should be an
array of two numbers, such as [ 1024, 1024 ])

3.29.8

Improve typescript definitions

3.29.7

Bugfix corruption when having one column with fixed width, and 3 columns with auto width.

3.29.6

Bugfix to use the synonym of "Heading1" style if the synonym exists.

3.29.5

Bugfix when using a dotx template and using a table.

The table would appear as zero-width, which would cause a corruption.

Now the template is handled correctly.

3.29.4

Bugfix to take into account border="0" property in table, like this :

<table border="0">
    <tr>
        <td>Table with no borders</td>
    </tr>
</table>

3.29.3

Make package size smaller

3.29.2

Bugfix corrupt document when adding HTML link inside header

3.29.1

Avoid using styles that reference non-existing styles

3.29.0

Make module compatible with docxtemplater@3.28.0. Please make sure to update docxtemplater to 3.28.0 at the same time you update this module. The internal change made is the use of the new matchers API which fixes bugs that were triggered depending on the order of the modules that are attached to the instance. Now the order of the modules should not matter as expected.

3.28.0

Make module compatible with docxtemplater@3.27.0. Please make sure to update docxtemplater to 3.27.0 at the same time you update this module

3.27.0

  • Use WidthCollector for each parsed file (makes module compatible with image module 3.10.0)

3.26.10

  • Add support for <table align="right">. It is also possible to use <table style="margin-left: auto"> to align a table to the right.

  • Add support for bordercolor attribute on <table bordercolor="#bbb">.

  • Add support for cellpadding attribute on <table cellpadding="5">.

3.26.9

Make img.getValue optional, even when running docxtemplater in async mode.

3.26.8

Update typing to allow ArrayBuffer or Promiseon getValue function

3.26.7

Update typing files to add types for using together with image module, with

const htmlOptions = {
    ignoreUnknownTags: true,
    img: {
        Module: ImageModule,
        getValue() {
            return Promise.resolve(Buffer.from("hhh"));
        },
        getSize() {
            return [100, 100];
        },
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

3.26.6

Add internal clone method (to use image tags with the Subtemplate.Segment module)

3.26.5

Use @xmldom/xmldom instead of xmldom, see this github issue

3.26.4

Generate files in built with correct filename In previous versions, the filename was always build/docxtemplater.js. Now the filename is build/html-module.js The .min.js file is also created now.

3.26.3

Add support for <ol start="3"><li>An item</li></ol> to start the list items at a different position, to render :

3. An item
4. An other item

3.26.2

Add support for images without src when using following CSS :

img {
    display: block;
    margin: auto;
}

Previously this would result in a corrupt document

3.26.1

Add support for setting the prefix to an empty string (to be able to replace normal tags by inline HTML).

To change the prefix for block tags, one will have to change the prefix like this :

For example to use {!!html} for block html, and {tag} for inline html :

function getHTMLModule() {
    const htmlModule = new HTMLModule();
    htmlModule.prefix = "";
    htmlModule.blockPrefix = "!!";
    return htmlModule;
}
const doc = new Docxtemplater(zip, {
    modules: [getHTMLModule()],
});
doc.render(data);

3.26.0

Add support for centering images in the output word document.

To use it, you need to add following styleSheet :

const doc = new Docxtemplater(zip, {
    modules: [
        new HTMLModule({
            styleSheet: `
                img {
                    display: block;
                    margin:auto;
                }
            `,
        }),
    ],
});
doc.render(data);

3.25.15

Add typescript definitions for public API

3.25.14

Improve support for columns width, so that tables inside columns which are of unequal width will render correctly.

For example, if you have a document with two columns, one of width of 2/3 of the document, and an other one of 1/3 of the document width, a table with width of 100% will be calculated correctly.

Previously, the width would be in this case always splitted equally, so you would have a smaller table on the column with 2/3 of the space.

3.25.13

Move webpack from dependency to devDependency (which triggered an error during installation on node version 10)

3.25.12

Bugfix issue when using "text-align: right", on a table cell, where the {~~html} tag was explicitly left-aligned.

Now, the text-alignment from the HTML style will take precedence and show the text aligned correctly.

3.25.11

Add support for table-layout: fixed; CSS property (which translates to <w:tblLayout w:type="fixed"/>)

3.25.10

Add support to customize pStyle for <pre> tags, for example

const htmlOptions = {};
htmlOptions.elementCustomizer = function (element) {
    if (element.name === "pre") {
        return { pStyle: "Code" };
    }
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({
    html: `<pre>Hello from
        pre tag</pre>`,
});

3.25.9

Add support for repeatHeaderRow and cantSplit on table row elements with elementCustomizer

For example, you can now do :

const htmlOptions = {};
htmlOptions.elementCustomizer = function (element) {
    if (element.matches("tr.header")) {
        return {
            cantSplit: true,
            repeatHeaderRow: true,
        };
    }
    if (element.matches("tr")) {
        return {
            cantSplit: true,
        };
    }
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render({
    html: `
        <tr class="header">
            <td>Head1</td>
            <td>Head2</td>
        </tr>
        <tr class="header">
            <td>Head3</td>
            <td>Head4</td>
        </tr>
        <tr><td>Some Text</td><td>Other Text</td></tr>
        ....
        ....
        <tr><td>Some Text</td><td>Other Text</td></tr>
    `,
});

And this will set the two header table rows to be repeated across each page when the table overflows. The cantSplit property can also be used to avoid the table row to be splitted between two pages.

3.25.8

Add support for <ol type="I"> to show ordered lists with uppercase roman numbers.

Here are the possible types :

  • type="1" The list items will be numbered with numbers (default)
  • type="A" The list items will be numbered with uppercase letters
  • type="a" The list items will be numbered with lowercase letters
  • type="I" The list items will be numbered with uppercase roman numbers
  • type="i" The list items will be numbered with lowercase roman numbers

Add support for style list-style-type and list-style, to use CSS to customize numbering.

For example :

const htmlOptions = {
    styleSheet: `
    ol {
        list-style-type: upper-alpha;
    }
    ol.roman {
        list-style: upper-roman;
    }
`,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

The list of possible values are : decimal-leading-zero, decimal, lower-alpha, lower-latin, upper-alpha, upper-latin, lower-roman, upper-roman

3.25.7

Add support for background-color on table element (previously it could only be set on tr or td)

3.25.6

Add support to customize bullet colors and font-family using elementCustomizer

3.25.5

Add support to customize li pStyle using elementCustomizer

3.25.4

To use this version with the image-module, you need to use the image-module version 3.8.4

Allow to retrieve containerWidth in getSize function when using <img> tags.

For example :

const ImageModule = require("docxtemplater-image-module");
const htmlOptions = {
    img: {
        Module: ImageModule,
        getSize({ part }) {
            return [
                part.containerWidth || 100,
                part.containerWidth || 100,
            ];
        },
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});

doc.render({ html: "<b>Hello</b>, Foo !" });

This allows to for example show all images as being the size of the container (most commonly, the size of the page, except when the HTML tag is inside a table).

3.25.3

Allow to have comments in stylesheets

3.25.2

Bugfix to take into account "border:none" on <table> elements

3.25.1

Correctly keep <w:rtl> tag in order to allow to insert "right-to-left" languages such as Hebrew, Arabic, Urdu, …

3.25.0

Add support for <style> tag inside HTML tags

3.24.7

Disallow to pass something other than a string to the stylesheet option (because this option only allows to pass a given global stylesheet)

3.24.6

Bugfix, when having text surrounding the HTML inline tag, such as in :

Hello {~name}, how are you ?

The HTML module would sometimes misplace the replacement of {~name} and put it at the end of the paragraph.

Now, the module correctly puts the replacement at the correct position.

3.24.5

Use w:lineRule="exact" when using CSS line-height

3.24.4

Add support for line-height attribute.

3.24.3

Improvements for cell widths. Now, when you declare only the widths of td (without defining the width of the table itself), the cell widths will be correct (the table width will be the sum of all cell widths).

For example : this will work :

const htmlOptions = {
    styleSheet: `
td {
    width: 50px;
}
`,
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(data);

Previously, this would result in having a default table width of 450px, and scaling of the cell widths.

3.24.2

Bugfix when having <br> in "implicit paragraph", for example in :

<h1>Hello</h1>
<br />
<h1>Hello</h1>
<br />
<h1>Hello</h1>

In previous versions, this would render two empty paragraphs between each title, now it correctly renders only one

3.24.1

Avoid importing unused styles, such as :

"Heading Car" "Heading 1 Car" "Heading 2 Car" "Citation Car"

Those styles are now imported only if the corresponding style does not exist in the templated document.

3.24.0

Add support for :

  • <table> that contains some empty <tr> elements (it would generate a corrupt document)
  • <input type="text">
  • <form> tag (no specific style currently)
  • <textarea> tag (no specific style currently)
  • <button> tag (no specific style currently)
  • <label> tag (no specific style currently)

3.23.7

Fix issue with css module :

Module not found: Error: Can't resolve 'fs' in '[...]\node_modules\css\lib\stringify'

Now, the module requires only the part that it uses, which removes this error.

3.23.6

Add support for "dotted" border-style.

Add support for border-style with multiple values (one to four values)

3.23.5

Bugfix to ignore <br> at the end of block elements.

3.23.4

Bugfix support for border styles, such as border: 1px dashed black;

List of handled styles : solid, dashed, double, outset, none, inset

3.23.3

Add third argument to styleTransformer() containing styleIds of the current document.

3.23.2

Bugfix to render space in inline HTML tag when using : <b>Foo</b> <i>Bar</i>

3.23.1

Fix error when using <img> tag without any src. The error message was TypeError: Cannot read property 'replace' of undefined at base64DataURLToArrayBuffer. Now, those images are ignored but do not fail with an error.

3.23.0

Improve table border support :

  • Add support for border-width property on border

  • Add support to change default for table borders with elementCustomizer, for example :

const htmlOptions = {
    elementCustomizer({ name }) {
        if (name === "table") {
            return {
                tblStyle: "TableauNormal",
                defaultBorder: null,
            };
        }
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(/* data */);

This makes it possible to use border style defined in the Word style.

3.22.9

Add support for <ins> and <del> tags (which will render underline and striked text)

3.22.8

Do not produce corrupt output when having either :

  • Tr element without any child : <table><tr></tr></table>

  • Table element without any child : <table></table>

Instead, the table will not be shown at all.

3.22.7

Correctly ignore width='0' on <table> element.

3.22.6.

Do not render newline when it is at the end of a <li> element, for example, in :

<ul>
    <li>Hello<br /></li>
    <li>Hello<br /></li>
</ul>

3.22.5

Render text that is inside an <ul> even if it is not in a ul.

In previous versions, the tag <ul>Hello</ul> would produce an empty paragraph. Now it will render a paragraph with the word "Hello".

3.22.4

Add support for "padding" property.

Previously, only "padding-left", "padding-right", "padding-top" and "padding-top" were working, but not she shorthand padding: 0 property for example.

For table cell margins, support all common units (not just px unit).

3.22.3

Make it possible to specify margin: 0 (or margin-left: 0) on table element. (It was ignored in previous versions)

3.22.2

Return an empty paragraph when using <p><br></p> instead of having a two-line paragraph

3.22.1

  • Bugfix Cannot read property 'getElementsByTagName' of undefined at addRelationship (es6/relation-utils.js:25:32) when using docx file saved from the online office 365 web app.

  • Add styleIds to elementCustomizer API to be able to know which styles are defined in the document when changing pStyle.

3.22.0

  • Remove tableRatio option (you should use deviceWidth instead)

  • Add support for "cm", "in", "mm", "pc", "pt" for all measurements

  • Bugfix do not produce a corrupt document when having escape codes such as an "escape character" (String.fromCharCode(27)). These characters are now ignored, like what a real browser does.

3.21.13

Add support for pt unit in font-size, for example : font-size: 15pt

The pt unit is for now not supported on all measures however.

3.21.12

Declare supportedFileTypes, which allows to use this module with the new docxtemplater constructor which was introduced in docxtemplater 3.17.

3.21.11

Add element.parsedStyle which contains the parsed CSS style for usage in getSize of image module

3.21.10

Add support for text-indent to indent first line of a paragraph.

3.21.9

Bugfix : Do not fail if using more list levels than are defined in pStyle.

For example :

const htmlOptions = {
    styleTransformer: (tags, docStyles) => {
        tags.ul.data.pStyle = ["bulletLevel1"];
        tags.ul.data.useNumPr = false;
        return tags;
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new HTMLModule(htmlOptions)],
});
doc.render(/* data */);

will use bulletLevel1 for each level of bullets.

Previously, this was failing with the following error code :

TypeError: Cannot read property 'oneOf' of undefined

3.21.8

Bugfix : Previously, when having text just before an inline HTML tag, like in :

Hello{~inlineHTML}

The text Hello was removed from the output.

This is no longer the case, the text on the left and on the right of the inline tag will be kept.

3.21.7

If using ignoreUnknownTags to true, hide images instead of throwing an error.

3.21.6

Add support for caption on images when using the image module version 3.7.0 or above.

3.21.5

The runProperties (w:rPr) used where the first encountered, instead of using the one inside the run itself (w:r).

3.21.4

For table tag, when the {~~htmlTag} is inside a multi-column session, the width:"100%" will use the width of one column instead of the width of one page.

3.21.3

Add support for margin-left on paragraphs

3.21.2

Add support for font-family in CSS

3.21.1

Add support for break-after: page and break-before: page in CSS

3.21.0

Add support for <pre> tag

Make it possible to have width: 100% for images inside tables

Fix the calculation of width for images so that a table with a width of 200px shows the same width as an image with width of 200px. Before this release, the images were smaller than expected.

3.20.3

Keep paragraph style including indents and alignment

3.20.2

Add support for pt values on table width

3.20.1

Add support for margin: 0 (without any unit)

3.20.0

Add support for colspan + rowspan on the same cell.

Multiple improvements for rowspan

3.19.5

Add support for Right-To-Left support with w:bidi tag.

Add support for margin-top and margin-bottom on li tags

3.19.4

Bugfix corrupted document when using margin-top or margin-bottom

3.19.3

Add support for margin-top and margin-bottom on paragraphs

3.19.2

Bugfix spacing in li :

<p>
<ul>
<li><em>Lorem ipsum dolor si amet</em> <strong>Test</strong></li>
</ul>
</p>

The space will now be correctly rendered

3.19.1

Bugfix : support vertical-align: middle; for td

3.19.0

Add initial support for rowspan on table td

3.18.4

Bugfix of propagation of style to all paragraphs.

For example, when having :

<div>
    <p>Uncentered</p>
    <p style="text-align:center">Centered</p>
</div>

The first paragraph was centered even if it should not.

3.18.3

Bugfix to avoid Cannot read property 'concat' of undefined" when defining styles on some elements (such as th).

3.18.2

Always generate output with w:sz as integer (instead of float) by using Math.round

3.18.1

Add support for td { width: 20% } in CSS

Bugfix issue of width of all cols being smaller than width of whole table

3.18.0

Add support for :

  • :first-child, :last-child, :nth-child(3) selectors
  • border-left, border-top, border-right and border-bottom on td and th for tables
  • text-align:center on th/td
  • border-style double property

3.17.3

Bugfix for "Cannot read property 'getAttribute' of undefined" when having styles without names.

3.17.2

Bugfix [object Object] shown when using async mode (resolveData) with null value

3.17.1

Bugfix corrupt document when having empty w:sdtContent

3.17.0

Add support for async image generation

3.16.9

Keep fontFamily if set in run properties

3.16.8

Do not corrupt document if having empty value in block html inside table cell

3.16.7

Do not fail if they are no sections at all in the document (return a default size).

3.16.6

Bugfix corrupt document when using table colspan with just one row.

3.16.5

  • Add support for centered tables with margin: 0 auto;

3.16.4

Inherit paragraph properties inside tables.

3.16.3

  • The table color properties were "leaking" from one cell to the other, resulting in wrong colors being used sometimes. This is now fixed

3.16.2

  • Improve list support when ul is a direct child of ol or or is a direct child of ul.

  • Add the style (run properties) of the {~~htmlTag} to bullet points so that the bullet points have the same size as the text

3.16.1

  • Add support for font-weight:bold of font-weight:700

3.16.0

  • Add support for styleSheet option in module constructor

3.15.1

  • Add support for margin-left on ul and ol

3.15.0

  • Better support for ul and ol : when using ols inside uls, if the TextBody style did not exist, the ul and ol style were missing bullets.

  • Add way to customize bullets in the elementCustomizer API

3.14.1

Update html-parser require calls to work well with Rollup

3.14.0

Improve table support (background && background-color, color, font-size.

Do not duplicate runProps anymore

3.13.6

Add support for inline and block <code> tags

3.13.5

Update to support the new image module v3.4.2

3.13.4

Update to support new image module with <svgs> (3.4.1 of the image-module)

3.13.3

Add support for <a name="mark"></a> to generate docx bookmarks

3.13.2

Add support for <a href="#mark">Go to mark</a> and <p id="mark">Mark</p> by using docx bookmarks

3.13.1

Links with no content are now hidden from the generated document (ignored)

3.13.0

Add two additional options for determining the meaning of 1 pixel.

The deviceWidth option explicitly permits to say that you want to have a window of for example 1200 pixels.

The getDxaWidth option to select how many dxas (20th of a point, or 1440 of an inch) your page is.

With these two options, docxtemplater can then accordingly convert any pixel value to a coherent size in your word document.

3.12.0

Add support for setting properties on multiple levels of divs/blockquotes or any block element.

For example :

<div style="text-align: justify;">
    <blockquote>
        Sit aliquid vitae non magni ex Eius saepe molestias
        minima non tempore amet! Accusamus corrupti at ipsa
        necessitatibus consequatur. Corporis autem debitis
        reiciendis illo modi, inventore. Delectus magni sint
        doloremque?
    </blockquote>
</div>

3.11.10

Add support for images inside link and inside lists, for example :

<ul>
    <li>
        <img
            src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QIJBywfp3IOswAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAkUlEQVQY052PMQqDQBREZ1f/d1kUm3SxkeAF/FdIjpOcw2vpKcRWCwsRPMFPsaIQSIoMr5pXDGNUFd9j8TOn7kRW71fvO5HTq6qqtnWtzh20IqE3YXtL0zyKwAROQLQ5l/c9gHjfKK6wMZjADE6s49Dver4/smEAc2CuqgwAYI5jU9NcxhHEy60sni986H9+vwG1yDHfK1jitgAAAABJRU5ErkJggg=="
        />
        Docxtemplater
    </li>
</ul>
<p>
    <a>
        Docxtemplater
        <img
            src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QIJBywfp3IOswAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAkUlEQVQY052PMQqDQBREZ1f/d1kUm3SxkeAF/FdIjpOcw2vpKcRWCwsRPMFPsaIQSIoMr5pXDGNUFd9j8TOn7kRW71fvO5HTq6qqtnWtzh20IqE3YXtL0zyKwAROQLQ5l/c9gHjfKK6wMZjADE6s49Dver4/smEAc2CuqgwAYI5jU9NcxhHEy60sni986H9+vwG1yDHfK1jitgAAAABJRU5ErkJggg=="
        />
    </a>
</p>

3.11.9

Add part argument to getSize

3.11.8

  • Add support for : text-align: justify

  • Add support for : bgcolor attribute on td and tr

3.11.7

  • Add support for : padding-top,padding-bottom,padding-left,padding-right on td

  • Add support for valign attribute on td

  • Add support for color in more CSS formats for background-color, color, border-color, for example : <span style='color: white;background-color: hsl(120, 100%, 50%); '>color output</span> will now work.

  • Make it possible to use text-align inside td

3.11.6

Add support for :

  • vertical-align style on td
  • background-color style on tr
  • border-color on td

3.11.5

Make it possible to customize pStyle for list items, for example :

const ulpStyles = ["ListBullet", "ListBullet2", "ListBullet3"];
const htmlOptions = {
    elementCustomizer({ name, listLevel }) {
        if (name === "ul") {
            return {
                pStyle: ulpStyles[listLevel],
                useNumPr: false,
            };
        }
    },
};

listLevel will be 0, 1, 2 depending on the nested level of the item in the HTML.

3.11.4

Do not apply elementCustomizer on implicit paragraphs.

For example, if you had in your html :

<table>
    <tr>
        <td>Lorem</td>
    </tr>
</table>

and wrote :

const htmlOptions = {
    // ...,
    elementCustomizer(element) {
        if (element.matches("td")) {
            return {
                pStyle: "TextBody",
            };
        }
        if (element.matches("p")) {
            return {
                pStyle: "Heading",
            };
        }
    },
};

Then, before this version, the text "Lorem" would use the "Heading" style.

In this new version the implicit paragraph <p>Lorem</p> would not trigger a call to elementCustomizer at all, thus using "TextBody", which is the correct style to apply !

3.11.3

Make it possible to style implicit paragraphs in td by setting a pStyle on the td element from elementCustomizer.

  • Fix bug of pStyle not kept in certain cases.

3.11.2

  • Add support to set td width with style in px

The style property takes precendence over the style attribute, for example :

<td width="100" style="width: 400px" align="center">John</td>

will resolve to a width of 400px.

3.11.1

Add ignoreCssErrors to ignore CSS parse errors.

3.11.0

  • Add new selector API that makes it possible to style elements with CSS like selectors , for example :

    const htmlOptions = {
        // ...,
        elementCustomizer(element) {
            if (
                element.matches(
                    "th h3.p1, tr>th>h3.p3, tr>h3.nomatch"
                )
            ) {
                return {
                    htmlStyle: "background-color: #ff0000;",
                };
            }
        },
    };
    
  • Add way to remove all table borders by specifying :

    For example

    <table style="border: none;">
        <tr>
            <td>Hello</td>
        </tr>
    </table>
    
  • Bugfix add possibility to style <a> element (link)

3.10.5

  • Update browser build to use XMLSerializer instead of xmldom

  • Use requiredAPIVersion

3.10.4

  • Fix browser build failing Nodes of type '#document' may not be inserted inside nodes of type ...

3.10.3

  • Fix browser build "TypeError: Argument 1 of XMLSerializer.serializeToString does not implement interface Node."

3.10.2

  • Support elementCustomizer even when having deeply nested paragraphs, for example with <div><p>Hello</p></div>

3.10.1

Add support for :

  • align attribute on table cell

  • enhance colspan support when widths are not all fixed

  • table width as percentage

3.10.0

Add support for :

  • Background-color in tables (in css format)

  • Better use width in tables (which now generates colgrid and gridspan)

  • Add support for align="center"

  • Background-color in span (in css format)

3.9.2

  • Add {part} argument to elementCustomizer

3.9.1

  • Move docxtemplater from devDependencies to dependencies

Explanation : On some versions of npm (notably 5.8.0), when having a package containing docxtemplater-html-module, the installation will generate a tree of node_modules that puts the module on a level where it has no access to docxtemplater. By explicitly asking it as a dependency, this issue is avoided.

3.9.0

  • Drop paragraphCustomizer api (which was added in 3.8.4), for a more generic elementCustomizer API.

3.8.4

Make it possible to customize docxstyles depending on classnames.

3.8.3

  • Make module compatible with docxtemplater version 3.5 and below.

Explanation : Recently, the scopemananger API (internal API) has changed, this new version of the html module makes the module work with both versions newer than 3.6 and older than 3.6 of docxtemplater.

3.8.2

Add support for svg tag (needs the image module too) (this format is only readable on newer Word version : Microsoft Word, PowerPoint, Outlook, and Excel 2016 on Windows, Mac, Android and Windows Mobile).

3.8.1

Add meta context argument to custom parser with information about the tag for each types of tags

3.8.0

  • Use default paragraph style instead of textbody for paragraphs

3.7.1

  • Fix issue with style that were overriden if the styles had the same name

3.7.0

  • Add styles only when using an HTML tag

3.6.6

  • Add way to change the size of paddingLeft with sizeConverters

3.6.5

  • Add support for padding-left : <p style="padding-left:15px">Hello</span>

3.6.4

  • Add support for font-size : <span style="font-size: 15px">Hello</span>

3.6.3

  • Add support for more image types in img tag : GIF, JPEG, BMP, PNG work now

3.6.2

  • Add support for blockquote tags

3.6.1

  • Correctly handle &#58 in style attributes (parsed as :).
  • Fail with clear error message if style attribute cannot be parsed

3.6.0

Add support for <img> if using imagemodule.

3.5.10

Throw explicit error when using pptx instead of docx

3.5.9

Fix bug introduced in 3.5.5 : When using <li> elements, all child tags are now correctly rendered (before, only the first child was rendered).

3.5.8

When using <a>Link</a> without href, set the Target to "" instead of "undefined"

3.5.7

Handle multiple occurences of noBreakHyphen in same tag

3.5.6

Handle noBreakHyphen

3.5.5

Improve whitespace support.

3.5.4

  • Fix rendering of space between tags for inline tags too {~html}, for example :
<p><b>Foo</b> <u>Bar</u></p>

will now correctly render "Foo Bar" instead of "Foobar"

3.5.3

  • Fix rendering of space between tags for block tags, eg {~~html}, for example :
<p><b>Foo</b> <u>Bar</u></p>

will now correctly render "Foo Bar" instead of "Foobar"

3.5.2

  • Add possibility to customize styles for nested <ul>,

eg :

this.options.styleTransformer = function (tags) {
    tags.ul.data.pStyle = [
        "ListBullet",
        "ListBullet2",
        "ListBullet3",
    ];
    tags.ul.data.useNumPr = false;
    return tags;
};

This will set the "ListBullet" for level 0 of <ul>, "ListBullet2" for level 1 and so on.

3.5.1

  • Add possibility to customize styles for BulletList with styleTransformer

3.5.0

  • Add option styleTransformer to customize styles.
  • Do not set <w:spacing w:before="0" w:after="0"/> for each paragraph, but use the one that is set in the paragraph containing the {~~blockTag}, if present.

This release needs version 3.1.11 of docxtemplater.

3.4.5

Bugfix issue with styles of TextBody or BodyText being wrongly changed.

3.4.4

Bugfix issue with bullet lists no more appearing

3.4.3

  • Fix issue with duplicate list content when using <ul><li><em>Test</em> after</li></ul>
  • All html escapes are now currently handled, including &#xA0, &and;, and all html handled escapes

3.4.2

  • Add support for text-align:center and text-align:right
  • Add correct styles for h5 and h6

3.4.1

  • Handle escapes such as &quot; &amp; &#x27; &gt; &lt;

3.4.0

  • Add possibility to ignore unknown tags with an option
  • Add support for <sub> and <sup>

3.3.3

Add support for style="text-decoration: underline"

3.3.2

Handle nested ul/li:

<ul>
    <li>Foo</li>
    <li>
        <ul>
            <li>Nested 1</li>
            <li>Nested 2</li>
        </ul>
    </li>
</ul>

3.3.1

Multiple fixes for tables :

Add support for tables that have :

  • no <tbody>, and directly <tr>
  • <thead> or <tfoot>
  • <th> instead of <td>

Also, allow td to be empty, for example :

<table><tr><td>First</td><td></td><td>Third</td></tr></table>

Fixes links containing dom children to be shown as "undefined", for example :

<a href="https://ddg.gg">Foobar <span>Foo</span></a>

3.3.0

Make it possible to add paragraphs nested inside paragraphs, for example :

```

Paragraph1

Paragraph2

Paragraph3

```

Fix issues with &amp; and others not getting decoded

3.2.1

Add support for background-color on p element. It uses the fill property of word, which sets the background-color for a full paragraph.

3.2.0

Add auto wrapping of inline elements in block-elements, so that <span>Foobar</span> is also valid in {~~blockElement}. Also, this makes it possible to use <td>Foobar</td> (the wrapping of the <p> is done for you).

3.1.4

Add support for inline style background-color:blue

3.1.3

Fixes following error in version 3.1.2 : "Cannot find module '../static/styles.json'"

3.1.2 [WIPED](Please use 3.1.3)

Bugfix when using multiple <ol>, the numbering is reset correctly for each <ol>

3.1.1

Bugfixes when using elements other than <p> inside a <td> (eg now <ul> works)

3.1.0

Bugfixes when using :

  • table inside table
  • multiple lists (<ul>, <li>)
  • multiple links to same Target

3.0.12

Fix bug when using tags inside lists, for example, <ul><li><i>Foo</i></li></ul> now works as expected

3.0.11

Update rendering of <ol> to use the default symbol.

3.0.10

Do not change style of Title, Heading1 - Heading6 of current document

3.0.9

Add support for <input type="checkbox"> and <input type="checkbox" checked>

3.0.8

Fix right borders for tables

3.0.7

Fix corrupted documents with some templates

3.0.6

Add support for <a href="URL">LinkText</a>

3.0.5

Add support for inline style color:#ef0000

3.0.4

Keep word-run style for inline replacement. For example if, the text that the {~html} tag is written in is red, it will also be the base style for the generated elements of the html tag.

3.0.3

Keep existing style. For example, if the html is : <p>Foobar</p>, the text should be styled the same as the rest of the document.

3.0.2

Add support for ol,ul and li tags

3.0.1

Update demo and readme

3.0.0

Initial release

Talk with sales Contact us