const PizZip = require('pizzip'); const Docxtemplater = require('docxtemplater'); const fs = require('fs'); const path = require('path'); const _ = require("lodash"); // The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors). function replaceErrors(key, value) { if (value instanceof Error) { return Object.getOwnPropertyNames(value).reduce(function (error, key) { error[key] = value[key]; return error; }, {}); } return value; } function errorHandler(error) { console.log(JSON.stringify({ error: error }, replaceErrors)); if (error.properties && error.properties.errors instanceof Array) { const errorMessages = error.properties.errors.map(function (error) { return error.properties.explanation; }).join("\n"); console.log('errorMessages', errorMessages); // errorMessages is a humanly readable message looking like this : // 'The tag beginning with "foobar" is unopened' } throw error; } class InspectModule { constructor() { this.inspect = {}; } set(obj) { if (obj.inspect) { this.inspect = _.merge({}, this.inspect, obj.inspect); } } } const getTags = function (postParsed) { return postParsed.filter(function (part) { return part.type === "placeholder"; }).reduce(function (tags, part) { tags[part.value] = {}; if (part.subparsed) { tags[part.value] = getTags(part.subparsed); } return tags; }, {}); } module.exports = function (templateInfo, fileName) { return new Promise((resolve, reject) => { //check empty fields for (const key in templateInfo) { if (!templateInfo[key]) { throw ({ eCode: 406, eText: 'هیچ یک از فیلدها نباید خالی باشند' }) } } let content = fs.readFileSync(path.resolve(__dirname, `../template/${fileName}`), 'binary'); let zip = new PizZip(content); let doc; let inspectModule = new InspectModule(); try { doc = new Docxtemplater(zip, { modules: [inspectModule] }); } catch (error) { errorHandler(error); } let postParsed = inspectModule.inspect.postparsed; let placeholders = Object.keys(getTags(postParsed)) let templateInfoKeys = Object.keys(templateInfo) //compare template placeholders and received fields from client(templateInfo) for (let i = 0; i < placeholders.length; i++) { if (!templateInfoKeys.includes(placeholders[i])) { throw ({ eCode: 406, eText: 'اطلاعات وارد شده ناقص است' }) }; }; doc.setData(templateInfo); try { doc.render() } catch (error) { errorHandler(error); } let buf = doc.getZip().generate({ type: 'nodebuffer' }); fs.writeFileSync(path.resolve(__dirname, `../public/files/${templateInfo.firstName}-${templateInfo.lastName}-${fileName}`), buf); resolve(`http://localhost:3000/users/download/${templateInfo.firstName}-${templateInfo.lastName}-${fileName}`) .catch(err => { reject({ eCode: 500, eText: err }) }) }) }