Repository: vitejs/vite
File: packages/vite/src/node/plugins/html.ts (TypeScript)

Code before:
      return
    case 'duplicate-attribute':
      // Accept duplicate attributes #5966
      // The first attribute is used, browsers silently ignore duplicates
      return
    case 'non-void-html-element-start-tag-with-trailing-solidus':
      // Allow self closing on non-void elements #10439
      return
    case 'unexpected-question-mark-instead-of-tag-name':
      // Allow <?xml> declaration and <?> empty elements
      // lit generates <?>: https://github.com/lit/lit/issues/2470
      return
  }
  fileErrorInfo[filePath] ??= {}
  if (fileErrorInfo[filePath][parserError.code]) {
    // already warned about this error
    return
  }
  fileErrorInfo[filePath][parserError.code] = true
  const parseError = formatParseError(parserError, filePath, html)

  warn(
    colors.yellow(
      `Unable to parse HTML; ${parseError.message}\n` +
        ` at ${parseError.loc.file}:${parseError.loc.line}:${parseError.loc.column}\n` +
        `${parseError.frame.length > 300 ? '[this line is omitted as the content was too long] ' : parseError.frame}`,
    ),
  )
}

/**
 * Compiles index.html into an entry js module
 */
export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
  const [preHooks, normalHooks, postHooks] = resolveHtmlTransforms(
    config.plugins,
  )
  preHooks.unshift(injectCspNonceMetaTagHook(config))
  preHooks.unshift(preImportMapHook(config))
  preHooks.push(htmlEnvHook(config))
  postHooks.push(injectNonceAttributeTagHook(config))
  postHooks.push(postImportMapHook())
  const processedHtml = perEnvironmentState(() => new Map<string, string>())

  const isExcludedUrl = (url: string) =>
    url[0] === '#' || isExternalUrl(url) || isDataUrl(url)

  // Same reason with `htmlInlineProxyPlugin`
  isAsyncScriptMap.set(config, new Map())

  return {

Review comment (refactor):
Since we are omitting the whole code frame instead of a specific line.
```suggestion
        `${parseError.frame.length > 300 ? '[this code frame is omitted as the content was too long] ' : parseError.frame}`,
```

Code after:
function handleParseError(
  parserError: ParserError,
  html: string,
  filePath: string,
  warnings: ParseWarnings,
) {
  switch (parserError.code) {
    case 'missing-doctype':
      // ignore missing DOCTYPE
      return
    case 'abandoned-head-element-child':
      // Accept elements without closing tag in <head>
      return
    case 'duplicate-attribute':
      // Accept duplicate attributes #5966
      // The first attribute is used, browsers silently ignore duplicates
      return
    case 'non-void-html-element-start-tag-with-trailing-solidus':
      // Allow self closing on non-void elements #10439
      return
    case 'unexpected-question-mark-instead-of-tag-name':
      // Allow <?xml> declaration and <?> empty elements
      // lit generates <?>: https://github.com/lit/lit/issues/2470
      return
  }
  const parseError = formatParseError(parserError, filePath, html)
  warnings[parseError.code] ??=
    `Unable to parse HTML; ${parseError.message}\n` +
    ` at ${parseError.loc.file}:${parseError.loc.line}:${parseError.loc.column}\n` +
    `${parseError.frame.length > 300 ? '[this code frame is omitted as the content was too long] ' : parseError.frame}`
}

/**
 * Compiles index.html into an entry js module
 */
export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
  const [preHooks, normalHooks, postHooks] = resolveHtmlTransforms(
    config.plugins,
  )
  preHooks.unshift(injectCspNonceMetaTagHook(config))
  preHooks.unshift(preImportMapHook(config))
  preHooks.push(htmlEnvHook(config))
  postHooks.push(injectNonceAttributeTagHook(config))
  postHooks.push(postImportMapHook())
  const processedHtml = perEnvironmentState(() => new Map<string, string>())

  const isExcludedUrl = (url: string) =>
    url[0] === '#' || isExternalUrl(url) || isDataUrl(url)

  // Same reason with `htmlInlineProxyPlugin`
  isAsyncScriptMap.set(config, new Map())