Skip to content

Commit 6fb64c9

Browse files
navoritedummdidumm
andauthored
fix: improve namespace inference when having {@render} and {@html} tags (#10631)
* fix: treat snippets like normal components when inferring namespace * n * simplify * better desc * slight adjustment * feedback Co-authored-by: Simon H <[email protected]> * feedback Co-authored-by: Simon H <[email protected]> * skip html tag * test * changeset name * cleanup --------- Co-authored-by: Simon H <[email protected]>
1 parent 767b5a8 commit 6fb64c9

File tree

4 files changed

+60
-49
lines changed

4 files changed

+60
-49
lines changed

.changeset/giant-planets-shake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: improve namespace inference when having `{@render}` and `{@html}` tags

packages/svelte/src/compiler/phases/3-transform/utils.js

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
regex_whitespaces_strict
66
} from '../patterns.js';
77
import * as b from '../../utils/builders.js';
8+
import { walk } from 'zimmerframe';
89

910
/**
1011
* @param {string} s
@@ -249,51 +250,49 @@ export function infer_namespace(namespace, parent, nodes, path) {
249250
* @param {import('#compiler').Namespace | 'keep' | 'maybe_html'} namespace
250251
*/
251252
function check_nodes_for_namespace(nodes, namespace) {
253+
/**
254+
* @param {import('#compiler').SvelteElement | import('#compiler').RegularElement} node}
255+
* @param {{stop: () => void}} context
256+
*/
257+
const RegularElement = (node, { stop }) => {
258+
if (!node.metadata.svg) {
259+
namespace = 'html';
260+
stop();
261+
} else if (namespace === 'keep') {
262+
namespace = 'svg';
263+
}
264+
};
265+
252266
for (const node of nodes) {
253-
if (node.type === 'RegularElement' || node.type === 'SvelteElement') {
254-
if (!node.metadata.svg) {
255-
namespace = 'html';
256-
break;
257-
} else if (namespace === 'keep') {
258-
namespace = 'svg';
259-
}
260-
} else if (
261-
(node.type === 'Text' && node.data.trim() !== '') ||
262-
node.type === 'HtmlTag' ||
263-
node.type === 'RenderTag'
264-
) {
265-
namespace = 'maybe_html';
266-
} else if (node.type === 'EachBlock') {
267-
namespace = check_nodes_for_namespace(node.body.nodes, namespace);
268-
if (namespace === 'html') break;
269-
if (node.fallback) {
270-
namespace = check_nodes_for_namespace(node.fallback.nodes, namespace);
271-
if (namespace === 'html') break;
272-
}
273-
} else if (node.type === 'IfBlock') {
274-
namespace = check_nodes_for_namespace(node.consequent.nodes, namespace);
275-
if (namespace === 'html') break;
276-
if (node.alternate) {
277-
namespace = check_nodes_for_namespace(node.alternate.nodes, namespace);
278-
if (namespace === 'html') break;
279-
}
280-
} else if (node.type === 'AwaitBlock') {
281-
if (node.pending) {
282-
namespace = check_nodes_for_namespace(node.pending.nodes, namespace);
283-
if (namespace === 'html') break;
267+
walk(
268+
node,
269+
{},
270+
{
271+
_(node, { next }) {
272+
if (
273+
node.type === 'EachBlock' ||
274+
node.type === 'IfBlock' ||
275+
node.type === 'AwaitBlock' ||
276+
node.type === 'Fragment' ||
277+
node.type === 'KeyBlock' ||
278+
node.type === 'RegularElement' ||
279+
node.type === 'SvelteElement' ||
280+
node.type === 'Text'
281+
) {
282+
next();
283+
}
284+
},
285+
SvelteElement: RegularElement,
286+
RegularElement,
287+
Text(node) {
288+
if (node.data.trim() !== '') {
289+
namespace = 'maybe_html';
290+
}
291+
}
284292
}
285-
if (node.then) {
286-
namespace = check_nodes_for_namespace(node.then.nodes, namespace);
287-
if (namespace === 'html') break;
288-
}
289-
if (node.catch) {
290-
namespace = check_nodes_for_namespace(node.catch.nodes, namespace);
291-
if (namespace === 'html') break;
292-
}
293-
} else if (node.type === 'KeyBlock') {
294-
namespace = check_nodes_for_namespace(node.fragment.nodes, namespace);
295-
if (namespace === 'html') break;
296-
}
293+
);
294+
295+
if (namespace === 'html') return namespace;
297296
}
298297

299298
return namespace;

packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/Wrapper.svelte

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22

33
{#if true}
44
<text x="0" y="26">true</text>
5-
{:else}
6-
<text x="0" y="26">false</text>
75
{/if}
86

9-
{#each Array(3).fill(0) as item, idx}
7+
{#each Array(2).fill(0) as item, idx}
108
<text x={idx * 10} y={42}>{idx}</text>
119
{/each}
1210

13-
<!-- comment should not set infer html namespace -->
11+
{@html '<text x="0" y="40">html</text>'}
12+
13+
{@render test("snippet")}
14+
15+
{#snippet test(text)}
16+
<text x={20} y={42}>{text}</text>
17+
{/snippet}
18+
19+
<!-- comment should not infer html namespace -->

packages/svelte/tests/runtime-runes/samples/svg-namespace-infer/_config.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export default test({
77
<text x="0" y="26">true</text>
88
<text x="0" y="42">0</text>
99
<text x="10" y="42">1</text>
10-
<text x="20" y="42">2</text>
10+
<text x="0" y="40">html</text>
11+
<text x="20" y="42">snippet</text>
1112
</svg>
1213
`,
1314
test({ assert, target }) {
@@ -18,7 +19,7 @@ export default test({
1819

1920
const text_elements = target.querySelectorAll('text');
2021

21-
assert.equal(text_elements.length, 5);
22+
assert.equal(text_elements.length, 6);
2223

2324
for (const { namespaceURI } of text_elements)
2425
assert.equal(namespaceURI, 'http://www.w3.org/2000/svg');

0 commit comments

Comments
 (0)