Demo Readme Changelog Buy html module Releases RSS

Summary (version 3.7.0)

This module exposes a tag to include html. The HTML is converted to Native Open XML by the module. This allows you to add a formatted field entered by the user

This module is available as part of the docxtemplater PRO plan.


Html Module

This module exposes a tag to include html. The HTML is converted to Native Open XML by the module. This allows you to add a formatted field entered by the user, or add more complex data by writing simple HTML (Open XML is much more complex to work with then HTML).

The HTML module currently supports:

  • <br> tags
  • <p> tags
  • <h1-6> tags, <h1> translates to Title, <h2> translates to Header1, <h3> translates to Header2, because there is no concept of title in the body of HTML
  • <p> tags
  • <b> tags
  • <i> tags
  • <u> tags
  • <ul> tags
  • <ol> tags
  • <li> tags
  • <span> tags
  • <small> tags
  • <s> tags
  • <strong> tags
  • <em> tags
  • <code> tags
  • <table>, <tr>, <td>, <tbody>, <thead>, <tfoot>, <th> tags
  • <a href="URL">Linktext</a> tags
  • style="color: #bbbbbb" property
  • style="font-size: 30px" property
  • <input type="checkbox"> and <input type="checkbox" checked>
  • style="background-color: blue" property (for black, blue, cyan, darkBlue, darkGray, darkRed, green, lightGray, magenta, red, white, yellow). This limitation is of microsoft word itself.
  • style="padding-left: 30px"
  • <sub> and <sup>
  • <img> only if including the imageModule too, by using base64 src

Important : This module only supports docx, not pptx, for multiple reasons


You will need docxtemplater v3: npm install docxtemplater

Install this module with npm install --save "$url"


Your docx should contain the text: {~html}. You can find a working sample at ./sample.js

  • {~html} is used for inline HTML
  • {~~html} is used for block HTML

To be clear :

  • The {~inline} tag is used when you want to replace part of a paragraph. For example you can write :
My product is {~blueText} and costs ...

The tag is inline, there is some other text in the paragraph. In this case, you can only use inline HTML elements (<span> , <b> , <i>, <u>)

  • The {~~block} tag is used when you want to replace a whole paragraph, and you want to insert multiple elements

The tag is block, there is no other text in the paragraph. In this case, you can only use block HTML elements (<p>, <ul>, <table>, <ol>, <h1>)

Also, in tr elements, we can have lists, …, so you have to surround your tags with <p>.

This code will throw an error (Tag 'em' is of type inline, it is not supported as the root of a block-scoped tag) :

<td style="width:33.333333333333336%;">

And this code will work :

<td style="width:33.333333333333336%;">


It is possible to set options to the htmlModule.

Option descriptions :

  • ignoreUnknownTags [default=false]: If this option is set to true, and the module finds a tag that it doesn't handle yet, it will not fail but instead make as if the tag was of type <span>
  • styleTransformer makes it possible to rewrite the styles that are used by the HTML module, for example :
  • sizeConverters makes it possible to change the ratio between px and dxa for different tags.

For example, this will 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;
    return tags;
const module = new HTMLModule({
    styleTransformer: styleTransformer,

For example to ignore all unknown tags:

const module = new HTMLModule({
    ignoreUnknownTags: true,

To change the size of "padding-left":

const module = new HTMLModule({
    sizeConverters: {
        paddingLeft: 20,

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

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.

Lets take a simple example :

pptx Paragraph and table in PPTX

docx Paragraph and table in DOCX

Here is how these documents map to XML :

For pptx

        <a:off x="2376000" y="936000"/>
        <a:ext cx="3384000" cy="346320"/>
    <a:t>My paragraph</a:t>
        <a:off x="3579480" y="2726640"/>
        <a:ext cx="5075280" cy="1439280"/>

For docx

    <w:t>My paragraph</w:t>

As you can see, in docx, the elements come one after the other, without any "placement" information, in pptx however, these are placed absolutely with the <a:xfrm> and <p:xfrm> tags.

In standard HTML, you would write this example with :

<p>My paragraph</p>

which maps very well to docx, but not to 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 htmlModule = new HTMLModule({
    img: {
        Module: ImageModule,
        // By default getSize returns the width and height attributes if both are present, or 200x200px as a default value.
        getSize: function(data) {
            // The html element, for example, if the data is :
            // '<img height="20" src="...">'
            // you will have data.element.attribs.width = '20'
            // The arraybuffer of your image
            // (you could use to calculate the size)
            // You return an array in pixel (here we have width 50px and height 100px)
            return [50, 100];

The <img> tag only supports base64 src, so for example, you can do :

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

Note that HTTP URLs in src will not work, since docxtemplater doesn't know how to load those files.

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);
    return sizeOf(buffer);


You can build the es6 into js by running npm run compile


You can test the module with npm test



  • Add styles only when using an HTML tag


  • Add way to change the size of paddingLeft with sizeConverters


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


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


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


  • Add support for blockquote tags


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


Add support for <img> if using imagemodule.


Throw explicit error when using pptx instead of docx


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).


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


Handle multiple occurences of noBreakHyphen in same tag


Handle noBreakHyphen


Improve whitespace support.


  • 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"


  • 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"


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

eg :

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

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


  • Add possibility to customize styles for BulletList with styleTransformer


  • 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.


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


Bugfix issue with bullet lists no more appearing


  • 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


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


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


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


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


Handle nested ul/li:

            <li>Nested 1</li>
            <li>Nested 2</li>


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 :


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

<a href="">Foobar <span>Foo</span></a>


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


Fix issues with &amp; and others not getting decoded


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


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

is done for you).


Add support for inline style background-color:blue


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>


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


Bugfixes when using :

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


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


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


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


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


Fix right borders for tables


Fix corrupted documents with some templates


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


Add support for inline style color:#ef0000


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.


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.


Add support for ol,ul and li tags


Update demo and readme


Initial release

Edgar Hipp

I'm the creator of docxtemplater. I work on making docxtemplater great since 2013.