prettier-plugin-astro icon indicating copy to clipboard operation
prettier-plugin-astro copied to clipboard

🐛 BUG: Formatting failed when there is a React component after a html comment.

Open Virgil-N opened this issue 8 months ago • 3 comments

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 |

3 | <LanguageSwitcher client:only="react" /> > 4 | | ^ 5 |
6 | )) 2025-04-13T09:00:20.175311+08:00 [ERROR] Formatting failed: prettier at "/Workspace/React/react-astro" failed to format buffer: 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 |
3 | <LanguageSwitcher client:only="react" />

4 | | ^ 5 |

6 | )

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.

Virgil-N avatar Apr 13 '25 01:04 Virgil-N

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

  1. 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.

  2. However, prettier-plugin-astro uses babel-ts to 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.2
  • prettier-plugin-astro: 0.14.1
  • Editor: Zed

jo-ced avatar Oct 06 '25 14:10 jo-ced

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',
      },
    },
  ],
};

jo-ced avatar Oct 06 '25 14:10 jo-ced

This also affects CSS styles, I had to switch to set:text={``} :/

stainless-em avatar Nov 04 '25 17:11 stainless-em