Skip to content

Commit

Permalink
Add syntax.allowUnbalancedLoops option
Browse files Browse the repository at this point in the history
  • Loading branch information
edi9999 committed Jan 27, 2025
1 parent 6fce806 commit 1ad6a19
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 3 deletions.
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
### 3.58.4

Make it possible to write unbalanced loops, if specifying the following the option :

```js
const expressionParser = require("docxtemplater/expressions.js");
const doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
syntax: {
allowUnbalancedLoops: true,
},
});
doc.render(/* data */);
```

Then the following template in a table will work

```docx
-------------------------
| {#a} | {/a}{#b}{/b} |
-------------------------
```

This template will normally throw an "unbalanced_loop_tags" exception.

The correct fix is to move the {#b} to be inside the {#a} loop like this :

```docx
-------------------------
| {#a} | {#b}{/b}{/a} |
-------------------------
```

However, if you have some templates that were used before v3.19.9 of docxtemplater, and can't change the templates, you can use the `allowUnbalancedLoops` option.

### 3.58.3

Do not throw an error if sending xml invalid character such as "\u0002" when using TxtTemplater.
Expand Down
27 changes: 24 additions & 3 deletions es6/modules/expand-pair-trait.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,13 @@ class ExpandPairTrait {
if (!expandTo || fileType === "text") {
const left = pair[0].offset;
const right = pair[1].offset;
if (left < lastRight) {
if (
left < lastRight &&
!this.docxtemplater.options.syntax.allowUnbalancedLoops
) {
errors.push(getUnbalancedLoopException(pair, lastPair));
}

lastPair = pair;
lastRight = right;
return [left, right];
Expand All @@ -179,7 +183,10 @@ class ExpandPairTrait {
} catch (e) {
errors.push(e);
}
if (left < lastRight) {
if (
left < lastRight &&
!this.docxtemplater.options.syntax.allowUnbalancedLoops
) {
errors.push(getUnbalancedLoopException(pair, lastPair));
}
lastRight = right;
Expand All @@ -192,7 +199,6 @@ class ExpandPairTrait {
return { postparsed, errors };
}
// Stryker restore all

let currentPairIndex = 0;
let innerParts;

Expand All @@ -207,20 +213,35 @@ class ExpandPairTrait {
newParsed.push(part);
return newParsed;
}
// We're inside the pair
if (expandedPair[0] === i) {
// Start pair
innerParts = [];
}
if (pair[0].offset !== i && pair[1].offset !== i) {
// Exclude inner pair indexes
innerParts.push(part);
}
if (expandedPair[1] === i) {
// End pair
const basePart = postparsed[pair[0].offset];
basePart.subparsed = postparse(innerParts, { basePart });
basePart.endLindex = pair[1].part.lIndex;
delete basePart.location;
delete basePart.expandTo;
newParsed.push(basePart);
currentPairIndex++;
let expandedPair = expandedPairs[currentPairIndex];
while (expandedPair && expandedPair[0] < i) {
/*
* If we have :
* expandedPairs =[[5,72],[51,67],[90,106]]
* Then after treating [5,72], we need to treat [90,106]
* Fixed since v3.58.4
*/
currentPairIndex++;
expandedPair = expandedPairs[currentPairIndex];
}
}
return newParsed;
}, []);
Expand Down
37 changes: 37 additions & 0 deletions es6/tests/e2e/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1353,3 +1353,40 @@ describe("OptionsTransformer", () => {
);
});
});

describe("Syntax.allowUnbalancedLoops option", () => {
it("should work with unbalanced loop with allowUnbalancedLoops option", () => {
const doc = createDocV4("table-unbalanced-loop.docx", {
syntax: {
allowUnbalancedLoops: true,
},
});
doc.render({
a: [1, 2, 3],
b: [1, 2, 3],
c: [1, 2, 3],
});
shouldBeSame({
doc,
expectedName: "expected-table-unbalanced-loop.docx",
});
});

it("should work with unbalanced loop with allowUnbalancedLoops option (2)", () => {
const doc = createDocV4("table-unbalanced-loop-2.docx", {
syntax: {
allowUnbalancedLoops: true,
},
});

doc.render({
a: [1, 2, 3],
b: [1, 2, 3],
c: [1, 2, 3],
});
shouldBeSame({
doc,
expectedName: "expected-table-unbalanced-loop-2.docx",
});
});
});
Binary file added examples/expected-table-unbalanced-loop-2.docx
Binary file not shown.
Binary file added examples/expected-table-unbalanced-loop.docx
Binary file not shown.
Binary file added examples/table-unbalanced-loop-2.docx
Binary file not shown.
Binary file added examples/table-unbalanced-loop.docx
Binary file not shown.

0 comments on commit 1ad6a19

Please sign in to comment.