fix(compiler): prevent namespaced SVG <style> elements from being stripped

Updates the template preparser to exclude namespaced SVG style tags (':svg:style') from the style elements set.

Previously, ':svg:style' elements were incorrectly classified as PreparsedElementType.STYLE, which caused them to be completely stripped from the final template DOM tree during the Render3 template transform and pushed into standard component stylesheets. By limiting the style element parsing to standard 'style' tags, namespaced SVG style tags remain safely in the template AST as normal DOM elements, preserving local SVG styling.

Closes #68977

(cherry picked from commit ec138c3645)
This commit is contained in:
Alan Agius
2026-05-28 08:39:55 +00:00
committed by Pawel Kozlowski
parent 8538bdce1c
commit eb1cbbf2eb
2 changed files with 11 additions and 3 deletions
@@ -14,7 +14,7 @@ const LINK_ELEMENT = 'link';
const LINK_STYLE_REL_ATTR = 'rel';
const LINK_STYLE_HREF_ATTR = 'href';
const LINK_STYLE_REL_VALUE = 'stylesheet';
const STYLE_ELEMENTS: ReadonlySet<string> = new Set([':svg:style', 'style']);
const STYLE_ELEMENT = 'style';
const SCRIPT_ELEMENTS: ReadonlySet<string> = new Set([':svg:script', 'script']);
const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
const NG_PROJECT_AS = 'ngProjectAs';
@@ -50,7 +50,7 @@ export function preparseElement(ast: html.Element): PreparsedElement {
let type = PreparsedElementType.OTHER;
if (isNgContent(nodeName)) {
type = PreparsedElementType.NG_CONTENT;
} else if (STYLE_ELEMENTS.has(nodeName)) {
} else if (STYLE_ELEMENT === nodeName) {
type = PreparsedElementType.STYLE;
} else if (SCRIPT_ELEMENTS.has(nodeName)) {
type = PreparsedElementType.SCRIPT;
@@ -910,7 +910,7 @@ describe('R3 template transform', () => {
});
});
describe('Ignored elements', () => {
describe('<script> and <style> elements', () => {
it('should ignore <script> elements', () => {
expectFromHtml('<script></script>a').toEqual([['Text', 'a']]);
});
@@ -918,6 +918,14 @@ describe('R3 template transform', () => {
it('should ignore <style> elements', () => {
expectFromHtml('<style></style>a').toEqual([['Text', 'a']]);
});
it('should not ignore namespaced SVG <style> elements', () => {
expectFromHtml('<svg><style>.a { fill: none; }</style></svg>').toEqual([
['Element', ':svg:svg'],
['Element', ':svg:style'],
['Text', '.a { fill: none; }'],
]);
});
});
describe('<link rel="stylesheet">', () => {