@@ -9,7 +9,12 @@ import type {
99} from 'rollup'
1010import MagicString from 'magic-string'
1111import colors from 'picocolors'
12- import type { DefaultTreeAdapterMap , ParserError , Token } from 'parse5'
12+ import type {
13+ DefaultTreeAdapterMap ,
14+ ErrorCodes ,
15+ ParserError ,
16+ Token ,
17+ } from 'parse5'
1318import { stripLiteral } from 'strip-literal'
1419import escapeHtml from 'escape-html'
1520import type { MinimalPluginContextWithoutEnvironment , Plugin } from '../plugin'
@@ -34,6 +39,7 @@ import { resolveEnvPrefix } from '../env'
3439import { cleanUrl } from '../../shared/utils'
3540import { perEnvironmentState } from '../environment'
3641import { getNodeAssetAttributes } from '../assetSource'
42+ import type { Logger } from '../logger'
3743import {
3844 assetUrlRE ,
3945 getPublicAssetFilename ,
@@ -184,21 +190,29 @@ function traverseNodes(
184190 }
185191}
186192
193+ type ParseWarnings = Partial < Record < ErrorCodes , string > >
194+
187195export async function traverseHtml (
188196 html : string ,
189197 filePath : string ,
198+ warn : Logger [ 'warn' ] ,
190199 visitor : ( node : DefaultTreeAdapterMap [ 'node' ] ) => void ,
191200) : Promise < void > {
192201 // lazy load compiler
193202 const { parse } = await import ( 'parse5' )
203+ const warnings : ParseWarnings = { }
194204 const ast = parse ( html , {
195205 scriptingEnabled : false , // parse inside <noscript>
196206 sourceCodeLocationInfo : true ,
197207 onParseError : ( e : ParserError ) => {
198- handleParseError ( e , html , filePath )
208+ handleParseError ( e , html , filePath , warnings )
199209 } ,
200210 } )
201211 traverseNodes ( ast , visitor )
212+
213+ for ( const message of Object . values ( warnings ) ) {
214+ warn ( colors . yellow ( `\n${ message } ` ) )
215+ }
202216}
203217
204218export function getScriptInfo ( node : DefaultTreeAdapterMap [ 'element' ] ) : {
@@ -297,6 +311,7 @@ function handleParseError(
297311 parserError : ParserError ,
298312 html : string ,
299313 filePath : string ,
314+ warnings : ParseWarnings ,
300315) {
301316 switch ( parserError . code ) {
302317 case 'missing-doctype' :
@@ -318,11 +333,10 @@ function handleParseError(
318333 return
319334 }
320335 const parseError = formatParseError ( parserError , filePath , html )
321- throw new Error (
336+ warnings [ parseError . code ] ??=
322337 `Unable to parse HTML; ${ parseError . message } \n` +
323- ` at ${ parseError . loc . file } :${ parseError . loc . line } :${ parseError . loc . column } \n` +
324- `${ parseError . frame } ` ,
325- )
338+ ` at ${ parseError . loc . file } :${ parseError . loc . line } :${ parseError . loc . column } \n` +
339+ `${ parseError . frame . length > 300 ? '[this code frame is omitted as the content was too long] ' : parseError . frame } `
326340}
327341
328342/**
@@ -442,7 +456,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
442456 }
443457
444458 const setModuleSideEffectPromises : Promise < void > [ ] = [ ]
445- await traverseHtml ( html , id , ( node ) => {
459+ await traverseHtml ( html , id , config . logger . warn , ( node ) => {
446460 if ( ! nodeIsElement ( node ) ) {
447461 return
448462 }
@@ -1238,7 +1252,7 @@ export function injectNonceAttributeTagHook(
12381252
12391253 const s = new MagicString ( html )
12401254
1241- await traverseHtml ( html , filename , ( node ) => {
1255+ await traverseHtml ( html , filename , config . logger . warn , ( node ) => {
12421256 if ( ! nodeIsElement ( node ) ) {
12431257 return
12441258 }
0 commit comments