diff --git a/CHANGELOG.md b/CHANGELOG.md index 62920a2..2986bef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Fixed + +- Restore class sorting in Astro templates when using `prettier-plugin-astro` v1 ([#473](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/473)) ## [0.8.1] - 2026-07-15 diff --git a/package.json b/package.json index 38df433..d91e6e6 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "postcss": "^8.5.6", "postcss-import": "^16.1.1", "prettier": "^3.7.3", - "prettier-plugin-astro": "^0.14.1", + "prettier-plugin-astro": "^1.0.0", "prettier-plugin-css-order": "^2.1.2", "prettier-plugin-jsdoc": "^1.3.3", "prettier-plugin-marko": "^3.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5e3024..b99d019 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,8 +87,8 @@ importers: specifier: ^3.7.3 version: 3.9.6 prettier-plugin-astro: - specifier: ^0.14.1 - version: 0.14.1 + specifier: ^1.0.0 + version: 1.0.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(prettier@3.9.6) prettier-plugin-css-order: specifier: ^2.1.2 version: 2.2.0(postcss@8.5.26)(prettier@3.9.6) @@ -138,8 +138,70 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@astrojs/compiler@2.13.1': - resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==} + '@astrojs/compiler-binding-darwin-arm64@0.4.0': + resolution: {integrity: sha512-ZVUwHundaQyFNjE6uoa0usaC0WOCitDCLS/4mdb4rOiJXwVUuKJBMxI5WMzXLWmamsXtK/Z//ifLXvV5Yeh4Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@astrojs/compiler-binding-darwin-x64@0.4.0': + resolution: {integrity: sha512-FI6G8AY8u6fR1SI/QRR5yGMwtvZwP34CDmZpZ5HwJGa50UM1VISTLhqkhV4a476pmgd25X1Aur2dqw6hUnrlKA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@astrojs/compiler-binding-linux-arm64-gnu@0.4.0': + resolution: {integrity: sha512-lB9gLFJK7m82EnjaU8nlRBEfcwGNeHidW3sSjODTUjMNaoewVuUz9fwwdY5M4jiSXIqWLH3yl6TX8FTDKA74Sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@astrojs/compiler-binding-linux-arm64-musl@0.4.0': + resolution: {integrity: sha512-HPbvWqbxFxyaoQJhLxCaSjtYBx9KBo7JGVzEFZCmMl968a2PsSH0UfiODYgYPXofTOIsIH2aoCcrHXML0IA3ig==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-linux-x64-gnu@0.4.0': + resolution: {integrity: sha512-tQKolMxoJ/+0AmLWm1PmJ/i+z3i10ZU1bNuVjEDulCf48azEMtUNjTZgHJ5MPtpYRNc7dlETr8QujUfduzoC7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@astrojs/compiler-binding-linux-x64-musl@0.4.0': + resolution: {integrity: sha512-5v5YymudsxMHp3NBLCS8BUlu5CRqeLtWD9cKS/4nIhIEHCbpz9okmVV6I0HWqmBAPhWYcDa3vw/vltYPrOQCTA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-wasm32-wasi@0.4.0': + resolution: {integrity: sha512-m/phuH3x3PREvv1OnkM44NoPh4MatUadix1fB1u5SvMLCyDTUZykDJbKnWf1cjnYmHdlB8HcjTjl6JrCqAIXcw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@astrojs/compiler-binding-win32-arm64-msvc@0.4.0': + resolution: {integrity: sha512-B9zYf3okEY83kM8gydlpH2BHP00w4ifxPqlYlWrgTwuD6wnkrJDCwBlgy1q31cERjCJRXN1lrE2VmkLvFjv/6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@astrojs/compiler-binding-win32-x64-msvc@0.4.0': + resolution: {integrity: sha512-zB0Nrv0dGc0zZWPGDRmmETTPhDRqyZjAjk+gWMlVrJX5U89obpB3VUUE1ZiHxOCN5LQojeLK6O8L/dnoHolvNQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@astrojs/compiler-binding@0.4.0': + resolution: {integrity: sha512-x2RjDUuWfwLNtc3mjAdSRInwqh/rqbLar9cm/5FOMbHvmYZB7yfKewzSclAxWjIZsypJDXv1lhaP2WG+P8TK3g==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@astrojs/compiler-rs@0.4.0': + resolution: {integrity: sha512-koVikeon1kreEy+/JzLQRy3vzHHQVOjycs4degg4vFufKApZOwMZvSSAEztYNhmcQVfNVsVZZI4cEge3cexAbQ==} + engines: {node: '>=22.12.0'} '@augment-vir/assert@32.2.3': resolution: {integrity: sha512-JCG8pcDRovaOdugxEirioZGFYC1V5G1qEl9WDl4IQ5HJJMgXgCWGsDDfltRwFCRRTiIdZuK/061dB+qMNrjE0Q==} @@ -879,6 +941,9 @@ packages: resolution: {integrity: sha512-OqiFvSOF0dBSesELYY2CAMa4YINvlLpvKOz/rv6NeZEqiyttlHgv98Juwv4Ch+GrEV7IZ8jfI2VcEoYUjXXCjw==} hasBin: true + '@prettier/parse-srcset@3.1.0': + resolution: {integrity: sha512-FIRv2rZotO9NP/r66taYqD1zICpPiBbrECqjKV/xqNotqDxF7fLzzUeK+1RSRx9Tenk0DajR/GcRmTJ2qtHaKQ==} + '@prettier/plugin-hermes@0.1.3': resolution: {integrity: sha512-ok9xBeAKSBo5r5+wRkn+IRG8eGX1EcjsTmTn0VfKdRiSLE1OhyUSXQdXOEUs8a/VdpctGJ9GHTHyLVFcIMkccQ==} engines: {node: '>=14'} @@ -2181,9 +2246,11 @@ packages: resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} engines: {node: ^10 || ^12 || >=14} - prettier-plugin-astro@0.14.1: - resolution: {integrity: sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==} - engines: {node: ^14.15.0 || >=16.0.0} + prettier-plugin-astro@1.0.0: + resolution: {integrity: sha512-xOlwKNSaPkPPiJeOhiFk8/MA2eH5A+in99dID+weTJhPcq+FBdIaB/3UNFdy9ckmc8/bT7QNyxSb78cnopgElQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + prettier: ^3.5.3 prettier-plugin-css-order@2.2.0: resolution: {integrity: sha512-GCkwEgQ2roT7le+zpUFQThPDO4x5EXcZmY9Rj6rvO++I/nATTGBWdZdsooha/BlvIBbZclJzXsgJdlKWrys9+w==} @@ -2344,8 +2411,9 @@ packages: s.color@0.0.15: resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} - sass-formatter@0.7.9: - resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==} + sass-formatter@0.8.0: + resolution: {integrity: sha512-Nf4eMGE2O5vnJG7KPCRyksWS9gVKSYoUWtPeMXRRxwZSPVQhSGtL602xVYS65LvMkHmkvKa7xpauF0+/5pPwrg==} + hasBin: true self-closing-tags@1.0.1: resolution: {integrity: sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA==} @@ -2684,7 +2752,59 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@astrojs/compiler@2.13.1': {} + '@astrojs/compiler-binding-darwin-arm64@0.4.0': + optional: true + + '@astrojs/compiler-binding-darwin-x64@0.4.0': + optional: true + + '@astrojs/compiler-binding-linux-arm64-gnu@0.4.0': + optional: true + + '@astrojs/compiler-binding-linux-arm64-musl@0.4.0': + optional: true + + '@astrojs/compiler-binding-linux-x64-gnu@0.4.0': + optional: true + + '@astrojs/compiler-binding-linux-x64-musl@0.4.0': + optional: true + + '@astrojs/compiler-binding-wasm32-wasi@0.4.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@astrojs/compiler-binding-win32-arm64-msvc@0.4.0': + optional: true + + '@astrojs/compiler-binding-win32-x64-msvc@0.4.0': + optional: true + + '@astrojs/compiler-binding@0.4.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + optionalDependencies: + '@astrojs/compiler-binding-darwin-arm64': 0.4.0 + '@astrojs/compiler-binding-darwin-x64': 0.4.0 + '@astrojs/compiler-binding-linux-arm64-gnu': 0.4.0 + '@astrojs/compiler-binding-linux-arm64-musl': 0.4.0 + '@astrojs/compiler-binding-linux-x64-gnu': 0.4.0 + '@astrojs/compiler-binding-linux-x64-musl': 0.4.0 + '@astrojs/compiler-binding-wasm32-wasi': 0.4.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@astrojs/compiler-binding-win32-arm64-msvc': 0.4.0 + '@astrojs/compiler-binding-win32-x64-msvc': 0.4.0 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@astrojs/compiler-rs@0.4.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@astrojs/compiler-binding': 0.4.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' '@augment-vir/assert@32.2.3': dependencies: @@ -3226,6 +3346,8 @@ snapshots: bignumber.js: 9.3.1 error-causes: 3.0.2 + '@prettier/parse-srcset@3.1.0': {} + '@prettier/plugin-hermes@0.1.3': {} '@prettier/plugin-oxc@0.1.4': @@ -4459,11 +4581,15 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - prettier-plugin-astro@0.14.1: + prettier-plugin-astro@1.0.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(prettier@3.9.6): dependencies: - '@astrojs/compiler': 2.13.1 + '@astrojs/compiler-rs': 0.4.0(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@prettier/parse-srcset': 3.1.0 prettier: 3.9.6 - sass-formatter: 0.7.9 + sass-formatter: 0.8.0 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' prettier-plugin-css-order@2.2.0(postcss@8.5.26)(prettier@3.9.6): dependencies: @@ -4683,7 +4809,7 @@ snapshots: s.color@0.0.15: {} - sass-formatter@0.7.9: + sass-formatter@0.8.0: dependencies: suf-log: 2.5.3 diff --git a/src/index.ts b/src/index.ts index 57beef6..5dcfd1d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -635,14 +635,16 @@ function transformJavaScript(ast: import('@babel/types').Node, env: TransformerE return } - if (!matcher.hasStaticAttr(node.name.name)) { - return - } - + let name = node.name.name if (isStringLiteral(node.value)) { - sortStringLiteral(node.value, { env }) + if (matcher.hasStaticAttr(name)) { + sortStringLiteral(node.value, { env }) + } } else if (node.value.type === 'JSXExpressionContainer') { - sortInside(node.value) + // Dynamic attrs (e.g. Astro's `class:list`) only carry expressions, never plain strings + if (matcher.hasStaticAttr(name) || matcher.hasDynamicAttr(name)) { + sortInside(node.value) + } } }, @@ -742,6 +744,14 @@ function transformCss(ast: any, env: TransformerEnv) { } function transformAstro(ast: any, env: TransformerEnv) { + // prettier-plugin-astro v1+ produces an ESTree/JSX AST via @astrojs/compiler-rs. + // Attributes are `JSXAttribute` nodes whose values are `Literal`s or expression containers, + // so the JavaScript transform can handle them directly. + if (ast.type === 'AstroRoot') { + transformJavaScript(ast.template, env) + return + } + let { matcher } = env if (ast.type === 'element' || ast.type === 'custom-element' || ast.type === 'component') { @@ -1157,6 +1167,8 @@ let js = defineTransform({ { name: '@prettier/plugin-hermes', importer: () => import('@prettier/plugin-hermes') }, ], }, + // Only exposed by prettier-plugin-astro 0.x. + // v1 parses expressions as part of the main `astro` AST. astroExpressionParser: { load: [ { @@ -1212,6 +1224,11 @@ let svelte = defineTransform({ }) type AstroNode = + // prettier-plugin-astro 1.x + // `template` is an ESTree + JSX AST emitted by @astrojs/compiler-rs (oxc). + // Typed loosely, see the note on `transformJavaScript`. + | { type: 'AstroRoot'; template: unknown } + // prettier-plugin-astro 0.x | { type: 'element'; attributes: Extract[] } | { type: 'custom-element' diff --git a/tests/plugins.test.ts b/tests/plugins.test.ts index 9ca4e7b..c24f45f 100644 --- a/tests/plugins.test.ts +++ b/tests/plugins.test.ts @@ -350,7 +350,7 @@ let tests: PluginTest[] = [ [ `{
}`, - `{(
)}`, + `{
}`, ], [ `