I want to make a local web page that accept users' pasted image and add to a docx file. To achieve this, I decided to use docxtemplater.js and docxtemplater-image-module-free module, but I can't get the 'getImage' callback function right. Any help is really appreciated! Here is the minimum example that repeat my current error.
include js
<script src="sources/vue.js"></script>
<script src="sources/elementui.js"></script>
<script src="sources/docxtemplater.js"></script>
<script src="sources/docxtemplater-image-module-free.js"></script>
<script src="sources/pizzip.js"></script>
<script src="sources/pizzip-utils.js"></script>
<script src="sources/FileSaver.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js" integrity="sha512-XMVd28F1oH/O71fzwBnV7HucLxVwtxf26XV8P4wPk26EDxuGZ91N8bsOttmnomcCD3CS5ZMRL50H0GgOHvegtg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js" integrity="sha512-3WaCYjK/lQuL0dVIRt1thLXr84Z/4Yppka6u40yEJT1QulYm9pCxguF6r8V84ndP5K03koI9hV1+zo/bUbgMtA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
html
<div style="text-align: center">
<input type="file" id="doc" />
</div>
<div>Copy an image from word<br />Press Ctrl+v to paste it here <br /></div>
<div id="editor"></div>
<button onclick="handleConfirm()">confirm</button>
javascript
var blob = null;
// create paste event listener
window.addEventListener("paste", pasteHandler);
// handle paste events
function pasteHandler(e) {
if (e.clipboardData) {
var items = e.clipboardData.items;
if (items) {
for (var i in items) {
// iterate through clipbord items
var item = items[i];
if (item.kind == "file") {
//image is a file
// create image source
blob = item.getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
var pastedImage = new Image();
pastedImage.src = source;
// add it in editor
document.getElementById("editor").innerHTML =
document.getElementById("editor").innerHTML +
pastedImage.outerHTML;
}
}
}
}
}
function handleConfirm() {
const reader = new FileReader();
const docs = document.getElementById("doc");
if (docs.files.length === 0) {
alert("No files selected");
}
reader.readAsBinaryString(docs.files.item(0));
var opts = {}
opts.centered = false;
opts.getImage = function (tagValue, tagName) {
return new Promise(function (resolve, reject) {
tagValue[1].arrayBuffer().then(r => {
const uint8array = new Uint8Array(r);
resolve(uint8array.buffer);
})
});
}
opts.getSize = function (img, tagValue, tagName) {
// FOR FIXED SIZE IMAGE :
return [150, 150];
}
var imageModule = new ImageModule(opts);
reader.onload = function (evt) {
const content = evt.target.result;
const zip = new PizZip(content);
const doc = new window.docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
modules: [imageModule]
});
doc.compile();
// Render the document (Replace {first_name} by John, {last_name} by Doe, ...)
doc.resolveData({
last_name:'a',
first_name: 'b',
phone: '123',
description: 'aa',
img: blob
}).then(function () {
console.log('ready');
doc.render();
const blob = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
// compression: DEFLATE adds a compression step.
// For a 50MB output document, expect 500ms additional CPU time
compression: "DEFLATE",
});
// Output the document using Data-URI
saveAs(blob, "output.docx");
})
}
}
And I got a error:
{"error": [{
"stack": "TypeError: Cannot set property namespaceURI of #<Element> which has only a getter\n at ImgManager.addExtensionRels (/dev/sources/docxtemplater-image-module-free.js:323:37)\n at ImgManager.addImageRels (/dev/sources/docxtemplater-image-module-free.js:350:22)\n at file:///E://dev/sources/docxtemplater-image-module-free.js:164:42\n at async Promise.all (index 2)\n at async Promise.all (index 4)",
"message": "Cannot set property namespaceURI of #<Element> which has only a getter",
"properties": {
"file": "word/document.xml"
}
}
] } It seems that the getImage callback function in opts of the ImageModule return a unsupported result (maybe I'm wrong), Can anyone help me to fix this error? Thanks a lot!
The
img
property of the object you pass toresolveData()
needs to contain a filename string and noblob
, like so:The image data is produced by the
getImage()
method. It has not to be passed in the data object.