diff --git a/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts b/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts index 1315f1e1444..7810d8f099f 100644 --- a/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts @@ -1,8 +1,10 @@ +import { namespaces } from './../../../utils/namespaces'; import { b, x } from 'code-red'; import Renderer from '../Renderer'; import Block from '../Block'; import Tag from './shared/Tag'; import Wrapper from './shared/Wrapper'; +import Element from '../../nodes/Element'; import MustacheTag from '../../nodes/MustacheTag'; import RawMustacheTag from '../../nodes/RawMustacheTag'; import { is_head } from './shared/is_head'; @@ -51,9 +53,12 @@ export default class RawMustacheTagWrapper extends Tag { const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null'; - block.chunks.create.push(b`${html_tag} = new @HtmlTag();`); + const parent_element = this.node.find_nearest(/^Element/) as Element; + const is_svg = parent_element && parent_element.namespace === namespaces.svg; + block.chunks.create.push(b`${html_tag} = new @HtmlTag(${is_svg ? 'true' : 'false'});`); + if (this.renderer.options.hydratable) { - block.chunks.claim.push(b`${html_tag} = @claim_html_tag(${_parent_nodes});`); + block.chunks.claim.push(b`${html_tag} = @claim_html_tag(${_parent_nodes}, ${is_svg ? 'true' : 'false'});`); } block.chunks.hydrate.push(b`${html_tag}.a = ${update_anchor};`); block.chunks.mount.push(b`${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`); diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index e2a74202360..cadc1abbaaf 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -492,12 +492,13 @@ function find_comment(nodes, text, start) { return nodes.length; } -export function claim_html_tag(nodes) { + +export function claim_html_tag(nodes, is_svg: boolean) { // find html opening tag const start_index = find_comment(nodes, 'HTML_TAG_START', 0); const end_index = find_comment(nodes, 'HTML_TAG_END', start_index); if (start_index === end_index) { - return new HtmlTagHydration(); + return new HtmlTagHydration(undefined, is_svg); } init_claim_info(nodes); @@ -509,7 +510,7 @@ export function claim_html_tag(nodes) { n.claim_order = nodes.claim_info.total_claimed; nodes.claim_info.total_claimed += 1; } - return new HtmlTagHydration(claimed_nodes); + return new HtmlTagHydration(claimed_nodes, is_svg); } export function set_data(text, data) { @@ -645,16 +646,18 @@ export function query_selector_all(selector: string, parent: HTMLElement = docum } export class HtmlTag { + private is_svg = false; // parent for creating node - e: HTMLElement; + e: HTMLElement | SVGElement; // html tag nodes n: ChildNode[]; // target - t: HTMLElement; + t: HTMLElement | SVGElement; // anchor - a: HTMLElement; + a: HTMLElement | SVGElement; - constructor() { + constructor(is_svg: boolean = false) { + this.is_svg = is_svg; this.e = this.n = null; } @@ -662,9 +665,14 @@ export class HtmlTag { this.h(html); } - m(html: string, target: HTMLElement, anchor: HTMLElement = null) { + m( + html: string, + target: HTMLElement | SVGElement, + anchor: HTMLElement | SVGElement = null + ) { if (!this.e) { - this.e = element(target.nodeName as keyof HTMLElementTagNameMap); + if (this.is_svg) this.e = svg_element(target.nodeName as keyof SVGElementTagNameMap); + else this.e = element(target.nodeName as keyof HTMLElementTagNameMap); this.t = target; this.c(html); } @@ -698,8 +706,8 @@ export class HtmlTagHydration extends HtmlTag { // hydration claimed nodes l: ChildNode[] | void; - constructor(claimed_nodes?: ChildNode[]) { - super(); + constructor(claimed_nodes?: ChildNode[], is_svg: boolean = false) { + super(is_svg); this.e = this.n = null; this.l = claimed_nodes; } diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js index 19947edbbb2..e91f77ecd84 100644 --- a/test/js/samples/each-block-changed-check/expected.js +++ b/test/js/samples/each-block-changed-check/expected.js @@ -52,7 +52,7 @@ function create_each_block(ctx) { t4 = text(t4_value); t5 = text(" ago:"); t6 = space(); - html_tag = new HtmlTag(); + html_tag = new HtmlTag(false); attr(span, "class", "meta"); html_tag.a = null; attr(div, "class", "comment"); @@ -170,4 +170,4 @@ class Component extends SvelteComponent { } } -export default Component; \ No newline at end of file +export default Component; diff --git a/test/runtime/samples/svg-html-tag/_config.js b/test/runtime/samples/svg-html-tag/_config.js new file mode 100644 index 00000000000..f35bfc21d5d --- /dev/null +++ b/test/runtime/samples/svg-html-tag/_config.js @@ -0,0 +1,35 @@ +export default { + html: ` + + + + + `, + test({ assert, target, component }) { + + let svg = target.querySelector('svg'); + let circles = target.querySelectorAll('circle'); + assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(2, circles.length); + assert.equal(circles[0].namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(circles[1].namespaceURI, 'http://www.w3.org/2000/svg'); + + component.width = 200; + component.height = 120; + assert.htmlEqual( + target.innerHTML, + ` + + + + + ` + ); + svg = target.querySelector('svg'); + circles = target.querySelectorAll('circle'); + assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(2, circles.length); + assert.equal(circles[0].namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(circles[1].namespaceURI, 'http://www.w3.org/2000/svg'); + } +}; diff --git a/test/runtime/samples/svg-html-tag/main.svelte b/test/runtime/samples/svg-html-tag/main.svelte new file mode 100644 index 00000000000..dfeb6b04d32 --- /dev/null +++ b/test/runtime/samples/svg-html-tag/main.svelte @@ -0,0 +1,10 @@ + + + + {@html circle} + + diff --git a/test/runtime/samples/svg-html-tag2/_config.js b/test/runtime/samples/svg-html-tag2/_config.js new file mode 100644 index 00000000000..3c07cd74999 --- /dev/null +++ b/test/runtime/samples/svg-html-tag2/_config.js @@ -0,0 +1,39 @@ +export default { + html: ` + + + + + + + `, + test({ assert, target, component }) { + + let svg = target.querySelector('svg'); + let circles = target.querySelectorAll('circle'); + assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(2, circles.length); + assert.equal(circles[0].namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(circles[1].namespaceURI, 'http://www.w3.org/2000/svg'); + + component.width = 200; + component.height = 120; + assert.htmlEqual( + target.innerHTML, + ` + + + + + + + ` + ); + svg = target.querySelector('svg'); + circles = target.querySelectorAll('circle'); + assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(2, circles.length); + assert.equal(circles[0].namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(circles[1].namespaceURI, 'http://www.w3.org/2000/svg'); + } +}; diff --git a/test/runtime/samples/svg-html-tag2/main.svelte b/test/runtime/samples/svg-html-tag2/main.svelte new file mode 100644 index 00000000000..d8192955d97 --- /dev/null +++ b/test/runtime/samples/svg-html-tag2/main.svelte @@ -0,0 +1,12 @@ + + + + + {@html circle} + + + diff --git a/test/runtime/samples/svg-html-tag3/_config.js b/test/runtime/samples/svg-html-tag3/_config.js new file mode 100644 index 00000000000..1209d298fed --- /dev/null +++ b/test/runtime/samples/svg-html-tag3/_config.js @@ -0,0 +1,33 @@ +export default { + html: ` + + + + + + `, + test({ assert, target, component }) { + + let svg = target.querySelector('svg'); + let circle = target.querySelector('circle'); + assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(circle.namespaceURI, 'http://www.w3.org/1999/xhtml'); + + component.width = 200; + component.height = 120; + assert.htmlEqual( + target.innerHTML, + ` + + + + + + ` + ); + svg = target.querySelector('svg'); + circle = target.querySelector('circle'); + assert.equal(svg.namespaceURI, 'http://www.w3.org/2000/svg'); + assert.equal(circle.namespaceURI, 'http://www.w3.org/1999/xhtml'); + } +}; diff --git a/test/runtime/samples/svg-html-tag3/main.svelte b/test/runtime/samples/svg-html-tag3/main.svelte new file mode 100644 index 00000000000..86dbb5aa7af --- /dev/null +++ b/test/runtime/samples/svg-html-tag3/main.svelte @@ -0,0 +1,11 @@ + + + + + {@html circle} + +