Skip to content

Commit 97a2bde

Browse files
committed
modify nunjucks parsing to stop parsing to string as [Object object]
1 parent 530a4be commit 97a2bde

File tree

4 files changed

+92
-13
lines changed

4 files changed

+92
-13
lines changed

js/src/template/nunjucks-env.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import { nunjucks } from "./nunjucks";
2-
import type { Environment as NunjucksEnvironment } from "nunjucks";
2+
import type {
3+
Environment as NunjucksEnvironment,
4+
ConfigureOptions,
5+
} from "nunjucks";
36
import { SyncLazyValue } from "../util";
47

58
const createNunjucksEnv = (throwOnUndefined: boolean): NunjucksEnvironment => {
6-
return new nunjucks.Environment(null, {
7-
autoescape: true,
9+
const options: ConfigureOptions & { finalize?: (val: unknown) => unknown } = {
10+
autoescape: false,
811
throwOnUndefined,
9-
});
12+
// Finalize function is called for every variable output
13+
// This automatically JSON.stringify's objects, similar to the custom Mustache's escape function
14+
finalize: (val: unknown) => {
15+
if (typeof val === "object" && val !== null) {
16+
return JSON.stringify(val);
17+
}
18+
return val;
19+
},
20+
};
21+
22+
const env = new nunjucks.Environment(null, options);
23+
return env;
1024
};
1125

1226
const nunjucksEnv = new SyncLazyValue<NunjucksEnvironment>(() =>

js/src/template/nunjucks-render.test.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
import { describe, test, expect } from "vitest";
22
import { lintTemplate } from "./nunjucks-utils";
33
import { nunjucks } from "./nunjucks";
4+
import { getNunjucksEnv } from "./nunjucks-env";
45

56
function getEnv() {
6-
return new nunjucks.Environment(null, {
7-
autoescape: true,
8-
throwOnUndefined: false,
9-
});
7+
return getNunjucksEnv(false);
108
}
119

1210
function getStrictEnv() {
13-
return new nunjucks.Environment(null, {
14-
autoescape: true,
15-
throwOnUndefined: true,
16-
});
11+
return getNunjucksEnv(true);
1712
}
1813

1914
describe("nunjucks rendering", () => {

js/src/template/nunjucks-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as nunjucks from "nunjucks";
22

33
export function lintTemplate(template: string, context: any): void {
44
const env = new nunjucks.Environment(null, {
5-
autoescape: true,
5+
autoescape: false,
66
throwOnUndefined: true,
77
});
88
env.renderString(template, context);

js/src/template/renderer.test.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,74 @@ describe("renderTemplateContent", () => {
8282
});
8383
expect(result).toBe("Data: 42");
8484
});
85+
86+
test("renders objects as JSON strings in mustache (not [object Object])", () => {
87+
const varsWithObject = {
88+
user: { name: "Alice", age: 30 },
89+
items: ["a", "b", "c"],
90+
};
91+
const result = renderTemplateContent(
92+
"User: {{user}}, Items: {{items}}",
93+
varsWithObject,
94+
escape,
95+
{ templateFormat: "mustache" },
96+
);
97+
expect(result).toBe(
98+
'User: {"name":"Alice","age":30}, Items: ["a","b","c"]',
99+
);
100+
expect(result).not.toContain("[object Object]");
101+
});
102+
103+
test("renders objects as JSON strings in nunjucks (not [object Object])", () => {
104+
const varsWithObject = {
105+
user: { name: "Bob", age: 25 },
106+
items: [1, 2, 3],
107+
};
108+
const result = renderTemplateContent(
109+
"User: {{ user }}, Items: {{ items }}",
110+
varsWithObject,
111+
escape,
112+
{ templateFormat: "nunjucks" },
113+
);
114+
expect(result).toBe('User: {"name":"Bob","age":25}, Items: [1,2,3]');
115+
expect(result).not.toContain("[object Object]");
116+
});
117+
118+
test("renders nested objects as JSON strings in mustache", () => {
119+
const varsWithNested = {
120+
data: {
121+
nested: {
122+
value: 123,
123+
items: ["x", "y"],
124+
},
125+
},
126+
};
127+
const result = renderTemplateContent(
128+
"Data: {{data}}",
129+
varsWithNested,
130+
escape,
131+
{ templateFormat: "mustache" },
132+
);
133+
expect(result).toBe('Data: {"nested":{"value":123,"items":["x","y"]}}');
134+
expect(result).not.toContain("[object Object]");
135+
});
136+
137+
test("renders nested objects as JSON strings in nunjucks", () => {
138+
const varsWithNested = {
139+
config: {
140+
settings: {
141+
enabled: true,
142+
count: 5,
143+
},
144+
},
145+
};
146+
const result = renderTemplateContent(
147+
"Config: {{ config }}",
148+
varsWithNested,
149+
escape,
150+
{ templateFormat: "nunjucks" },
151+
);
152+
expect(result).toBe('Config: {"settings":{"enabled":true,"count":5}}');
153+
expect(result).not.toContain("[object Object]");
154+
});
85155
});

0 commit comments

Comments
 (0)