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; } };