This commit is contained in:
Géry Debongnie
2021-10-11 14:00:56 +02:00
parent c86bb6111a
commit 82ab18ad83
2 changed files with 69 additions and 2 deletions
+67 -1
View File
@@ -15,7 +15,7 @@ import { browser } from "./browser";
export function whenReady(fn?: any) { export function whenReady(fn?: any) {
return new Promise(function (resolve) { return new Promise(function (resolve) {
if (document.readyState !== "loading") { if (document.readyState !== "loading") {
resolve(); (resolve as any)();
} else { } else {
document.addEventListener("DOMContentLoaded", resolve, false); document.addEventListener("DOMContentLoaded", resolve, false);
} }
@@ -101,3 +101,69 @@ export function shallowEqual(p1, p2): boolean {
} }
return true; return true;
} }
const escapeMethod = Symbol('html')
// notable issues:
// * objects can't be negative in JS, so !!"" -> false but
// !!(new String) -> true, likewise markup
// TODO (?)
// * Markup.join / Markup#join => escapes items and returns a Markup
// * Markup#replace => automatically escapes the replacements (difficult impl)
class _Markup extends String {
[escapeMethod]() {
return this;
}
}
/**
* Returns a markup object, which acts like a String but is considered safe by
* `_.escape`, and will therefore be injected as-is (without additional
* escaping) in templates. Can be used to inject dynamic HTML in templates
* (where the template itself can't), see first example.
*
* Can also be used as a *template tag*, in which case the literal content
* won't be escaped but the substitutions which are not already markup objects
* will be.
*
* ## WARNINGS:
* * A markup object is a `String` (boxed) but not a `string` (primitive), they
* typecheck differently which can be relevant.
* * To strip out the "markupness", just call `String(markup)`.
* * Most string operations (e.g. concatenation, `String#replace`, ...) will
* also strip out markupness
* * If the input is empty, returns a regular string (that way boolean tests
* work as expected).
*
* @returns a markup object
*
* @example regular function
* let h;
* if (someTest) {
* h = Markup(_t("This is a <strong>success</strong>"));
* } else {
* h = Markup(_t("Things did <strong>not</strong> work out"));
* }
* qweb.render("some_template", { message: h });
*
* @example template tag
* const escaped = "<some> text";
* const asis = Markup`some <b>text</b>`;
* const h = Markup`Regular strings get ${escaped} but markup is injected ${asis}`;
*/
export function Markup(v, ...exprs) {
if (!(v instanceof Array)) {
return v ? new _Markup(v) : '';
}
const elements = [];
let i = 0;
for(; i < exprs.length; ++i) {
elements.push(v[i], escape(exprs[i]));
}
elements.push(v[i]);
const s = elements.join('');
if (!s) { return '' }
return new _Markup(s);
}
+2 -1
View File
@@ -2,6 +2,7 @@ import { QWeb } from "../../src/qweb/index";
import { config } from "../../src/index"; import { config } from "../../src/index";
import { nextTick, normalize, renderToDOM, renderToString, trim } from "../helpers"; import { nextTick, normalize, renderToDOM, renderToString, trim } from "../helpers";
import { patch } from "../../src/vdom"; import { patch } from "../../src/vdom";
import { Markup } from "../../src/utils";
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Setup and helpers // Setup and helpers
@@ -246,7 +247,7 @@ describe("t-out (formerly t-raw tests)", () => {
test("not escaping", () => { test("not escaping", () => {
qweb.addTemplate("test", `<div><t t-out="var"/></div>`); qweb.addTemplate("test", `<div><t t-out="var"/></div>`);
expect(renderToString(qweb, "test", { var: "<ok></ok>" })).toBe("<div><ok></ok></div>"); expect(renderToString(qweb, "test", { var: Markup`<ok></ok>` })).toBe("<div><ok></ok></div>");
}); });
test("t-raw and another sibling node", () => { test("t-raw and another sibling node", () => {