You are currently offline, serving cached version

Usage

It is possible to retrieve data from any data source (synchronously or asynchronously).

For example :

  • from base64 data
  • from the filesystem
  • from a url like : https://docxtemplater.com/xt-pro-white.png
  • from an Amazon S3 stored image

The tag should be prefixed by % to be parsed as an image. So for example, you could use :{%image} which will take the data from the image key, or {%secondImage} to take the data from the secondImage key.

Usage (nodejs)

The below example is in nodejs, to read the image data from the filesystem :

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

const imageOpts = {
    centered: false,
    getImage: function (tagValue, tagName) {
        return fs.readFileSync(tagValue);
    },
    getSize: function (img, tagValue, tagName) {
        // it also is possible to return a size in centimeters, like this : return [ "2cm", "3cm" ];
        return [150, 150];
    },
};

const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
});
doc.render({ image: "examples/image.png" });

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

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

Usage (browser)

In the browser, this shows how to get the image from a URL :

<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/imagemodule.js"></script>
    <script>
        docxType =
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        PizZipUtils.getBinaryContent(
            "examples/image-example.docx",
            function (error, content) {
                if (error) {
                    console.error(error);
                    return;
                }
                const imageOpts = {
                    centered: false,
                    getImage: function (tagValue, tagName) {
                        return new Promise(function (
                            resolve,
                            reject
                        ) {
                            PizZipUtils.getBinaryContent(
                                tagValue,
                                function (error, content) {
                                    if (error) {
                                        return reject(error);
                                    }
                                    return resolve(content);
                                }
                            );
                        });
                    },
                    getSize: function (img, tagValue, tagName) {
                        // FOR FIXED SIZE IMAGE :
                        return [150, 150];

                        // FOR IMAGE COMING FROM A URL (IF TAGVALUE IS AN ADDRESS) :
                        // To use this feature, you have to be using docxtemplater async
                        // (if you are calling render(), you are not using async).
                        return new Promise(function (
                            resolve,
                            reject
                        ) {
                            const image = new Image();
                            image.src = url;
                            image.onload = function () {
                                resolve([
                                    image.width,
                                    image.height,
                                ]);
                            };
                            image.onerror = function (e) {
                                console.log(
                                    "img, tagValue, tagName : ",
                                    img,
                                    tagValue,
                                    tagName
                                );
                                alert(
                                    "An error occured while loading " +
                                        tagValue
                                );
                                reject(e);
                            };
                        });
                    },
                };

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

                doc.renderAsync({
                    image: "examples/image.png",
                }).then(function () {
                    const out = doc.getZip().generate({
                        type: "blob",
                        mimeType: docxType,
                    });
                    saveAs(out, "generated.docx");
                });
            }
        );
    </script>
</html>

After installing the module, you can use a working demo by running node sample.js.

To understand what img, tagValue, tagName mean, lets take an example :

If your template is :

{%myImage}

and your data:

{
    "myImage": "sampleImage.png"
}
  • tagValue will be equal to "sampleImage.png"
  • tagName will be equal to "myImage"
  • img will be what ever the getImage function returned

One of the most useful cases of this is to set the images to be the size of that image.

For this, you will need to install the npm package 'image-size' then, write:

const sizeOf = require("image-size");
const imageOpts = {
    centered: false,
    getImage: function (tagValue) {
        return fs.readFileSync(tagValue, "binary");
    },
    getSize: function (img) {
        const sizeObj = sizeOf(img);
        console.log(sizeObj);
        return [sizeObj.width, sizeObj.height];
    },
};
const doc = new Docxtemplater(zip, {
    modules: new ImageModule(imageOpts),
});

Replace an existing image

It is possible to replace an existing image in the document instead of adding a new image. This is possible since version 3.9.0 of the image module.

To replace an image, you can write {%image1} in the alt-text attribute, or the name of the image, and the image will be replaced. Note that the width will be updated depending on the getSize function.

To replace images in header or replace them in footers, you can use the "alt-text" property.

Inside Microsoft Word on Windows, you can update the alt-text by right clicking on the image :

Alt text demo1

Alt text demo2

It is possible to keep the size of the existing image by using the following function for getSize :

const sizeOf = require("image-size");

const imageOpts = {
    getImage: function(tagValue) {
        // return usual value, using fs or any other method
    },
    getSize : function (image, data, tagValue, options) {
        const part = options.part;
        if (part.module === "open-xml-templating/docxtemplater-replace-image-module") {
            return [
                part.width,
                part.height
            ]
        }

        // return usual value, using image-size or other method.
        const buffer = Buffer.from(image, "binary");
        const sizeObj = sizeOf(buffer);
        return [sizeObj.width, sizeObj.height];
    };
}
const doc = new Docxtemplater(zip, {modules: [new ImageModule(imageOpts)]});

Base64 include

You can use base64 images with the following code

const base64Regex =
    /^data:image\/(png|jpg|svg|svg\+xml);base64,/;
function base64Parser(dataURL) {
    if (
        typeof dataURL !== "string" ||
        !base64Regex.test(dataURL)
    ) {
        return false;
    }
    const stringBase64 = dataURL.replace(base64Regex, "");

    // For nodejs
    if (typeof Buffer !== "undefined" && Buffer.from) {
        return Buffer.from(stringBase64, "base64");
    }

    // For browsers :
    const binaryString = window.atob(stringBase64);
    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 imageOpts = {
    getImage(tag) {
        return base64Parser(tag);
    },
    getSize() {
        return [100, 100];
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
});

Fetch image from url

It is possible to get images asynchronously by returning a Promise in the getImage function and use the docxtemplater async api.

Here is an example in node that allows you to retrieve values from an URL and use a fixed width, and keep the aspect ratio.

const fs = require("fs");
const Docxtemplater = require("docxtemplater");
const https = require("https");
const http = require("http");
const Stream = require("stream").Transform;
const ImageModule = require("docxtemplater-image-module");
const PizZip = require("pizzip");

const content = fs.readFileSync("demo_template.docx");

const data = { image: "https://docxtemplater.com/xt-pro.png" };

const imageOpts = {
    getImage: function (tagValue, tagName) {
        console.log(tagValue, tagName);
        const base64Value = base64Parser(tagValue);
        if (base64Value) {
            return base64Value;
        }
        // tagValue is "https://docxtemplater.com/xt-pro-white.png"
        // tagName is "image"
        return new Promise(function (resolve, reject) {
            getHttpData(tagValue, function (err, data) {
                if (err) {
                    return reject(err);
                }
                resolve(data);
            });
        });
    },
    getSize: function (img, tagValue, tagName) {
        console.log(tagValue, tagName);
        // img is the value that was returned by getImage
        // This is to force the width to 600px, but keep the same aspect ratio
        const sizeOf = require("image-size");
        const sizeObj = sizeOf(img);
        console.log(sizeObj);
        const forceWidth = 600;
        const ratio = forceWidth / sizeObj.width;
        return [
            forceWidth,
            // calculate height taking into account aspect ratio
            Math.round(sizeObj.height * ratio),
        ];
    },
};

const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
});

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

        fs.writeFileSync("test.docx", buffer);
        console.log("rendered");
    })
    .catch(function (error) {
        console.log("An error occured", error);
    });

function getHttpData(url, callback) {
    (url.substr(0, 5) === "https" ? https : http)
        .request(url, function (response) {
            if (response.statusCode !== 200) {
                return callback(
                    new Error(
                        `Request to ${url} failed, status code: ${response.statusCode}`
                    )
                );
            }

            const data = new Stream();
            response.on("data", function (chunk) {
                data.push(chunk);
            });
            response.on("end", function () {
                callback(null, data.read());
            });
            response.on("error", function (e) {
                callback(e);
            });
        })
        .end();
}

Pixel to Inch conversions

Pixels and Inches are two very different units, conceptually.

Pixels represent not a physical length, but a logical length. Screens can be the same physical size (13 inches for example) and have different amount of pixels (640px or 1920px for example).

The images in the image-module are specified in pixels, and Word is a format that is made for print, Word stores all dimensions in inches (or fractions of inches). The unit used for images is usually "DXA", where 1 inch is equal to 1440 DXAS. This unit is also called a "twip".

To translate pixels to inches, the image-module uses the concept of "dpi", or "dots per inches", which is a way to convert the image sizes returned by the "getSize" function which are in pixel unit, and convert them to inches.

This is done with the formula :

sizeInInch = sizeInPixel / dpi

By default, the dpi is set to 96, which means 96px will be translated to one inch.

You can change the dpi by setting it in the options, like this :

const imageOpts = {
    getImage: function (tagValue) {
        // ...
    },
    getSize: function (img) {
        // ...
    },
    dpi: 120,
};

const doc = new Docxtemplater(zip, {
    modules: new ImageModule(imageOpts),
});

To have the image module scale the images in exactly the same way as Microsoft word does, you should use a dpi of 224.23.

Centering images

You can center the images using opts.centered = true or by using {%%image} instead of {%image} in your documents

Avoid images bigger than their container

If you include some images inside tables, it is possible that you get some images that are not shown completely because they are bigger than their container.

To fix this issue, you can do the following to never overflow the containerWidth and keep the aspect ratio

const sizeOf = require("image-size");
const imageOpts = {
    // getImage: as usual
    getSize: function (buffer, value, tagName, context) {
        const sizeObj = sizeOf(img);
        const maxWidth = context.part.containerWidth;
        const maxHeight =
            context.part.containerHeight ||
            context.part.containerWidth;

        const widthRatio = sizeObj.width / maxWidth;
        const heightRatio = sizeObj.height / maxHeight;
        if (widthRatio < 1 && heightRatio < 1) {
            /*
             * Do not scale up images that are
             * smaller than maxWidth,maxHeight
             */
            return [sizeObj.width, sizeObj.height];
        }
        let finalWidth, finalHeight;
        if (widthRatio > heightRatio) {
            /*
             * Width will be equal to maxWidth
             * because width is the most "limiting"
             */
            finalWidth = maxWidth;
            finalHeight = sizeObj.height / widthRatio;
        } else {
            /*
             * Height will be equal to maxHeight
             * because height is the most "limiting"
             */
            finalHeight = maxHeight;
            finalWidth = sizeObj.width / heightRatio;
        }

        return [Math.round(finalWidth), Math.round(finalHeight)];
    },
};

const doc = new Docxtemplater(zip, {
    modules: new ImageModule(imageOpts),
});

Size and path based on placeholder

You can customize the image loader using the template's placeholder name.

const imageOpts = {
    getImage: function (tagValue, tagName) {
        if (tagName === "logo")
            return fs.readFileSync(
                __dirname + "/logos/" + tagValue
            );

        return fs.readFileSync(
            __dirname + "/images/" + tagValue
        );
    },
};

The same thing can be used to customize image size.

const imageOpts = {
    getSize: function (img, tagValue, tagName) {
        if (tagName === "logo") return [100, 100];

        return [300, 300];
    },
};

Size with angular-parser

You can also use angular expressions to set image sizes :

In your template, write :

(This will force the aspect ratio to 2/1)

{%image | size:200:100}

or, to keep the aspect ratio by specifying a max size

{%image | maxSize:200:100}

First argument is the width, second argument is the height.

In your code, you would write the following :

const expressions = require("angular-expressions");
expressions.filters.size = function (input, width, height) {
    return {
        data: input,
        size: [width, height],
    };
};
// This one sets a max size, allowing to keep the aspect ratio of the image, but ensuring that the width and height do not exceed the limits specified
expressions.filters.maxSize = function (input, width, height) {
    return {
        data: input,
        maxSize: [width, height],
    };
};

function angularParser(tag) {
    tag = tag
        .replace(/^\.$/, "this")
        .replace(/(’|‘)/g, "'")
        .replace(/(“|”)/g, '"');
    const expr = expressions.compile(tag);
    return {
        get: function (scope, context) {
            let obj = {};
            const scopeList = context.scopeList;
            const num = context.num;
            for (let i = 0, len = num + 1; i < len; i++) {
                obj = assign(obj, scopeList[i]);
            }
            return expr(scope, obj);
        },
    };
}

const imageOpts = {
    getImage: function (tagValue) {
        if (tagValue.size && tagValue.data) {
            return base64Parser(tagValue.data);
        }
        if (tagValue.maxSize && tagValue.data) {
            return base64Parser(tagValue.data);
        }
        return base64Parser(tagValue);
    },
    getSize: function (img, tagValue) {
        if (tagValue.size && tagValue.data) {
            return tagValue.size;
        }
        if (!tagValue.maxSize) {
            return [150, 150];
        }

        const maxWidth = tagValue.maxSize[0];
        const maxHeight = tagValue.maxSize[1];
        const sizeOf = require("image-size");
        const sizeObj = sizeOf(img);

        const widthRatio = sizeObj.width / maxWidth;
        const heightRatio = sizeObj.height / maxHeight;
        if (widthRatio < 1 && heightRatio < 1) {
            /*
             * Do not scale up images that are
             * smaller than maxWidth,maxHeight
             */
            return [sizeObj.width, sizeOf.height];
        }
        let finalWidth, finalHeight;
        if (widthRatio > heightRatio) {
            /*
             * Width will be equal to maxWidth
             * because width is the most "limiting"
             */
            finalWidth = maxWidth;
            finalHeight = sizeObj.height / widthRatio;
        } else {
            /*
             * Height will be equal to maxHeight
             * because height is the most "limiting"
             */
            finalHeight = maxHeight;
            finalWidth = sizeObj.width / heightRatio;
        }

        return [Math.round(finalWidth), Math.round(finalHeight)];
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
    parser: angularParser,
});

Max width and max height

It is quite likely that you would want to limit the width and the height of your images, to do this, you could use the following code in your getSize function

const imageOpts = {
    getSize: function (img, tagValue, tagName) {
        // img is the value that was returned by getImage
        // This is to limit the width and height of the resulting image
        const maxWidth = 1000;
        const maxHeight = 800;
        const sizeOf = require("image-size");
        const sizeObj = sizeOf(img);
        const widthRatio = sizeObj.width / maxWidth;
        const heightRatio = sizeObj.height / maxHeight;
        if (widthRatio < 1 && heightRatio < 1) {
            /*
             * Do not scale up images that are
             * smaller than maxWidth,maxHeight
             */
            return [sizeObj.width, sizeObj.height];
        }
        let finalWidth, finalHeight;
        if (widthRatio > heightRatio) {
            /*
             * Width will be equal to maxWidth
             * because width is the most "limiting"
             */
            finalWidth = maxWidth;
            finalHeight = sizeObj.height / widthRatio;
        } else {
            /*
             * Height will be equal to maxHeight
             * because height is the most "limiting"
             */
            finalHeight = maxHeight;
            finalWidth = sizeObj.width / heightRatio;
        }
        return [Math.round(finalWidth), Math.round(finalHeight)];
    },
};

Retrieve image from <canvas>

It is possible to retrieve image from a canvas value, by customizing the getImage option.

const imageOpts = {
    getImage: function (tagValue, tagName) {
        const canvas = document.getElementById("myCanvas");
        const ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.arc(100, 75, 50, 0, 2 * Math.PI);
        ctx.stroke();
        return base64Parser(canvas.toDataURL());
    },
};

Note that you can change that function so that depending on the tagvalue, either the image is loaded from canvas or from a URL.

SVG support

SVGs can be added, but this format is only readable on newer Word version : Microsoft Word, PowerPoint, Outlook, and Excel on the Office 365 subscription.

See this article for details about this feature.

When SVG is not supported in your reader (libreoffice, google-docs, Word 2013), you will see the image "SVG unsupported" instead.

You can configure the image that is shown as a fallback if SVG is not supported, by defining the getSVGFallback method. You can use this method to convert the SVG to png so that all docx readers are able to see the SVG. In the below example, I use graphicsmagick to do the conversion : sudo apt-get install -y graphicsmagick

const imageOpts = {
    getSVGFallback: function (svgFile, sizePixel) {
        const result = require("child_process").spawnSync(
            "gm",
            [
                "convert",
                "SVG:-",
                "-resize",
                sizePixel.join("x"),
                "PNG:-",
            ],
            {
                input: new Buffer(svgFile),
            }
        );
        if (result.status !== 0) {
            /* eslint-disable-next-line no-console */
            console.error(
                JSON.stringify({
                    "result.stderr": result.stderr.toString(),
                })
            );
            throw new Error(
                "Error while executing graphicsmagick"
            );
        }
        return new Buffer(result.stdout);
    },
};

In the browser, you can use the following to transform the SVG's into PNG :

const imageOpts = {
    getSVGFallback: function (svgFile, sizePixel) {
        function arrayBufferToString(buffer) {
            let binary = "";
            const bytes = new Uint8Array(buffer);
            const len = bytes.byteLength;
            for (let i = 0; i < len; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            return binary;
        }

        return new Promise(function (resolve, reject) {
            function svgUrlToPng(svgUrl) {
                const svgImage = document.createElement("img");
                svgImage.style.position = "absolute";
                svgImage.style.top = "-9999px";
                document.body.appendChild(svgImage);
                const width = sizePixel[0];
                const height = sizePixel[1];
                svgImage.width = width;
                svgImage.height = height;
                svgImage.onload = function () {
                    const canvas =
                        document.createElement("canvas");
                    canvas.width = width;
                    canvas.height = height;
                    const canvasCtx = canvas.getContext("2d");
                    canvasCtx.drawImage(
                        svgImage,
                        0,
                        0,
                        width,
                        height
                    );
                    const imgData =
                        canvas.toDataURL("image/png");
                    resolve(base64Parser(imgData));
                };
                svgImage.onerror = function () {
                    reject(
                        new Error(
                            "Could not transform svg to png"
                        )
                    );
                };
                svgImage.src =
                    "data:image/svg+xml;utf8," + svgUrl;
            }
            svgUrlToPng(
                arrayBufferToString(svgFile).replace(
                    "<svg",
                    "<svg xmlns='http://www.w3.org/2000/svg'"
                )
            );
        });
    },
};

Adding Captions

For docx, it is possible to add captions with the following code :

const imageOpts = {
    getProps: function (img, tagValue, tagName) {
        /*
         * If you don't want to change the props
         * for a given tagValue, you should write :
         *
         * return null;
         */
        return {
            caption: {
                text: "My custom caption",
            },
        };
    },
    getImage: function (tagValue, tagName) {
        return fs.readFileSync(tagValue);
    },
    getSize: function (img, tagValue, tagName) {
        return [150, 150];
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
});

Changing Alignment

For docx, it is possible to change the alignment of a block image with the following code :

const imageOpts = {
    getProps: function (img, tagValue, tagName) {
        /*
         * If you don't want to change the props
         * for a given tagValue, you should write :
         *
         * return null;
         */
        return {
            align: "right",
        };
    },
    getImage: function (tagValue, tagName) {
        return fs.readFileSync(tagValue);
    },
    getSize: function (img, tagValue, tagName) {
        return [150, 150];
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
});

Changing name or alternative text

It is possible to customize the alternative text (the text shown on non-visual editors) using the getProps "alt" attribute. The "name" attribute is used to set the name of the image.

const imageOpts = {
    getProps: function (img, tagValue, tagName) {
        /*
         * If you don't want to change the props
         * for a given tagValue, you should write :
         *
         * return null;
         */
        return {
            name: "myimage.png",
            alt: "A cat looking playfully at a mouse.",
        };
    },
    getImage: function (tagValue, tagName) {
        return fs.readFileSync(tagValue);
    },
    getSize: function (img, tagValue, tagName) {
        return [150, 150];
    },
};
const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOpts)],
});

Centered Images should be placed in empty paragraphs

For the imagereplacer to work, the image tag: {%image} needs to be in its own paragraph (<w:p> tag in Word), so that means that you have to put a new line after and before the tag.

The following template will throw that error :

Foo
Hello {%image}
Bar

And the following will work

Foo
Hello
{%image}
Bar

Powerpoint notice

If you put images in a box that also contains some other text (content, title, or even whitespace , you will get an error :

To fix this error, you have to create a box that contains the {%...} and only this text, no other whitespace nor content.

For example, the following template will fail, because the shape containing the text {%image} also contains "Some content" and "Other content".

Fail

For example, the following template will succeed, because there are 3 different shapes, and the shape containing the {%image} tag contains no other text. Note that the width/height of the generated image will be the same as the one from the shape.

Succeed

Building in the browser

You can build a release for the browser with the following commands

npm install
npm run preversion

You will have build/imagemodule.js.

Images inside loop for Powerpoint files

If you try to add a loop with an image inside it, like this :

{#images}
{%src}
{/}

You will get an error message like this :

The image tag "src" should not be placed inside a loop, it should be the only text in a given shape

This is because a shape is positioned statically in the powerpoint format, and docxtemplater can not determine at which position the image would be compared to the surrounding text.

To include multiple images in a given slide, you need to have both the "Table" module and the "Slides" module.

Here's a demo of this feature

Take into account XResolution (from the jpeg metadata)

JPEG images often have metadata about the XResolution, which means they can have a specific dpi as metadata to the image. When copy-pasting a JPEG image into Microsoft Word, Microsoft Word will read the XResolution of the image and size the image accordingly.

With the image-module, usually the getSize function only will read the size of the image in pixels, but not the metadata.

If you need docxtemplater to behave like Microsoft Word, you could use an Exif extractor that will give you the XResolution. Here is an example of how you can do that (you need to use async rendering)

const ExifImage = require('exif').ExifImage;

function scaleWithExif(result, image) {
    return new Promise(function (resolve) {
        if (typeof image === "string") {
            image = Buffer.from(image, "binary");
        }
        try {
            new ExifImage({ image }, function (error, exifData) {
                if (error) {
                    resolve(result);
                    console.log("Error: " + error.message);
                } else {
                    const image = exifData.image;
                    const unit = image.ResolutionUnit;
                    const res = image.XResolution;
                    let scaleFactor;
                    if (unit === 1) {
                        scaleFactor = 1;
                    } else if (unit === 2) {
                        scaleFactor = 96 / res;
                    } else if (unit === 3) {
                        // dots per centimeter => dots per inch conversion
                        scaleFactor = 96 / res / 2.54;
                    }
                    console.log(JSON.stringify({ scaleFactor }));
                    console.log(JSON.stringify({ result }));
                    resolve([result[0] * scaleFactor, result[1] * scaleFactor]);
                }
            });
        } catch (error) {
            resolve(result);
        }
    });
}
const imageOpts = {
    getImage: function(tagValue) {
        // return usual value, using fs or any other method
    },
    getSize : function (image) {
        const sizeOf = require("image-size");
        const buffer = Buffer.from(image, "binary");
        const sizeObj = sizeOf(buffer);
        return scaleWithExif([sizeObj.width, sizeObj.height], image);
    };
}
const doc = new Docxtemplater(zip, {modules: [new ImageModule(imageOpts)]});
doc.renderAsync(data).then(function() {
    console.log('rendered');
});

CHANGELOG

3.14.3

Add support to be able to customize the name and alt text of replaced images using getProps.

3.14.2

Update to make module compatible with docxtemplater@3.30.0

Fixes following error :

TypeError: Cannot read properties of undefined (reading 'droppedTagsInsidePlaceholder')
    at parse (js/parser.js:170:46)

3.14.1

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

See : https://github.com/open-xml-templating/docxtemplater/issues/655

Now, images that are inside li elements will always be rendered as "inline-block" elements.

3.14.0

Add support for setting the name and alt attribute of the image programmatically using the getProps function.

3.13.6

Improve typescript typings (sizePixel, svgSize, getProps, getDxaWidth)

3.13.5

Add access to the "path" property of the image replacement module.

This allows to for example retrieve all placeholders and the linked images.

const InspectModule = require("docxtemplater/js/inspect-module");

const imageOptions = {
    /* ... */
};
const imageModule = new ImageModule(imageOptions);
const iModule = InspectModule();
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, {
    modules: [imageModule, iModule],
});
const tags = iModule.getStructuredTags();
// tags will be an array, you could filter for the module name :
// open-xml-templating/docxtemplater-replace-image-module
tags.forEach(function (part) {
    if (
        part.module ===
        "open-xml-templating/docxtemplater-replace-image-module"
    ) {
        console.log(
            "Tag",
            part.value,
            "which path is at ",
            part.path
        );
        const buffer = zip.file(part.path).asArrayBuffer();
        console.log(buffer.length);
    }
});

3.13.4

Bugfix on offset when replacing an image.

Previously, if the offset value was [0, 100] or [100, 0], the fact that one value was zero made the offset not apply at all.

Now, the offset works even when one value is zero.

3.13.3

On Powerpoint documents, when using the replace-image feature, allow to set an offset to move the image a certain amount of pixels. This allows for example to keep an image centered (see below example)

const doc = new Docxtemplater(zip, {
    modules: [
        new ImageModule({
            getImage: function () {
                // Usual getImage function
            },
            getSize: function () {
                return [200, 200];
            },
            getProps : function (a, b, c, d) {
                const { part, sizePixel } = d;
                if (
                    part.module ===
                        "open-xml-templating/docxtemplater-replace-image-module" &&
                    part.width &&
                    part.height
                ) {
                    return {
                        offset: [
                            part.width / 2 - sizePixel[0] / 2,
                            part.height / 2 - sizePixel[1] / 2,
                        ],
                    };
                }
            };
        }),
    ],
});

3.13.2

On Powerpoint documents, bugfix to correctly calculate size of images that are replaced using the "description" field

3.13.1

On Excel documents, bugfix to use correct width/height when replacing an image using the description field. Internally, we now convert the "twoCellAnchor" element into a "oneCellAnchor".

3.13.0

When used together with the xlsx module v3.9.0 or higher, Add possibility to replace images in Excel documents (using the description field).

3.12.5

Avoid removing hdphoto images from the template by mistake.

This was causing a corruption in the generated document

3.12.4

Bugfix slideMasters (and images in slideMasters) are now correctly templated

3.12.3

Avoid corrupting images that contain "instrText" and "INCLUDEPICTURE"

3.12.2

Add `to all images

3.12.1

Add support for returning containerWidth when having a <v:rect> element

3.12.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.11.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.10.0

Bugfix to correctly retrieve the width/height of the image when the image is in the header or footer when trying to replace an image.

Add support for other units for getSize (by default, the unit is in px when using integers).

You can now write :

const doc = new Docxtemplater(zip, {
    modules: [
        new ImageModule({
            getImage: function () {
                // Usual getImage function
            },
            getSize: function () {
                return ["1cm", "1in"];
            },
        }),
    ],
});

The list of allowed units is :

  • px => the default unit
  • in => an inch, which is 2.54cm
  • pt => a point, which is 1/72th of an inch
  • cm => a centimeter
  • mm => a millimeter
  • pc => a pica, which is 1/12th of a point
  • emu => english metric unit, which is 1/914400th of an inch, and is the unit used by Word to store sizes internally.

3.9.3

Throw TemplateError when having a centered image tag surrounded by text. This makes it possible for the Error-location module to show the error correctly.

Also, throw TemplateError when having other text in a text shape for Powerpoint document

3.9.2

Allow to replace an existing image using the "title" property, which is the property accessible using "alt-text"

This allows to replace images in headers/footers, which do not have the name property.

3.9.1

Bugfix issue when using together with the subtemplate module.

The error message : "ParseError: Attribute name redefined" could appear

3.9.0

Add support to change an existing image by using {%image} in the "alt-text" name of the image.

3.8.14

Call nullGetter in async mode when the value returned by the parser is falsy.

3.8.13

Update typings for getImage to allow Uint8Array, ArrayBuffer, …

3.8.12

Add typings for async mode (getSize can also return a Promise, and getImage can return a Promise) Add typings for options.part.containerWidth

3.8.11

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

3.8.10

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

3.8.9

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

3.8.8

Add typescript definitions for public API

3.8.7

Improve support for columns width, so that images 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, the containerWidth property will be correctly calculated.

Previously, the width would be in this case always splitted equally, so you have a wrong containerWidth in this case

3.8.6

Make width and height calculation work when a textbox is inside a v:shape, and the width and height are set in the style attribute

3.8.5

When having hyperlinks that contain "/media" in the target, the generated document would be corrupt. Now the document is not made corrupt anymore.

3.8.4

  • Add support for floating point numbers in getSize.
  • This version is compatible with version 3.25.4 of the HTML module
  • Add currentSection argument to getDxaWidth function

3.8.3

Update to retrieve containerHeight and containerWidth for pptx textboxes and pptx tables.

For docx tables, containerHeight cannot be retrieved because the height depends on the rendering of the fonts and the content of the table, so it cannot be retrieved.

3.8.2

Don't fail when placing the {%image} tag inside a table element.

3.8.1

Bugfix to make Image replacement work in async mode (you need access to both modules image and xlsx)

3.8.0

Add support for ImageModule together with XLSXModule to insert images with {%image} (you need access to both modules)

3.7.9

Do not fail when using the tag {%image} on "generic" shapes, eg those defined in the slideLayout

3.7.8

  • Do not console.log errors, as they are now properly handled by docxtemplater in async mode with loops (with docxtemplater 3.17.7)

  • Avoid corruption on XLSX file when it contains images (the images would be removed by the document)

3.7.7

Use SEQ Figure instead of SEQ Illustration for Captions

3.7.6

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

3.7.5

Better bugfix to remove unused images (works with other modules)

3.7.4

Bugfix No section found appeared :

  • when using document with tags inside properties (for Title, Subject, Keywords, …)
  • when using a document generated from onedrive (online office version)

3.7.3

Add getSVGFallback option to allow to convert the svg to png in JS

3.7.2

Bugfix when using image module together with pptx-subtemplate module, the images were removed

3.7.1

Bugfix to allow to have inline loop of inline images

Improve error message when putting block image inside inline loop

3.7.0

(docx) Add support to add captions with module.getProps function.

(docx) Add support for aligning block images to the left or the right with module.getProps function.

3.6.1

Fix issue "No section found" when having an image in a footer

3.6.0

Add possibility to retrieve the containerWidth to be able to use 100% of the containerWidth for example

Add possibility to change deviceWidth and getDxaWidth to change the dpi

3.5.4

  • Bugfix : do not remove images inside vfill
  • Remove usage of new Buffer

3.5.3

Expect to have error when using centered image in a paragraph which contains other text.

When using centered: true option, images containing %% now will show up as normal images (uncentered).

3.5.2

Add part.extPx and part.offsetPx to be able to know the size of the placeholder in pptx in pixel unit.

3.5.1

Fix corruption when having centered image inside table and return no img

3.5.0

Change the way this.opts.centered works.

Before, you would have to write : {%image} for inline images and {%%image} for centered images, and if you used the centered:true option, you would only be able to write centered images (with any of {%image} or {%%image}). Now when you specify opts.centered : true, the standard behavior is just swapped ({%image} for centered images and {%%image} for inline images).

However, in the future, opts.centered : true will be removed and this means that you should rather just change the prefix, like this :

function getImageModule() {
    const imageModule = new ImageModule(options);
    imageModule.prefix = {
        normal: "%%",
        centered: "%",
    };
    return imageModule;
}
const doc = new Docxtemplater(zip, {
    modules: [getImageModule()],
});

Also, this fixes a bug with SVG that were not shown when using "centered" images.

3.4.4

Bugfix for pptx. Before this release, if the document contained <a:extLst>, the error Images should be placed in new Text Boxes, that are not part of any slide layout was sometimes wrongfully thrown.

3.4.3

Bugfix in asyncmode, errors are now correctly thrown

3.4.2

Bugfix image module loops in async mode. Before this bugfix, images inside loops where sometimes always using the same image.

If you use the HTML module, you should update to 3.13.5 of the HTML module.

3.4.1

Bugfix SVG : async rendering should also work with base64 svgs

If you use the image module with the HTML module, please also update the HTML module to 3.14.4

3.4.0

Auto remove images that are no more needed when using slides module or when using a loop.

This makes the size of the generated docx smaller, and might make the rendering a little bit slower.

3.3.4

  • Update browser build to use XMLSerializer instead of xmldom

  • Use requiredAPIVersion

3.3.3

Make it possible to change prefix and normal prefix :

function getImageModule() {
    const imageModule = new ImageModule(options);
    imageModule.prefix = {
        normal: ":image ",
        centered: ":centered ",
    };
    return imageModule;
}
const doc = new Docxtemplater(zip, {
    modules: [getImageModule()],
});

3.3.2

  • Move docxtemplater from devDependencies to dependencies

Explanation : On some versions of npm (notably 5.8.0), when having a package containing docxtemplater-image-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.3.1

  • Make module compatible with docxtemplater version 3.5 and below.

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

3.3.0

Add SVG support (but this format is only readable on newer Word version : Microsoft Word, PowerPoint, Outlook, and Excel on the Office 365 subscription).

3.2.8

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

3.2.7

  • Fix issue "size is not defined"

3.2.6

  • Add clearer error message if getSize returns float or not an array of two integers

3.2.5

  • Add fallback to calling nullGetter if getValue returns falsey value

3.2.4

  • Fix "Maximum call stack size exceeeded" when using huge arraybuffers

3.2.3

  • Fix corruption error because of duplicate docPr. The shown error is usually : HRESULT 0x80004005 Location: Part: /word/document.xml, Line: 0, Column: 0

  • Add async support (by returning a Promise in the getImage function).

3.2.2

  • Fix error in browser "Buffer is not defined"

3.2.1

  • Fix regression in 3.2.0 : It should work with Buffer type

3.2.0

  • Throw error if using unsupported filetype (SVG)

  • Throw error if using image in a default box ("Images should be placed in new Text Boxes, that are not part of any slide layout")

3.1.6

Mark package as private in package.json

3.1.5

Fix corruption when reusing multiple times the docPrId

Reuse Target when possible

3.1.4

Do not add relationship for files docProps/app.xml and docProps/core.xml

3.1.3

Fix unit tests

3.1.2

Files are no longer corrupted when using the option "center"

3.1.1

The image module now throws an error if the given size is invalid.

3.1.0

  • Breaking : The image module no longer swallows error thrown by options.getImage and options.getSize. It is the implementors responsibility to not throw any errors, or the error will be passed. You can return a falsy value in getImage to not render an image at all.

3.0.2

  • Fix issue with PPTX : Before, you had to add to your options : {fileType: "pptx"} in the module options passed as argument in the constructor of the module. Now, the fileType is retrieved from the main docxtemplater.

3.0.1

  • Add support for PPTX.
  • Add centering of images with {%%image} syntax

3.0.0

  • This version is compatible with docxtemplater 3.0.