[IMP] svg namespace support

This commit is contained in:
Bruno Boi
2021-11-19 11:31:04 +01:00
committed by Aaron Bohy
parent 093218a067
commit 5d4a38ad0f
8 changed files with 310 additions and 38 deletions
+20 -9
View File
@@ -116,6 +116,7 @@ interface IntermediateTree {
forceRef?: boolean;
refIdx?: number;
refN: number;
currentNS: string | null;
}
function buildTree(
@@ -124,9 +125,10 @@ function buildTree(
domParentTree: IntermediateTree | null = null
): IntermediateTree {
switch (node.nodeType) {
case 1: {
case Node.ELEMENT_NODE: {
// HTMLElement
let isActive = false;
let currentNS = parent && parent.currentNS;
const tagName = (node as Element).tagName;
let el: Node | undefined = undefined;
const info: DynamicInfo[] = [];
@@ -143,11 +145,18 @@ function buildTree(
el = document.createTextNode("");
isActive = true;
}
if (!el) {
el = document.createElement(tagName);
const attrs = (node as Element).attributes;
const ns = attrs.getNamedItem("block-ns");
if (ns) {
attrs.removeNamedItem("block-ns");
currentNS = ns.value;
}
if (el instanceof HTMLElement) {
const attrs = (node as Element).attributes;
if (!el) {
el = currentNS
? document.createElementNS(currentNS, tagName)
: document.createElement(tagName);
}
if (el instanceof Element) {
for (let i = 0; i < attrs.length; i++) {
const attrName = attrs[i].name;
const attrValue = attrs[i].value;
@@ -193,13 +202,14 @@ function buildTree(
el,
info,
refN: isActive ? 1 : 0,
currentNS,
};
if (node.firstChild) {
const childNode = node.childNodes[0];
if (
node.childNodes.length === 1 &&
childNode.nodeType === 1 &&
childNode.nodeType === Node.ELEMENT_NODE &&
(childNode as Element).tagName.startsWith("block-child-")
) {
const tagName = (childNode as Element).tagName;
@@ -227,11 +237,11 @@ function buildTree(
}
return tree;
}
case 3:
case 8: {
case Node.TEXT_NODE:
case Node.COMMENT_NODE: {
// text node or comment node
const el =
node.nodeType === 3
node.nodeType === Node.TEXT_NODE
? document.createTextNode(node.textContent!)
: document.createComment(node.textContent!);
return {
@@ -241,6 +251,7 @@ function buildTree(
el,
info: [],
refN: 0,
currentNS: null,
};
}
}
+4
View File
@@ -497,6 +497,10 @@ export class CodeGenerator {
}
// attributes
const attrs: { [key: string]: string } = {};
if (ast.ns) {
// specific namespace uri
attrs["block-ns"] = ast.ns;
}
for (let key in ast.attrs) {
if (key.startsWith("t-attf")) {
let expr = interpolate(ast.attrs[key]);
+12 -9
View File
@@ -49,6 +49,7 @@ export interface ASTDomNode {
shouldTrim: boolean;
shouldNumberize: boolean;
} | null;
ns: string | null;
}
export interface ASTMulti {
@@ -171,11 +172,12 @@ export type AST =
// -----------------------------------------------------------------------------
interface ParsingContext {
inPreTag: boolean;
inSVG: boolean;
}
export function parse(xml: string | Node): AST {
const node = xml instanceof Element ? xml : parseXML(`<t>${xml}</t>`).firstChild!;
const ctx = { inPreTag: false };
const ctx = { inPreTag: false, inSVG: false };
const ast = parseNode(node, ctx);
if (!ast) {
return { type: ASTType.Text, value: "" };
@@ -240,7 +242,7 @@ const lineBreakRE = /[\r\n]/;
const whitespaceRE = /\s+/g;
function parseTextCommentNode(node: ChildNode, ctx: ParsingContext): AST | null {
if (node.nodeType === 3) {
if (node.nodeType === Node.TEXT_NODE) {
let value = node.textContent || "";
if (!ctx.inPreTag) {
if (lineBreakRE.test(value) && !value.trim()) {
@@ -250,7 +252,7 @@ function parseTextCommentNode(node: ChildNode, ctx: ParsingContext): AST | null
}
return { type: ASTType.Text, value };
} else if (node.nodeType === 8) {
} else if (node.nodeType === Node.COMMENT_NODE) {
return { type: ASTType.Comment, value: node.textContent || "" };
}
return null;
@@ -289,18 +291,18 @@ const hasBracketsAtTheEnd = /\[[^\[]+\]\s*$/;
function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
const { tagName } = node;
let dynamicTag = null;
if (node.hasAttribute("t-tag")) {
dynamicTag = node.getAttribute("t-tag");
node.removeAttribute("t-tag");
}
const dynamicTag = node.getAttribute("t-tag");
node.removeAttribute("t-tag");
if (tagName === "t" && !dynamicTag) {
return null;
}
const children: AST[] = [];
if (tagName === "pre") {
ctx = { inPreTag: true };
ctx.inPreTag = true;
}
const shouldAddSVGNS = tagName === "svg" || (tagName === "g" && !ctx.inSVG);
ctx.inSVG = ctx.inSVG || shouldAddSVGNS;
const ns = shouldAddSVGNS ? "http://www.w3.org/2000/svg" : null;
const ref = node.getAttribute("t-ref");
node.removeAttribute("t-ref");
@@ -381,6 +383,7 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
ref,
content: children,
model,
ns,
};
}