🐛 BUG: Formatting failed when there is a React component after a html comment.
Describe the Bug
2025-04-13T09:00:20.17513+08:00 [ERROR] [project.format.local.prettier]: failed, reason: Err(prettier at "/Workspace/Personal/React/react-astro" failed to format buffer
Caused by: error during message '{"jsonrpc":"2.0","id":3,"method":"prettier/format","params":{"text":"..snip..","options":{"plugins":["/Workspace/React/react-astro/node_modules/prettier-plugin-astro/dist/index.js"],"parser":null,"filepath":"/Workspace/React/react-astro/src/components/Header.astro","prettierOptions":null,"ignorePath":"/Workspace/React/react-astro/.prettierignore"}}}' handling: SyntaxError: Unexpected token (4:18) 2 |
4 | | ^ 5 |
my prettier.config.js
/** @type {import("prettier").Config} */
export default { plugins: ["prettier-plugin-astro"], overrides: [ { files: "*.astro", options: { parser: "astro", }, }, ], trailingComma: "es5", printWidth: 80, tabWidth: 2, semi: true, singleQuote: false, };
my .prettierignore
Ignore artifacts:
build coverage
Ignore all HTML files:
*.html
**/.git **/.svn **/.hg **/node_modules **/public **/dist
**/.vercel
**/-lock.json **/-lock.yaml
my eslint.config.js
export default defineConfig([ ... eslint.configs.recommended, tseslint.configs.strict, tseslint.configs.stylistic, eslintPluginAstro.configs.recommended, eslintConfigPrettier ... ])
Steps to Reproduce
Write a comment after a React component in an Astro file. Then format.
HTML comments in JSX expressions cause formatting to fail
Suspected Problem
Formatting .astro files fails when HTML comment syntax (<!-- comment -->) is used inside JSX expressions. The astroExpressionParser wraps expressions in <>{} and passes them to babel-ts, but HTML-style comments inside expressions cause Babel to throw a syntax error.
Reproduction
File: test.astro
---
const items = [1, 2, 3];
---
{items.map(item => (
<div>
<!-- This comment breaks prettier formatting -->
<p>{item}</p>
</div>
))}
Error:
SyntaxError: Unexpected token (3:16)
> 3 | <!-- This comment breaks prettier formatting -->
| ^
Workaround
Use JSX-style comments instead: {/* comment */}
Root Cause
-
The Astro compiler is more lenient than standard JSX parsers and allows HTML-style comments (
<!--) even inside JSX expression contexts. This is why the code compiles and runs successfully. -
However, prettier-plugin-astro uses
babel-tsto parse expressions, and babel-ts (being a strict JSX parser) does not allow HTML comments inside JSX contexts.
In src/index.ts, the astroExpressionParser.preprocess() function wraps expression content in JSX without transforming HTML comments:
preprocess(text) {
return `<>{${text}\n}</>`; // HTML comments inside text will break Babel
},
Proposed Solution
Transform HTML comments to JSX comments before passing to Babel:
preprocess(text) {
// Transform HTML comments to JSX comments
const transformed = text.replace(/<!--([\s\S]*?)-->/g, '{/*$1*/}');
return `<>{${transformed}\n}</>`;
},
Environment
prettier: 3.6.2prettier-plugin-astro: 0.14.1- Editor: Zed
This seems to be confirmed by the fact that using the proposed configuration and changing the default parser, solves the commenting issue as well.
// .prettierrc.mjs
/** @type {import("prettier").Config} */
export default {
plugins: ['prettier-plugin-astro'],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
],
};
This also affects CSS styles, I had to switch to set:text={``} :/