mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] compiler: fix xmlns attribute not being set correctly in firefox
Firefox will not serialize the xmlns attributes of node inside XMLDocuments, see https://bugzilla.mozilla.org/show_bug.cgi?id=175946 it will only output an xmlns attribute if the node being serialized has a non-null namespaceURI. When compiling templates, we currently use a special attribute, "block-ns" to keep track of the namespace, but we do not make use of the namespace to create the elements that will be serialized to the compiled block string. This causes a difference in behaviour between Chrome and Firefox: since we end up with an Element with two attributes: the block-ns attribute and the xmlns attribute. Chrome will serialize both, but Firefox will only serialize the block-ns because the Element does not have a namespaceURI. To fix this issue, we get rid of the block-ns magic attribute completely, and use xmlns instead. We also use the namespace when creating intermediate elements that will be used to create the serialized block string: the namespace is only used to create the elements but *not* set as an attribute, as this would cause chrome to serialize it twice, causing a duplicate attribute error when parsing it further down the line. When creating the template element for the block at runtime, the xmlns attribute is used both as the namespace with which to create the element, and set as an attribute, this doesn't cause issues when serializing later because the namespaceURI is never serialized as an attribute when serializing an HTML document[1], so we avoid the double-serialization in Chrome, and when doing HTML serialization, Firefox will correctly serialize the attribute. It's desirable that the xmlns is set as an attribute to allow users to use owl to render SVG, and then use the HTML serialization of it as a SVG even outside the context of an HTML document (eg to generate an SVG file or an SVG data URL). [1]: https://w3c.github.io/DOM-Parsing/#xml-serialization
This commit is contained in:
committed by
Jorge Pinna Puissant
parent
e0758c0e9e
commit
b25e988628
@@ -585,11 +585,6 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
// attributes
|
// attributes
|
||||||
const attrs: Attrs = {};
|
const attrs: Attrs = {};
|
||||||
const nameSpace = ast.ns || ctx.nameSpace;
|
|
||||||
if (nameSpace && isNewBlock) {
|
|
||||||
// specific namespace uri
|
|
||||||
attrs["block-ns"] = nameSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let key in ast.attrs) {
|
for (let key in ast.attrs) {
|
||||||
let expr, attrName;
|
let expr, attrName;
|
||||||
@@ -718,7 +713,10 @@ export class CodeGenerator {
|
|||||||
attrs["block-ref"] = String(idx);
|
attrs["block-ref"] = String(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dom = xmlDoc.createElement(ast.tag);
|
const nameSpace = ast.ns || ctx.nameSpace;
|
||||||
|
const dom = nameSpace
|
||||||
|
? xmlDoc.createElementNS(nameSpace, ast.tag)
|
||||||
|
: xmlDoc.createElement(ast.tag);
|
||||||
for (const [attr, val] of Object.entries(attrs)) {
|
for (const [attr, val] of Object.entries(attrs)) {
|
||||||
if (!(attr === "class" && val === "")) {
|
if (!(attr === "class" && val === "")) {
|
||||||
dom.setAttribute(attr, val);
|
dom.setAttribute(attr, val);
|
||||||
|
|||||||
@@ -213,14 +213,14 @@ export function parse(xml: string | Element): AST {
|
|||||||
|
|
||||||
function _parse(xml: Element): AST {
|
function _parse(xml: Element): AST {
|
||||||
normalizeXML(xml);
|
normalizeXML(xml);
|
||||||
const ctx = { inPreTag: false, inSVG: false };
|
const ctx = { inPreTag: false };
|
||||||
return parseNode(xml, ctx) || { type: ASTType.Text, value: "" };
|
return parseNode(xml, ctx) || { type: ASTType.Text, value: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ParsingContext {
|
interface ParsingContext {
|
||||||
tModelInfo?: TModelInfo | null;
|
tModelInfo?: TModelInfo | null;
|
||||||
|
nameSpace?: string;
|
||||||
inPreTag: boolean;
|
inPreTag: boolean;
|
||||||
inSVG: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
||||||
@@ -323,9 +323,8 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
if (tagName === "pre") {
|
if (tagName === "pre") {
|
||||||
ctx.inPreTag = true;
|
ctx.inPreTag = true;
|
||||||
}
|
}
|
||||||
const shouldAddSVGNS = ROOT_SVG_TAGS.has(tagName) && !ctx.inSVG;
|
|
||||||
ctx.inSVG = ctx.inSVG || shouldAddSVGNS;
|
let ns = !ctx.nameSpace && ROOT_SVG_TAGS.has(tagName) ? "http://www.w3.org/2000/svg" : null;
|
||||||
const ns = shouldAddSVGNS ? "http://www.w3.org/2000/svg" : null;
|
|
||||||
const ref = node.getAttribute("t-ref");
|
const ref = node.getAttribute("t-ref");
|
||||||
node.removeAttribute("t-ref");
|
node.removeAttribute("t-ref");
|
||||||
|
|
||||||
@@ -389,6 +388,8 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
}
|
}
|
||||||
} else if (attr.startsWith("block-")) {
|
} else if (attr.startsWith("block-")) {
|
||||||
throw new OwlError(`Invalid attribute: '${attr}'`);
|
throw new OwlError(`Invalid attribute: '${attr}'`);
|
||||||
|
} else if (attr === "xmlns") {
|
||||||
|
ns = value;
|
||||||
} else if (attr !== "t-name") {
|
} else if (attr !== "t-name") {
|
||||||
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
||||||
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
||||||
@@ -401,6 +402,9 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
attrs[attr] = value;
|
attrs[attr] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ns) {
|
||||||
|
ctx.nameSpace = ns;
|
||||||
|
}
|
||||||
|
|
||||||
const children = parseChildren(node, ctx);
|
const children = parseChildren(node, ctx);
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -144,12 +144,7 @@ function buildTree(
|
|||||||
info.push({ type: "child", idx: index });
|
info.push({ type: "child", idx: index });
|
||||||
el = document.createTextNode("");
|
el = document.createTextNode("");
|
||||||
}
|
}
|
||||||
const attrs = (node as Element).attributes;
|
currentNS ||= (node as Element).namespaceURI;
|
||||||
const ns = attrs.getNamedItem("block-ns");
|
|
||||||
if (ns) {
|
|
||||||
attrs.removeNamedItem("block-ns");
|
|
||||||
currentNS = ns.value;
|
|
||||||
}
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
el = currentNS
|
el = currentNS
|
||||||
? document.createElementNS(currentNS, tagName)
|
? document.createElementNS(currentNS, tagName)
|
||||||
@@ -165,6 +160,7 @@ function buildTree(
|
|||||||
const fragment = document.createElement("template").content;
|
const fragment = document.createElement("template").content;
|
||||||
fragment.appendChild(el);
|
fragment.appendChild(el);
|
||||||
}
|
}
|
||||||
|
const attrs = (node as Element).attributes;
|
||||||
for (let i = 0; i < attrs.length; i++) {
|
for (let i = 0; i < attrs.length; i++) {
|
||||||
const attrName = attrs[i].name;
|
const attrName = attrs[i].name;
|
||||||
const attrValue = attrs[i].value;
|
const attrValue = attrs[i].value;
|
||||||
|
|||||||
@@ -244,12 +244,14 @@ describe("misc", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("namespace is not propagated to siblings", () => {
|
test("namespace is not propagated to siblings", () => {
|
||||||
const block = createBlock(`<div><svg block-ns="someNameSpace"><g/></svg><div></div></div>`);
|
const block = createBlock(`<div><svg xmlns="someNameSpace"><g/></svg><div></div></div>`);
|
||||||
|
|
||||||
const fixture = makeTestFixture();
|
const fixture = makeTestFixture();
|
||||||
mount(block(), fixture);
|
mount(block(), fixture);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("<div><svg><g></g></svg><div></div></div>");
|
expect(fixture.innerHTML).toBe(
|
||||||
|
'<div><svg xmlns="someNameSpace"><g></g></svg><div></div></div>'
|
||||||
|
);
|
||||||
expect(fixture.querySelector("svg")!.namespaceURI).toBe("someNameSpace");
|
expect(fixture.querySelector("svg")!.namespaceURI).toBe("someNameSpace");
|
||||||
expect(fixture.querySelector("g")!.namespaceURI).toBe("someNameSpace");
|
expect(fixture.querySelector("g")!.namespaceURI).toBe("someNameSpace");
|
||||||
const allDivs = fixture.querySelectorAll("div");
|
const allDivs = fixture.querySelectorAll("div");
|
||||||
|
|||||||
@@ -30,22 +30,22 @@ describe("namespace", () => {
|
|||||||
expect(fixture.firstElementChild!.namespaceURI).toBe(XHTML_URI);
|
expect(fixture.firstElementChild!.namespaceURI).toBe(XHTML_URI);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace can be changed with block-ns", () => {
|
test("namespace can be changed with xmlns", () => {
|
||||||
const block = createBlock(`<tag block-ns="${SVG_URI}"/>`);
|
const block = createBlock(`<tag xmlns="${SVG_URI}"/>`);
|
||||||
const tree = block();
|
const tree = block();
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<tag></tag>");
|
expect(fixture.innerHTML).toBe(`<tag xmlns="${SVG_URI}"></tag>`);
|
||||||
expect(fixture.firstElementChild!.namespaceURI).toBe(SVG_URI);
|
expect(fixture.firstElementChild!.namespaceURI).toBe(SVG_URI);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace is kept for children", () => {
|
test("namespace is kept for children", () => {
|
||||||
const block = createBlock(
|
const block = createBlock(
|
||||||
`<parent block-ns="${SVG_URI}"><child><subchild/></child><child/></parent>`
|
`<parent xmlns="${SVG_URI}"><child><subchild/></child><child/></parent>`
|
||||||
);
|
);
|
||||||
const tree = block();
|
const tree = block();
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
expect(fixture.innerHTML).toBe(
|
expect(fixture.innerHTML).toBe(
|
||||||
"<parent><child><subchild></subchild></child><child></child></parent>"
|
`<parent xmlns="${SVG_URI}"><child><subchild></subchild></child><child></child></parent>`
|
||||||
);
|
);
|
||||||
const parent = fixture.firstElementChild!;
|
const parent = fixture.firstElementChild!;
|
||||||
const child1 = parent.firstElementChild!;
|
const child1 = parent.firstElementChild!;
|
||||||
@@ -58,10 +58,10 @@ describe("namespace", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("various namespaces in same block", () => {
|
test("various namespaces in same block", () => {
|
||||||
const block = createBlock(`<none><one block-ns="one"/><two block-ns="two"/></none>`);
|
const block = createBlock(`<none><one xmlns="one"/><two xmlns="two"/></none>`);
|
||||||
const tree = block();
|
const tree = block();
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<none><one></one><two></two></none>");
|
expect(fixture.innerHTML).toBe('<none><one xmlns="one"></one><two xmlns="two"></two></none>');
|
||||||
const none = fixture.firstElementChild!;
|
const none = fixture.firstElementChild!;
|
||||||
const one = none.firstElementChild!;
|
const one = none.firstElementChild!;
|
||||||
const two = one.nextElementSibling!;
|
const two = one.nextElementSibling!;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ exports[`properly support svg add proper namespace to g tags 1`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<g block-ns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </g>\`);
|
let block1 = createBlock(\`<g xmlns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </g>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -18,7 +18,7 @@ exports[`properly support svg add proper namespace to svg 1`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\" width=\\"100px\\" height=\\"90px\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"100px\\" height=\\"90px\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -31,7 +31,7 @@ exports[`properly support svg namespace to g tags not added if already in svg na
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><g/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><g/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -44,7 +44,7 @@ exports[`properly support svg namespace to svg tags added even if already in svg
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><svg/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><svg/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -58,8 +58,8 @@ exports[`properly support svg svg creates new block if it is within html -- 2 1`
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/><block-child-0/></svg>\`);
|
let block2 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
let block3 = createBlock(\`<path block-ns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
let block3 = createBlock(\`<path xmlns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let b3;
|
let b3;
|
||||||
@@ -78,7 +78,7 @@ exports[`properly support svg svg creates new block if it is within html 1`] = `
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/></svg>\`);
|
let block2 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = block2();
|
const b2 = block2();
|
||||||
@@ -93,7 +93,7 @@ exports[`properly support svg svg namespace added to sub templates if root tag i
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
const callTemplate_1 = app.getTemplate(\`path\`);
|
const callTemplate_1 = app.getTemplate(\`path\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
@@ -107,7 +107,7 @@ exports[`properly support svg svg namespace added to sub templates if root tag i
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<path block-ns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
let block1 = createBlock(\`<path xmlns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -120,8 +120,8 @@ exports[`properly support svg svg namespace added to sub-blocks 1`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
let block2 = createBlock(\`<path block-ns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
let block2 = createBlock(\`<path xmlns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let b2;
|
let b2;
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ describe("properly support svg", () => {
|
|||||||
test("add proper namespace to svg", () => {
|
test("add proper namespace to svg", () => {
|
||||||
const template = `<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </svg>`;
|
const template = `<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </svg>`;
|
||||||
expect(renderToString(template)).toBe(
|
expect(renderToString(template)).toBe(
|
||||||
`<svg width=\"100px\" height=\"90px\"><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </svg>`
|
`<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle> </svg>`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("add proper namespace to g tags", () => {
|
test("add proper namespace to g tags", () => {
|
||||||
const template = `<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </g>`;
|
const template = `<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </g>`;
|
||||||
expect(renderToString(template)).toBe(
|
expect(renderToString(template)).toBe(
|
||||||
`<g><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </g>`
|
`<g xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle> </g>`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace to g tags not added if already in svg namespace", () => {
|
test("namespace to g tags not added if already in svg namespace", () => {
|
||||||
const template = `<svg><g/></svg>`;
|
const template = `<svg><g/></svg>`;
|
||||||
expect(renderToString(template)).toBe(`<svg><g></g></svg>`);
|
expect(renderToString(template)).toBe(`<svg xmlns="http://www.w3.org/2000/svg"><g></g></svg>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace to svg tags added even if already in svg namespace", () => {
|
test("namespace to svg tags added even if already in svg namespace", () => {
|
||||||
@@ -41,8 +41,13 @@ describe("properly support svg", () => {
|
|||||||
test("svg namespace added to sub-blocks", () => {
|
test("svg namespace added to sub-blocks", () => {
|
||||||
const template = `<svg><path t-if="path"/></svg>`;
|
const template = `<svg><path t-if="path"/></svg>`;
|
||||||
|
|
||||||
expect(renderToString(template, { path: false })).toBe(`<svg></svg>`);
|
expect(renderToString(template, { path: false })).toBe(
|
||||||
expect(renderToString(template, { path: true })).toBe(`<svg><path></path></svg>`);
|
`<svg xmlns="http://www.w3.org/2000/svg"></svg>`
|
||||||
|
);
|
||||||
|
// Because the path is its own block, it has its own xmlns attribute
|
||||||
|
expect(renderToString(template, { path: true })).toBe(
|
||||||
|
`<svg xmlns="http://www.w3.org/2000/svg"><path xmlns="http://www.w3.org/2000/svg"></path></svg>`
|
||||||
|
);
|
||||||
|
|
||||||
const bdom = renderToBdom(template, { path: true });
|
const bdom = renderToBdom(template, { path: true });
|
||||||
const fixture = makeTestFixture();
|
const fixture = makeTestFixture();
|
||||||
|
|||||||
@@ -1248,7 +1248,7 @@ exports[`support svg components add proper namespace to svg 1`] = `
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
const comp1 = app.createComponent(\`GComp\`, true, false, false, []);
|
const comp1 = app.createComponent(\`GComp\`, true, false, false, []);
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = comp1({}, key + \`__1\`, node, this, null);
|
const b2 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
@@ -1262,7 +1262,7 @@ exports[`support svg components add proper namespace to svg 2`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<g block-ns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/></g>\`);
|
let block1 = createBlock(\`<g xmlns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/></g>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
|
|||||||
@@ -1024,7 +1024,7 @@ describe("support svg components", () => {
|
|||||||
await mount(Svg, fixture);
|
await mount(Svg, fixture);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe(
|
expect(fixture.innerHTML).toBe(
|
||||||
'<svg><g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle></g></svg>'
|
'<svg xmlns="http://www.w3.org/2000/svg"><g xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle></g></svg>'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user