Skip to content

Commit

Permalink
feat: tojson filter
Browse files Browse the repository at this point in the history
  • Loading branch information
wenfw committed Sep 13, 2024
1 parent 41cd5df commit a5b1758
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
21 changes: 20 additions & 1 deletion packages/environment/src/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,25 @@ export const rejectattr: SelectReject = nunjucksFunction(["value"], {
} else throw new Error("unreachable");
});

export function tojson(o: unknown, indent = 0): string {
if (o === undefined) {
return "undefined";
}

return markSafe(
JSON.stringify(
o,
(_, v) =>
typeof v === "bigint" || typeof v === "symbol" ? v.toString() : v,
indent,
)
.replace(/</g, "\\u003c")
.replace(/>/g, "\\u003e")
.replace(/&/g, "\\u0026")
.replace(/'/g, "\\u0027"),
);
}

export default {
abs,
// attr,
Expand Down Expand Up @@ -1532,5 +1551,5 @@ export default {
wordcount,
// wordwrap,
xmlattr,
// tosjon,
tojson,
};
50 changes: 47 additions & 3 deletions test/filters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -952,9 +952,53 @@ describe("filters", () => {
});
});

it.skip("tojson", () => {
const tmpl = env.fromString("{{ x | tojson }}");
expect(tmpl.render({ x: { foo: "bar" } })).toBe('{"foo": "bar"}');
describe("tojson", () => {
it("primitive value", () => {
const tmpl = env.fromString("{{ x | tojson }}");
expect(tmpl.render({ x: "string" })).toBe('"string"');
expect(tmpl.render({ x: 0 })).toBe("0");
expect(tmpl.render({ x: -1 })).toBe("-1");
expect(tmpl.render({ x: -1 })).toBe("-1");
expect(tmpl.render({ x: true })).toBe("true");
expect(tmpl.render({ x: false })).toBe("false");
expect(tmpl.render({ x: null })).toBe("null");
expect(tmpl.render({ x: undefined })).toBe("undefined");
expect(tmpl.render({ x: BigInt("9007199254740991") })).toBe(
'"9007199254740991"',
);
expect(tmpl.render({ x: Symbol("symbol") })).toBe('"Symbol(symbol)"');
});

it("object value", () => {
const tmpl = env.fromString("{{ x | tojson }}");
expect(tmpl.render({ x: { foo: "bar" } })).toBe('{"foo":"bar"}');
expect(tmpl.render({ x: ["foo", "bar"] })).toBe('["foo","bar"]');
expect(tmpl.render({ x: /\b/ })).toBe("{}");
expect(tmpl.render({ x: new Error("<error />") })).toBe("{}");
expect(tmpl.render({ x: new Date("2021-02-28T23:15:00.000Z") })).toBe(
'"2021-02-28T23:15:00.000Z"',
);
});

it("escape", () => {
const tmpl = env.fromString("{{ x | tojson }}");
expect(tmpl.render({ x: "\"ba&r'" })).toBe('"\\"ba\\u0026r\\u0027"');
expect(tmpl.render({ x: "<bar>" })).toBe('"\\u003cbar\\u003e"');
expect(tmpl.render({ x: { "<foo>": "</bar>" } })).toBe(
'{"\\u003cfoo\\u003e":"\\u003c/bar\\u003e"}',
);
expect(tmpl.render({ x: ["<foo>", "<bar>"] })).toBe(
'["\\u003cfoo\\u003e","\\u003cbar\\u003e"]',
);
});

it("indent: 2", () => {
const tmpl = env.fromString("{{ x | tojson(2) }}");
expect(tmpl.render({ x: { foo: "bar" } })).toBe('{\n "foo": "bar"\n}');
expect(tmpl.render({ x: ["foo", "bar"] })).toBe(
'[\n "foo",\n "bar"\n]',
);
});
});

it.skip("wordwrap", () => {
Expand Down

0 comments on commit a5b1758

Please sign in to comment.