From 70dbc7a6e9a7f6d55aeb4e10e8e686b186e6cdf3 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 25 Apr 2024 16:20:59 +0000 Subject: [PATCH] fix(@angular/build): emit error for invalid self-closing element in index HTML When an invalid self-closing HTML element is used in the index.html file, the build proceeds without raising an error, potentially leading to runtime issues. Now, when an invalid self-closing element is encountered in the index.html file, the build process issues an error, providing developers with immediate feedback to correct the issue. Closes: #27528 --- .../utils/index-file/augment-index-html.ts | 27 +++++++++++++- .../index-file/augment-index-html_spec.ts | 36 ++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/angular/build/src/utils/index-file/augment-index-html.ts b/packages/angular/build/src/utils/index-file/augment-index-html.ts index 4396f18f92f6..4c9f5fe16918 100644 --- a/packages/angular/build/src/utils/index-file/augment-index-html.ts +++ b/packages/angular/build/src/utils/index-file/augment-index-html.ts @@ -48,6 +48,25 @@ export interface FileInfo { name?: string; extension: string; } + +/** A list of valid self closing HTML elements */ +const VALID_SELF_CLOSING_TAGS = new Set([ + 'area', + 'base', + 'br', + 'col', + 'embed', + 'hr', + 'img', + 'input', + 'link', + 'meta', + 'param', + 'source', + 'track', + 'wbr', +]); + /* * Helper function used by the IndexHtmlWebpackPlugin. * Can also be directly used by builder, e. g. in order to generate an index.html @@ -190,7 +209,7 @@ export async function augmentIndexHtml( const foundPreconnects = new Set(); rewriter - .on('startTag', (tag) => { + .on('startTag', (tag, rawTagHtml) => { switch (tag.tagName) { case 'html': // Adjust document locale if specified @@ -225,6 +244,12 @@ export async function augmentIndexHtml( } } break; + default: + if (tag.selfClosing && !VALID_SELF_CLOSING_TAGS.has(tag.tagName)) { + errors.push(`Invalid self-closing element in index HTML file: '${rawTagHtml}'.`); + + return; + } } rewriter.emitStartTag(tag); diff --git a/packages/angular/build/src/utils/index-file/augment-index-html_spec.ts b/packages/angular/build/src/utils/index-file/augment-index-html_spec.ts index 4203b7f3cb3c..c484e7364b17 100644 --- a/packages/angular/build/src/utils/index-file/augment-index-html_spec.ts +++ b/packages/angular/build/src/utils/index-file/augment-index-html_spec.ts @@ -481,7 +481,7 @@ describe('augment-index-html', () => { it('should add image preconnects if it encounters preconnect elements for other resources', async () => { const imageDomains = ['https://www.example2.com', 'https://www.example3.com']; - const { content, warnings } = await augmentIndexHtml({ + const { content } = await augmentIndexHtml({ ...indexGeneratorOptions, html: '', imageDomains, @@ -500,4 +500,38 @@ describe('augment-index-html', () => { `); }); + + describe('self-closing tags', () => { + it('should return an error when used on a not supported element', async () => { + const { errors } = await augmentIndexHtml({ + ...indexGeneratorOptions, + html: ` + + + + + ' + `, + }); + + expect(errors.length).toEqual(1); + expect(errors).toEqual([`Invalid self-closing element in index HTML file: ''.`]); + }); + + it('should not return an error when used on a supported element', async () => { + const { errors } = await augmentIndexHtml({ + ...indexGeneratorOptions, + html: ` + + +
+ + + ' + `, + }); + + expect(errors.length).toEqual(0); + }); + }); });