const wrapper = require("../module-wrapper");
const { getScopeCompilationError } = require("../errors");
const { utf8ToWord, hasCorruptCharacters } = require("../doc-utils");
const { getCorruptCharactersException } = require("../errors");
const ftprefix = {
docx: "w",
pptx: "a",
};
class Render {
constructor() {
this.name = "Render";
this.recordRun = false;
this.recordedRun = [];
}
set(obj) {
if (obj.compiled) {
this.compiled = obj.compiled;
}
if (obj.data != null) {
this.data = obj.data;
}
}
getRenderedMap(mapper) {
return Object.keys(this.compiled).reduce((mapper, from) => {
mapper[from] = { from, data: this.data };
return mapper;
}, mapper);
}
optionsTransformer(options, docxtemplater) {
this.parser = docxtemplater.parser;
this.fileType = docxtemplater.fileType;
return options;
}
postparse(postparsed, options) {
const errors = [];
postparsed.forEach((p) => {
if (p.type === "placeholder") {
const tag = p.value;
try {
options.cachedParsers[p.lIndex] = this.parser(tag, { tag: p });
} catch (rootError) {
errors.push(
getScopeCompilationError({ tag, rootError, offset: p.offset })
);
}
}
});
return { postparsed, errors };
}
recordRuns(part) {
if (part.tag === `${ftprefix[this.fileType]}:r`) {
this.recordRun = false;
this.recordedRun = [];
} else if (part.tag === `${ftprefix[this.fileType]}:rPr`) {
if (part.position === "start") {
this.recordRun = true;
this.recordedRun = [part.value];
}
if (part.position === "end") {
this.recordedRun.push(part.value);
this.recordRun = false;
}
} else if (this.recordRun) {
this.recordedRun.push(part.value);
}
}
render(part, { scopeManager, linebreaks, nullGetter }) {
if (linebreaks) {
this.recordRuns(part);
}
if (part.type !== "placeholder" || part.module) {
return;
}
let value;
try {
value = scopeManager.getValue(part.value, { part });
} catch (e) {
return { errors: [e] };
}
if (value == null) {
value = nullGetter(part);
}
if (hasCorruptCharacters(value)) {
return {
errors: [
getCorruptCharactersException({
tag: part.value,
value,
offset: part.offset,
}),
],
};
}
if (typeof value !== "string") {
value = value.toString();
}
if (linebreaks) {
return this.renderLineBreaks(value);
}
return { value: utf8ToWord(value) };
}
renderLineBreaks(value) {
const p = ftprefix[this.fileType];
const br = this.fileType === "docx" ? "" : "";
const lines = value.split("\n");
const runprops = this.recordedRun.join("");
return {
value: lines
.map(function (line) {
return utf8ToWord(line);
})
.join(
`${p}:t>${p}:r>${br}<${p}:r>${runprops}<${p}:t${
this.fileType === "docx" ? ' xml:space="preserve"' : ""
}>`
),
};
}
}
module.exports = () => wrapper(new Render());