Skip to content

Commit

Permalink
Add syntax.allowUnclosedTag
Browse files Browse the repository at this point in the history
  • Loading branch information
edi9999 committed Nov 7, 2024
1 parent 3102906 commit 24a645d
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 29 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
### 3.52.0

Add `syntax.allowUnclosedTag` option.

This allows to write : `Hello {user` and not have an error in your template.

### 3.51.2

Improve typescript typings :
Expand Down
1 change: 1 addition & 0 deletions es6/docxtemplater.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ declare namespace DXT {

interface Syntax {
allowUnopenedTag?: boolean;
allowUnclosedTag?: boolean;
changeDelimiterPrefix?: string | null;
}

Expand Down
1 change: 1 addition & 0 deletions es6/docxtemplater.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ const doc8 = new Docxtemplater(new PizZip("hello"), {
const doc9 = new Docxtemplater(new PizZip("hello"), {
syntax: {
allowUnopenedTag: true,
allowUnclosedTag: true,
changeDelimiterPrefix: null,
},
});
Expand Down
45 changes: 27 additions & 18 deletions es6/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,25 +126,30 @@ function getDelimiterErrors(delimiterMatches, fullText, syntaxOptions) {
lastDelimiterOffset,
delimiterOffset - lastDelimiterOffset + lastDelimiterLength + 4
);
if (!syntaxOptions.allowUnclosedTag) {
errors.push(
getDuplicateOpenTagException({
xtag,
offset: lastDelimiterOffset,
})
);
lastDelimiterMatch = currDelimiterMatch;
delimiterAcc.push({ ...currDelimiterMatch, error: true });
return delimiterAcc;
}
}
if (!syntaxOptions.allowUnclosedTag) {
errors.push(
getDuplicateOpenTagException({
xtag,
getUnclosedTagException({
xtag: wordToUtf8(xtag),
offset: lastDelimiterOffset,
})
);
lastDelimiterMatch = currDelimiterMatch;
delimiterAcc.push({ ...currDelimiterMatch, error: true });
return delimiterAcc;
}
errors.push(
getUnclosedTagException({
xtag: wordToUtf8(xtag),
offset: lastDelimiterOffset,
})
);
lastDelimiterMatch = currDelimiterMatch;
delimiterAcc.push({ ...currDelimiterMatch, error: true });
return delimiterAcc;
delimiterAcc.pop();
}

if (!inDelimiter && position === "end") {
Expand Down Expand Up @@ -177,7 +182,7 @@ function getDelimiterErrors(delimiterMatches, fullText, syntaxOptions) {
return delimiterAcc;
}

inDelimiter = !inDelimiter;
inDelimiter = position === "start";
lastDelimiterMatch = currDelimiterMatch;
delimiterAcc.push(currDelimiterMatch);
return delimiterAcc;
Expand All @@ -191,12 +196,16 @@ function getDelimiterErrors(delimiterMatches, fullText, syntaxOptions) {
lastDelimiterOffset,
fullText.length - lastDelimiterOffset
);
errors.push(
getUnclosedTagException({
xtag: wordToUtf8(xtag),
offset: lastDelimiterOffset,
})
);
if (!syntaxOptions.allowUnclosedTag) {
errors.push(
getUnclosedTagException({
xtag: wordToUtf8(xtag),
offset: lastDelimiterOffset,
})
);
} else {
delimiterWithErrors.pop();
}
}

return {
Expand Down
145 changes: 134 additions & 11 deletions es6/tests/e2e/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -1656,47 +1656,47 @@ const fixtures = [
},
{
it: "should work well with $index angular parser",
content: "<w:t>{#todos}{#$index==0}FIRST {/}{text} {/todos}</w:t>",
content: "<w:t>{#list}{#$index==0}FIRST {/}{text} {/list}</w:t>",
...noInternals,
options: {
parser: expressionParser,
},
scope: { todos: [{ text: "Hello" }, { text: "Other todo" }] },
result: '<w:t xml:space="preserve">FIRST Hello Other todo </w:t>',
scope: { list: [{ text: "Hello" }, { text: "Other item" }] },
result: '<w:t xml:space="preserve">FIRST Hello Other item </w:t>',
},
{
it: "should work well with $index inside condition angular parser",
content:
"<w:t>{#todos}{#important}!!{$index+1}{text}{/}{^important}?{$index+1}{text}{/}{/}</w:t>",
"<w:t>{#list}{#important}!!{$index+1}{text}{/}{^important}?{$index+1}{text}{/}{/}</w:t>",
...noInternals,
options: {
parser: expressionParser,
},
scope: {
todos: [
list: [
{ important: true, text: "Hello" },
{ text: "Other todo" },
{ text: "Other item" },
{ important: true, text: "Bye" },
],
},
result: '<w:t xml:space="preserve">!!1Hello?2Other todo!!3Bye</w:t>',
result: '<w:t xml:space="preserve">!!1Hello?2Other item!!3Bye</w:t>',
},
{
it: "should work well with $index inside condition angular parser",
content:
"<w:t>{#todos}{#important}!!{$index+1}{text}{/}{^important}?{$index+1}{text}{/}{/}</w:t>",
"<w:t>{#list}{#important}!!{$index+1}{text}{/}{^important}?{$index+1}{text}{/}{/}</w:t>",
...noInternals,
options: {
parser: angularParserIE11,
},
scope: {
todos: [
list: [
{ important: true, text: "Hello" },
{ text: "Other todo" },
{ text: "Other item" },
{ important: true, text: "Bye" },
],
},
result: '<w:t xml:space="preserve">!!1Hello?2Other todo!!3Bye</w:t>',
result: '<w:t xml:space="preserve">!!1Hello?2Other item!!3Bye</w:t>',
},
{
it: "should work well with nested conditions inside table",
Expand Down Expand Up @@ -2136,6 +2136,70 @@ http://errors.angularjs.org/"NG_VERSION_FULL"/$parse/lexerr?p0=Unexpected%20next
<w:r>
<w:t xml:space="preserve"> world</w:t>
</w:r>
</w:p>`,
},
{
it: "should not fail on triple open tag if allowUnclosedTag is true",
...noInternals,
content: `<w:p>
<w:r>
<w:t>Hello {{{</w:t>
</w:r>
<w:r>
<w:t>lastName</w:t>
</w:r>
<w:r>
<w:t>} world</w:t>
</w:r>
</w:p>`,
options: {
syntax: {
allowUnclosedTag: true,
},
},
scope: { firstName: "John", lastName: "Doe" },
result: `<w:p>
<w:r>
<w:t xml:space="preserve">Hello {{Doe</w:t>
</w:r>
<w:r>
<w:t></w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> world</w:t>
</w:r>
</w:p>`,
},
{
it: "should not fail on SPACED unclosed tag if allowUnclosedTag is true",
...noInternals,
content: `<w:p>
<w:r>
<w:t>Hello {firstName {</w:t>
</w:r>
<w:r>
<w:t>lastName</w:t>
</w:r>
<w:r>
<w:t>} world</w:t>
</w:r>
</w:p>`,
options: {
syntax: {
allowUnclosedTag: true,
},
},
scope: { firstName: "John", lastName: "Doe" },
result: `<w:p>
<w:r>
<w:t xml:space="preserve">Hello {firstName Doe</w:t>
</w:r>
<w:r>
<w:t></w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> world</w:t>
</w:r>
</w:p>`,
},
{
Expand Down Expand Up @@ -2168,6 +2232,65 @@ http://errors.angularjs.org/"NG_VERSION_FULL"/$parse/lexerr?p0=Unexpected%20next
<w:r>
<w:t xml:space="preserve"> } world} } }</w:t>
</w:r>
</w:p>`,
},
{
it: "should not fail if allowUnclosedTag on 'Hello {' string",
...noInternals,
content: "<w:p><w:r><w:t>Hello {</w:t></w:r></w:p>",
options: {
syntax: {
allowUnclosedTag: true,
allowUnopenedTag: true,
},
},
scope: { firstName: "John", lastName: "Doe" },
result: "<w:p><w:r><w:t>Hello {</w:t></w:r></w:p>",
},
{
it: "should not fail if allowUnclosedTag on 'Hello }' string",
...noInternals,
content: "<w:p><w:r><w:t>Hello }</w:t></w:r></w:p>",
options: {
syntax: {
allowUnclosedTag: true,
allowUnopenedTag: true,
},
},
scope: { firstName: "John", lastName: "Doe" },
result: "<w:p><w:r><w:t>Hello }</w:t></w:r></w:p>",
},
{
it: "should not fail on double delimiters if allowUnclosedTag and allowUnopenedTag is true",
...noInternals,
content: `<w:p>
<w:r>
<w:t>Hello {{</w:t>
</w:r>
<w:r>
<w:t>lastName</w:t>
</w:r>
<w:r>
<w:t>}}</w:t>
</w:r>
</w:p>`,
options: {
syntax: {
allowUnclosedTag: true,
allowUnopenedTag: true,
},
},
scope: { firstName: "John", lastName: "Doe" },
result: `<w:p>
<w:r>
<w:t xml:space="preserve">Hello {Doe</w:t>
</w:r>
<w:r>
<w:t></w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">}</w:t>
</w:r>
</w:p>`,
},
{
Expand Down

0 comments on commit 24a645d

Please sign in to comment.