175 lines
5.1 KiB
JavaScript
175 lines
5.1 KiB
JavaScript
const { wordToUtf8, convertSpaces, defaults } = require("./doc-utils");
|
|
const createScope = require("./scope-manager");
|
|
const xmlMatcher = require("./xml-matcher");
|
|
const { throwContentMustBeString } = require("./errors");
|
|
const Lexer = require("./lexer");
|
|
const Parser = require("./parser.js");
|
|
const render = require("./render.js");
|
|
const postrender = require("./postrender.js");
|
|
const resolve = require("./resolve.js");
|
|
const joinUncorrupt = require("./join-uncorrupt");
|
|
|
|
function getFullText(content, tagsXmlArray) {
|
|
const matcher = xmlMatcher(content, tagsXmlArray);
|
|
const result = matcher.matches.map(function (match) {
|
|
return match.array[2];
|
|
});
|
|
return wordToUtf8(convertSpaces(result.join("")));
|
|
}
|
|
|
|
module.exports = class XmlTemplater {
|
|
constructor(content, options) {
|
|
this.filePath = options.filePath;
|
|
this.cachedParsers = {};
|
|
this.modules = options.modules;
|
|
this.fileTypeConfig = options.fileTypeConfig;
|
|
this.contentType = options.contentType;
|
|
Object.keys(defaults).map(function (key) {
|
|
this[key] = options[key] != null ? options[key] : defaults[key];
|
|
}, this);
|
|
this.setModules({ inspect: { filePath: this.filePath } });
|
|
this.load(content);
|
|
}
|
|
load(content) {
|
|
if (typeof content !== "string") {
|
|
throwContentMustBeString(typeof content);
|
|
}
|
|
this.content = content;
|
|
}
|
|
setTags(tags) {
|
|
this.tags = tags != null ? tags : {};
|
|
this.scopeManager = createScope({
|
|
tags: this.tags,
|
|
parser: this.parser,
|
|
cachedParsers: this.cachedParsers,
|
|
});
|
|
return this;
|
|
}
|
|
resolveTags(tags) {
|
|
this.tags = tags != null ? tags : {};
|
|
this.scopeManager = createScope({
|
|
tags: this.tags,
|
|
parser: this.parser,
|
|
cachedParsers: this.cachedParsers,
|
|
});
|
|
const options = this.getOptions();
|
|
options.scopeManager = createScope(options);
|
|
options.resolve = resolve;
|
|
return resolve(options).then(({ resolved, errors }) => {
|
|
errors.forEach((error) => {
|
|
// error properties might not be defined if some foreign
|
|
// (unhandled error not throw by docxtemplater willingly) is
|
|
// thrown.
|
|
error.properties = error.properties || {};
|
|
error.properties.file = this.filePath;
|
|
});
|
|
if (errors.length !== 0) {
|
|
throw errors;
|
|
}
|
|
return Promise.all(resolved).then((resolved) => {
|
|
this.setModules({ inspect: { resolved } });
|
|
return (this.resolved = resolved);
|
|
});
|
|
});
|
|
}
|
|
getFullText() {
|
|
return getFullText(this.content, this.fileTypeConfig.tagsXmlTextArray);
|
|
}
|
|
setModules(obj) {
|
|
this.modules.forEach((module) => {
|
|
module.set(obj);
|
|
});
|
|
}
|
|
preparse() {
|
|
this.allErrors = [];
|
|
this.xmllexed = Lexer.xmlparse(this.content, {
|
|
text: this.fileTypeConfig.tagsXmlTextArray,
|
|
other: this.fileTypeConfig.tagsXmlLexedArray,
|
|
});
|
|
this.setModules({ inspect: { xmllexed: this.xmllexed } });
|
|
const { lexed, errors: lexerErrors } = Lexer.parse(
|
|
this.xmllexed,
|
|
this.delimiters
|
|
);
|
|
this.allErrors = this.allErrors.concat(lexerErrors);
|
|
this.lexed = lexed;
|
|
this.setModules({ inspect: { lexed: this.lexed } });
|
|
const options = this.getOptions();
|
|
Parser.preparse(this.lexed, this.modules, options);
|
|
}
|
|
parse() {
|
|
this.setModules({ inspect: { filePath: this.filePath } });
|
|
const options = this.getOptions();
|
|
this.parsed = Parser.parse(this.lexed, this.modules, options);
|
|
this.setModules({ inspect: { parsed: this.parsed } });
|
|
const { postparsed, errors: postparsedErrors } = Parser.postparse(
|
|
this.parsed,
|
|
this.modules,
|
|
options
|
|
);
|
|
this.postparsed = postparsed;
|
|
this.setModules({ inspect: { postparsed: this.postparsed } });
|
|
this.allErrors = this.allErrors.concat(postparsedErrors);
|
|
this.errorChecker(this.allErrors);
|
|
return this;
|
|
}
|
|
errorChecker(errors) {
|
|
if (errors.length) {
|
|
errors.forEach((error) => {
|
|
// error properties might not be defined if some foreign
|
|
// (unhandled error not thrown by docxtemplater willingly) is
|
|
// thrown.
|
|
error.properties = error.properties || {};
|
|
error.properties.file = this.filePath;
|
|
});
|
|
this.modules.forEach(function (module) {
|
|
errors = module.errorsTransformer(errors);
|
|
});
|
|
}
|
|
}
|
|
baseNullGetter(part, sm) {
|
|
const value = this.modules.reduce((value, module) => {
|
|
if (value != null) {
|
|
return value;
|
|
}
|
|
return module.nullGetter(part, sm, this);
|
|
}, null);
|
|
if (value != null) {
|
|
return value;
|
|
}
|
|
return this.nullGetter(part, sm);
|
|
}
|
|
getOptions() {
|
|
return {
|
|
compiled: this.postparsed,
|
|
cachedParsers: this.cachedParsers,
|
|
tags: this.tags,
|
|
modules: this.modules,
|
|
parser: this.parser,
|
|
contentType: this.contentType,
|
|
baseNullGetter: this.baseNullGetter.bind(this),
|
|
filePath: this.filePath,
|
|
fileTypeConfig: this.fileTypeConfig,
|
|
linebreaks: this.linebreaks,
|
|
};
|
|
}
|
|
render(to) {
|
|
this.filePath = to;
|
|
const options = this.getOptions();
|
|
options.resolved = this.resolved;
|
|
options.scopeManager = createScope(options);
|
|
options.render = render;
|
|
options.joinUncorrupt = joinUncorrupt;
|
|
const { errors, parts } = render(options);
|
|
this.allErrors = errors;
|
|
this.errorChecker(errors);
|
|
if (errors.length > 0) {
|
|
return this;
|
|
}
|
|
|
|
this.content = postrender(parts, options);
|
|
this.setModules({ inspect: { content: this.content } });
|
|
return this;
|
|
}
|
|
};
|