Skip to content

Commit 5d29255

Browse files
dwirzDominique Wirz
and
Dominique Wirz
authored
fix: correctly handle svg class attribute within parseClassList (#6085)
* fix: handle svg class whithin * add test --------- Co-authored-by: Dominique Wirz <dominique@smartive.ch>
1 parent af102ce commit 5d29255

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

src/runtime/vdom/set-accessor.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,18 @@ const parseClassListRegex = /\s/;
198198
* @param value className string, e.g. "foo bar baz"
199199
* @returns list of classes, e.g. ["foo", "bar", "baz"]
200200
*/
201-
const parseClassList = (value: string | undefined | null): string[] => (!value ? [] : value.split(parseClassListRegex));
201+
const parseClassList = (value: string | SVGAnimatedString | undefined | null): string[] => {
202+
// Can't use `value instanceof SVGAnimatedString` because it'll break in non-browser environments
203+
// see https://developer.mozilla.org/docs/Web/API/SVGAnimatedString for more information
204+
if (typeof value === 'object' && 'baseVal' in value) {
205+
value = value.baseVal;
206+
}
207+
208+
if (!value) {
209+
return [];
210+
}
211+
212+
return value.split(parseClassListRegex);
213+
};
202214
const CAPTURE_EVENT_SUFFIX = 'Capture';
203215
const CAPTURE_EVENT_REGEX = new RegExp(CAPTURE_EVENT_SUFFIX + '$');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// @ts-ignore may not be existing when project hasn't been built
2+
type HydrateModule = typeof import('../../hydrate');
3+
let renderToString: HydrateModule['renderToString'];
4+
5+
describe('custom svg element', function () {
6+
let originalConsoleError: typeof console.error;
7+
before(async () => {
8+
// @ts-ignore may not be existing when project hasn't been built
9+
const mod = await import('/hydrate/index.mjs');
10+
renderToString = mod.renderToString;
11+
originalConsoleError = console.error;
12+
});
13+
14+
after(() => {
15+
console.error = originalConsoleError;
16+
});
17+
18+
it('should render without errors', async () => {
19+
const errorLogs: string[] = [];
20+
console.error = (message) => errorLogs.push(message);
21+
22+
const { html } = await renderToString(`<custom-svg-element />`, { prettyHtml: true });
23+
const stage = document.createElement('div');
24+
stage.setAttribute('id', 'stage');
25+
stage.setHTMLUnsafe(html);
26+
document.body.appendChild(stage);
27+
28+
await expect($('custom-svg-element')).toHaveText('');
29+
30+
expect(errorLogs.length).toEqual(0);
31+
});
32+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Component, h } from '@stencil/core';
2+
3+
@Component({
4+
tag: 'custom-svg-element',
5+
shadow: true,
6+
})
7+
export class CustomSvgElement {
8+
render() {
9+
return (
10+
<svg viewBox="0 0 54 54">
11+
<circle cx="8" cy="18" width="54" height="8" r="2" />
12+
</svg>
13+
);
14+
}
15+
}

0 commit comments

Comments
 (0)