Trying to setup angular parser, but is failing with compilation error.
Closed this issue · 8 comments
Environment
- Version of docxtemplater :3.46.0
- Used docxtemplater-modules : none
- angular-expressions: 1.2.1
- Runner : Node_js
How to reproduce my problem :
I'm following the angular-parser doc to setup the angular parser
With the following js file :
import Docxtemplater from "docxtemplater";
import angularParser from "docxtemplater/expressions";
try {
const templatePath = path.join(process.cwd(), "templates", tenant, type, template + ".docx");
const templateDoc = fs.readFileSync(templatePath);
const zip = new PizZip(templateDoc);
doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
parser: angularParser,
});
} catch (error) {
logError("error setting up Docxtemplater", { error: error, template: template, data: data, tenant: tenant });
return error;
}
I would expect it to :
setup the Docxtemplater with the angularParser
The error I'm getting is:
"error": [
{
"name": "ScopeParserError",
"message": "Scope parser compilation failed",
"stack": "Error: Scope parser compilation failed\n at new XTScopeParserError (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/errors.js:33:16)\n at getScopeCompilationError (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/errors.js:255:13)\n at /Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/modules/render.js:75:25\n at Array.forEach (<anonymous>)\n at Render.postparse (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/modules/render.js:67:18)\n at /Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/parser.js:179:24\n at Array.reduce (<anonymous>)\n at _postparse (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/parser.js:178:22)\n at Object.postparse (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/parser.js:196:19)\n at XmlTemplater.parse (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/xml-templater.js:147:38)",
"properties": {
"id": "scopeparser_compilation_failed",
"offset": 307,
"xtag": "1a7cc267-fc2a-41bf-bee5-5d7d83acec88",
"explanation": "The scope parser for the tag \"1a7cc267-fc2a-41bf-bee5-5d7d83acec88\" failed to compile",
"rootError": {
"stack": "Error: [$parse:syntax] Syntax Error: Token 'a7cc267' is an unexpected token at column 2 of the expression [1a7cc267-fc2a-41bf-bee5-5d7d83acec88] starting at [a7cc267-fc2a-41bf-bee5-5d7d83acec88].\nhttp://errors.angularjs.org/\"NG_VERSION_FULL\"/$parse/syntax?p0=a7cc267&p1=is%20an%20unexpected%20token&p2=2&p3=1a7cc267-fc2a-41bf-bee5-5d7d83acec88&p4=a7cc267-fc2a-41bf-bee5-5d7d83acec88\n at /Users/Shared/data/source/bpipartners.nl/communis/node_modules/angular-expressions/lib/parse.js:2151:10\n at AST.throwError (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/angular-expressions/lib/parse.js:2818:9)\n at AST.ast (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/angular-expressions/lib/parse.js:2500:9)\n at ASTCompiler.compile (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/angular-expressions/lib/parse.js:3070:29)\n at Parser.parse (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/angular-expressions/lib/parse.js:4205:27)\n at Object.compile (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/angular-expressions/lib/main.js:61:32)\n at parser (/Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/expressions.js:120:28)\n at Render.parser (/Users/Shared/data/source/bpipartners.nl/communis/dist/apps/sandbox/webpack:/libs/generators/src/word/generateWORD.ts:22:40)\n at /Users/Shared/data/source/bpipartners.nl/communis/node_modules/docxtemplater/js/modules/render.js:71:54\n at Array.forEach (<anonymous>)",
"message": "[$parse:syntax] Syntax Error: Token 'a7cc267' is an unexpected token at column 2 of the expression [1a7cc267-fc2a-41bf-bee5-5d7d83acec88] starting at [a7cc267-fc2a-41bf-bee5-5d7d83acec88].\nhttp://errors.angularjs.org/\"NG_VERSION_FULL\"/$parse/syntax?p0=a7cc267&p1=is%20an%20unexpected%20token&p2=2&p3=1a7cc267-fc2a-41bf-bee5-5d7d83acec88&p4=a7cc267-fc2a-41bf-bee5-5d7d83acec88"
},
"file": "docProps/custom.xml"
}
}
]
Hello, it seems that your tag looks like this :
{1a7cc267-fc2a-41bf-bee5-5d7d83acec88}
There are basically two issues :
-
If you use the angular parser, variables are not allowed to start with a number, so :
{a1b} is a valid tag but {1ab} is not valid.
-
{abcd-efg} means the variable "abcd" minus the variable "efg".
Are you sure you want the angular parser ?
Does your data look like this ?
doc.render({
"1a7cc267-fc2a-41bf-bee5-5d7d83acec88": "My data",
})
One way would be to detect if a tag is a uuid and if it is a uuid, not use the angular parser.
Hi, thanks for the quick reply!
The thing is that it is not reaching the doc.render yet.
the app is already crashing at:
const templatePath = path.join(process.cwd(), "templates", tenant, type, template + ".docx");
const templateDoc = fs.readFileSync(templatePath);
const zip = new PizZip(templateDoc);
doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
parser: angularParser,
});
You could use following code to check if the tag is a uuid and return some other value in that case.
import Docxtemplater from "docxtemplater";
import angularParser from "docxtemplater/expressions";
function isUUID ( uuid ) {
let s = "" + uuid;
s = s.match('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$');
if (s === null) {
return false;
}
return true;
}
try {
const templatePath = path.join(process.cwd(), "templates", tenant, type, template + ".docx");
const templateDoc = fs.readFileSync(templatePath);
const zip = new PizZip(templateDoc);
doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
parser: function(tag) {
if (isUUID(tag)) {
console.log('this is an uuid tag', tag);
return {
get: function(scope) {
return scope[tag];
}
}
}
return angularParser(tag);
},
});
} catch (error) {
logError("error setting up Docxtemplater", { error: error, template: template, data: data, tenant: tenant });
return error;
}
Also that tag is not in my document and not in the data.
Oh I see, this is actually a tag that is inside docProps/custom.xml inside a custom property.
You can setup your code to not try to replace those tags at all using this :
https://docxtemplater.com/faq/#skip-templating-custom-xml
Your code should be like this :
const avoidRenderingCoreXMLModule = {
name: "avoidRenderingCoreXMLModule",
getFileType({ doc }) {
doc.targets = doc.targets.filter(function (file) {
if (
file === "docProps/core.xml" ||
file === "docProps/app.xml" ||
file === "docProps/custom.xml"
) {
return false;
}
return true;
});
},
};
const doc = new Docxtemplater(zip, {
modules: [avoidRenderingCoreXMLModule],
paragraphLoop: true,
linebreaks: true,
});
Thanks for quick reply/update, it is working without the ts-ignore with 3.46.1!