diff --git a/src/qweb/qweb.ts b/src/qweb/qweb.ts index b808828c..a6c6572a 100644 --- a/src/qweb/qweb.ts +++ b/src/qweb/qweb.ts @@ -1,7 +1,7 @@ import { EventBus } from "../core/event_bus"; import { h, patch, VNode } from "../vdom/index"; import { CompilationContext } from "./compilation_context"; -import { shallowEqual } from "../utils"; +import { shallowEqual, escape } from "../utils"; import { addNS } from "../vdom/vdom"; /** @@ -348,8 +348,15 @@ export class QWeb extends EventBus { return vnode.text!; } const node = document.createElement(vnode.sel); - const result = patch(node, vnode); - return (result.elm).outerHTML; + const elem = patch(node, vnode).elm as HTMLElement; + function escapeTextNodes(node) { + if (node.nodeType === 3) { + node.textContent = escape(node.textContent); + } + for (let n of node.childNodes) { escapeTextNodes(n) } + } + escapeTextNodes(elem); + return elem.outerHTML; } /** diff --git a/src/utils.ts b/src/utils.ts index 4dfa6ee0..b8c34d2c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -58,12 +58,9 @@ export function escape(str: string | number | undefined): string { if (typeof str === "number") { return String(str); } - return str - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, "'") - .replace(/`/g, "`"); + const p = document.createElement('p'); + p.textContent = str; + return p.innerHTML; } /** diff --git a/tests/helpers.ts b/tests/helpers.ts index 912cb23f..cd3483f2 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -123,11 +123,8 @@ export function renderToString( context: EvalContext = {}, extra?: any ): string { - const node = renderToDOM(qweb, t, context, extra); - const result = node instanceof Text ? node.textContent! : node.outerHTML; - if (result !== qweb.renderToString(t, context, extra)) { - throw new Error("HTML string returned by renderToString helper does not match QWeb render"); - } + const result = qweb.renderToString(t, context, extra); + expect(qweb.templates[t].fn.toString()).toMatchSnapshot(); return result; } diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap index e02a0312..bc187066 100644 --- a/tests/qweb/__snapshots__/qweb.test.ts.snap +++ b/tests/qweb/__snapshots__/qweb.test.ts.snap @@ -347,6 +347,29 @@ exports[`attributes tuple variable 1`] = ` }" `; +exports[`attributes various escapes 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"test\\" + let scope = Object.create(context); + var h = this.h; + var _1 = '\`; + var _4 = scope['qux']; + let c5 = [], p5 = {key:5,attrs:{foo: _1,bar: _2,baz: _3}}; + if (_4 instanceof Array) { + p5.attrs[_4[0]] = _4[1]; + } else { + for (let key in _4) { + p5.attrs[key] = _4[key]; + } + } + var vn5 = h('div', p5, c5); + return vn5; +}" +`; + exports[`debugging t-debug 1`] = ` "function anonymous(context, extra ) { @@ -1553,6 +1576,22 @@ exports[`t-call (template calling with used set body 1`] = ` }" `; +exports[`t-esc escaping 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"test\\" + let scope = Object.create(context); + var h = this.h; + let c1 = [], p1 = {key:1}; + var vn1 = h('span', p1, c1); + var _2 = scope['var']; + if (_2 || _2 === 0) { + c1.push({text: _2}); + } + return vn1; +}" +`; + exports[`t-esc escaping on a node 1`] = ` "function anonymous(context, extra ) { diff --git a/tests/qweb/qweb.test.ts b/tests/qweb/qweb.test.ts index 9add73b0..28d4f655 100644 --- a/tests/qweb/qweb.test.ts +++ b/tests/qweb/qweb.test.ts @@ -120,9 +120,9 @@ describe("t-esc", () => { expect(renderToString(qweb, "test", { var: "ok" })).toBe("ok"); }); - test.skip("escaping", () => { + test("escaping", () => { qweb.addTemplate("test", ``); - expect(renderToString(qweb, "test", { var: "" })).toBe("<ok>"); + expect(renderToString(qweb, "test", { var: "abc" })).toBe("&lt;ok&gt;abc&lt;/ok&gt;"); }); test("escaping on a node", () => { @@ -620,7 +620,7 @@ describe("attributes", () => { expect(result).toBe(`
`); }); - test.skip("various escapes", () => { + test("various escapes", () => { // not needed?? qweb.addTemplate( "test", @@ -636,7 +636,7 @@ describe("attributes", () => { baz: 1, qux: { qux: "<>" } }); - const expected = `
`; + const expected = "
\" qux=\"<>\">
"; expect(result).toBe(expected); });