From 9ae1edec706b707c8897e26d4aae0693a596ce8a Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 30 Jun 2025 21:06:58 -0400 Subject: [PATCH 1/3] Refactor --- tests/format.test.ts | 276 +------------------------------------------ tests/tests.ts | 272 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+), 273 deletions(-) create mode 100644 tests/tests.ts diff --git a/tests/format.test.ts b/tests/format.test.ts index d426e26..9b49283 100644 --- a/tests/format.test.ts +++ b/tests/format.test.ts @@ -1,278 +1,8 @@ import { describe, test } from 'vitest' -import type { TestEntry } from './utils.js' -import { format, no, t, yes } from './utils.js' +import { tests } from './tests.js' +import { format } from './utils.js' -let html: TestEntry[] = [ - t`
`, - t``, - t`
`, - t`
`, - ['
', '
'], - t`
`, - t`
`, - // Ensure duplicate classes are removed - ['
', '
'], - // Duplicates are not removed for unknown classes - [ - '
', - '
', - ], - // Ensure duplicate can be kept - [ - '
', - '
', - { - tailwindPreserveDuplicates: true, - }, - ], - - // … is moved to the end of the list - ['
', '
'], - ['
', '
'], - ['
', '
'], - ['
', '
'], - ['
', '
'], - ['
', '
'], -] - -let css: TestEntry[] = [ - t`@apply ${yes};`, - t`/* @apply ${no}; */`, - t`@not-apply ${no};`, - [ - '@apply sm:p-0\n p-0;', - '@apply p-0\n sm:p-0;', - { tailwindPreserveWhitespace: true }, - ], -] - -let javascript: TestEntry[] = [ - t`;
`, - t`;
`, - t`/*
*/`, - t`//
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - t`;
`, - [ - `;
`, - `;
`, - ], - [ - `;
`, - `;
`, - ], - [ - `;
`, - `;
`, - ], - [ - `;
`, - `;
`, - ], - - // Whitespace is normalized and duplicates are removed - [ - ';
', - ';
', - ], - [ - ";
", - ";
", - ], - [';
', ';
'], - [';
', ';
'], - [';
', ';
'], - [ - ';
', - ';
', - ], - [ - ';
', - ';
', - ], - [ - ';
', - ';
', - ], - - t`;
`, - t`;
`, - t`;
`, - - [ - `;
`, - `;
`, - ], -] -javascript = javascript.concat( - javascript.map((test) => [ - test[0].replace(/class/g, 'className'), - test[1].replace(/class/g, 'className'), - test[2], - ]), -) - -let vue: TestEntry[] = [ - ...html, - t`
`, - t``, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, // ts - t`
`, // ts - [ - `
`, - `
`, - ], - [ - `
`, - `
`, - ], - [ - `
`, - `
`, - ], - - [`
`, `
`], - [`
`, `
`], - [ - `
`, - `
`, - ], - [ - `
`, - `
`, - ], - - [ - `
`, - `
`, - ], -] - -let glimmer: TestEntry[] = [ - t`
`, - t``, - t`
`, - t`
`, - t`
`, - t`
`, - [ - `
`, - `
`, - ], - [ - `
`, - `
`, - ], - t`
`, - ["
", "
"], - t`
`, - t`
`, - t`{{link 'Some page' href=person.url class='${no}'}}`, - t`
`, - [ - `
`, - `
`, - ], - [ - `
`, - `
`, - ], - [ - `
`, - `
`, - ], - - [`
`, `
`], - - [ - `
`, - `
`, - ], -] - -let tests: Record = { - html, - glimmer, - lwc: html, - vue: [ - ...vue, - t`
`, - ], - angular: [ - ...html, - t`
`, - t``, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - t`
`, - - [ - `
`, - `
`, - ], - - // TODO: Enable this test — it causes console noise but not a failure - // t`
`, - ], - css: [...css, t`@apply ${yes} !important;`], - scss: [ - ...css, - t`@apply ${yes} #{!important};`, - t`@apply ${yes} #{'!important'};`, - t`@apply ${yes} #{"!important"};`, - - // These shouldn't ever be used but they are valid - // syntax so we might as well not break them - t`@apply ${yes} #{""!important""};`, - t`@apply ${yes} #{'''!important'''};`, - t`@apply ${yes} #{"'"'"!important"'"'"};`, - ], - less: [...css, t`@apply ${yes} !important;`], - babel: javascript, - typescript: javascript, - 'babel-ts': javascript, - flow: javascript, - 'babel-flow': javascript, - acorn: javascript, - meriyah: javascript, - mdx: javascript - .filter((test) => { - return !/^\/\*/.test(test[0]) && !/^\/\*/.test(test[1]) - }) - .map((test) => [ - test[0].replace(/^;/, ''), - test[1].replace(/^;/, ''), - test[2], - ]), -} - -describe('parsers', () => { +describe('parsers', async () => { for (let parser in tests) { test(parser, async ({ expect }) => { for (let [input, expected, options] of tests[parser]) { diff --git a/tests/tests.ts b/tests/tests.ts new file mode 100644 index 0000000..c2813de --- /dev/null +++ b/tests/tests.ts @@ -0,0 +1,272 @@ +import type { TestEntry } from './utils.js' +import { no, t, yes } from './utils.js' + +let html: TestEntry[] = [ + t`
`, + t``, + t`
`, + t`
`, + ['
', '
'], + t`
`, + t`
`, + // Ensure duplicate classes are removed + ['
', '
'], + // Duplicates are not removed for unknown classes + [ + '
', + '
', + ], + // Ensure duplicate can be kept + [ + '
', + '
', + { + tailwindPreserveDuplicates: true, + }, + ], + + // … is moved to the end of the list + ['
', '
'], + ['
', '
'], + ['
', '
'], + ['
', '
'], + ['
', '
'], + ['
', '
'], +] + +let css: TestEntry[] = [ + t`@apply ${yes};`, + t`/* @apply ${no}; */`, + t`@not-apply ${no};`, + [ + '@apply sm:p-0\n p-0;', + '@apply p-0\n sm:p-0;', + { tailwindPreserveWhitespace: true }, + ], +] + +export let javascript: TestEntry[] = [ + t`;
`, + t`;
`, + t`/*
*/`, + t`//
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + t`;
`, + [ + `;
`, + `;
`, + ], + [ + `;
`, + `;
`, + ], + [ + `;
`, + `;
`, + ], + [ + `;
`, + `;
`, + ], + + // Whitespace is normalized and duplicates are removed + [ + ';
', + ';
', + ], + [ + ";
", + ";
", + ], + [';
', ';
'], + [';
', ';
'], + [';
', ';
'], + [ + ';
', + ';
', + ], + [ + ';
', + ';
', + ], + [ + ';
', + ';
', + ], + + t`;
`, + t`;
`, + t`;
`, + + [ + `;
`, + `;
`, + ], +] +javascript = javascript.concat( + javascript.map((test) => [ + test[0].replace(/class/g, 'className'), + test[1].replace(/class/g, 'className'), + test[2], + ]), +) + +let vue: TestEntry[] = [ + ...html, + t`
`, + t``, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, // ts + t`
`, // ts + [ + `
`, + `
`, + ], + [ + `
`, + `
`, + ], + [ + `
`, + `
`, + ], + + [`
`, `
`], + [`
`, `
`], + [ + `
`, + `
`, + ], + [ + `
`, + `
`, + ], + + [ + `
`, + `
`, + ], +] + +let glimmer: TestEntry[] = [ + t`
`, + t``, + t`
`, + t`
`, + t`
`, + t`
`, + [ + `
`, + `
`, + ], + [ + `
`, + `
`, + ], + t`
`, + ["
", "
"], + t`
`, + t`
`, + t`{{link 'Some page' href=person.url class='${no}'}}`, + t`
`, + [ + `
`, + `
`, + ], + [ + `
`, + `
`, + ], + [ + `
`, + `
`, + ], + + [`
`, `
`], + + [ + `
`, + `
`, + ], +] + +export let tests: Record = { + html, + glimmer, + lwc: html, + vue: [ + ...vue, + t`
`, + ], + angular: [ + ...html, + t`
`, + t``, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + t`
`, + + [ + `
`, + `
`, + ], + + // TODO: Enable this test — it causes console noise but not a failure + // t`
`, + ], + css: [...css, t`@apply ${yes} !important;`], + scss: [ + ...css, + t`@apply ${yes} #{!important};`, + t`@apply ${yes} #{'!important'};`, + t`@apply ${yes} #{"!important"};`, + + // These shouldn't ever be used but they are valid + // syntax so we might as well not break them + t`@apply ${yes} #{""!important""};`, + t`@apply ${yes} #{'''!important'''};`, + t`@apply ${yes} #{"'"'"!important"'"'"};`, + ], + less: [...css, t`@apply ${yes} !important;`], + babel: javascript, + typescript: javascript, + 'babel-ts': javascript, + flow: javascript, + 'babel-flow': javascript, + acorn: javascript, + meriyah: javascript, + mdx: javascript + .filter((test) => { + return !/^\/\*/.test(test[0]) && !/^\/\*/.test(test[1]) + }) + .map((test) => [ + test[0].replace(/^;/, ''), + test[1].replace(/^;/, ''), + test[2], + ]), +} From 1542d3e9ee2182528174a92aa5e4907bcc54ccc5 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 30 Jun 2025 21:07:15 -0400 Subject: [PATCH 2/3] Add support for OXC and Hermes plugins --- package-lock.json | 395 ++++++++++++++++++++++++++++++++++++++++++ package.json | 10 ++ src/index.ts | 15 ++ src/plugins.ts | 24 ++- tests/plugins.test.ts | 14 ++ 5 files changed, 450 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1606cf..6a107e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "@babel/types": "^7.24.7", "@ianvs/prettier-plugin-sort-imports": "^4.1.0", "@microsoft/api-extractor": "^7.47.0", + "@prettier/plugin-hermes": "^0.0.3", + "@prettier/plugin-oxc": "^0.0.4", "@prettier/plugin-pug": "^3.0", "@shopify/prettier-plugin-liquid": "^1.4.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", @@ -57,6 +59,8 @@ }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", @@ -78,6 +82,12 @@ "@ianvs/prettier-plugin-sort-imports": { "optional": true }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, "@prettier/plugin-pug": { "optional": true }, @@ -643,6 +653,40 @@ "node": ">=6.9.0" } }, + "node_modules/@emnapi/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", @@ -1316,6 +1360,19 @@ "resolve": "~1.22.2" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", + "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.9.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1351,6 +1408,271 @@ "node": ">= 8" } }, + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.74.0.tgz", + "integrity": "sha512-lgq8TJq22eyfojfa2jBFy2m66ckAo7iNRYDdyn9reXYA3I6Wx7tgGWVx1JAp1lO+aUiqdqP/uPlDaETL9tqRcg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-arm64": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.74.0.tgz", + "integrity": "sha512-xbY/io/hkARggbpYEMFX6CwFzb7f4iS6WuBoBeZtdqRWfIEi7sm/uYWXfyVeB8uqOATvJ07WRFC2upI8PSI83g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.74.0.tgz", + "integrity": "sha512-FIj2gAGtFaW0Zk+TnGyenMUoRu1ju+kJ/h71D77xc1owOItbFZFGa+4WSVck1H8rTtceeJlK+kux+vCjGFCl9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.74.0.tgz", + "integrity": "sha512-W1I+g5TJg0TRRMHgEWNWsTIfe782V3QuaPgZxnfPNmDMywYdtlzllzclBgaDq6qzvZCCQc/UhvNb37KWTCTj8A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.74.0.tgz", + "integrity": "sha512-gxqkyRGApeVI8dgvJ19SYe59XASW3uVxF1YUgkE7peW/XIg5QRAOVTFKyTjI9acYuK1MF6OJHqx30cmxmZLtiQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.74.0.tgz", + "integrity": "sha512-jpnAUP4Fa93VdPPDzxxBguJmldj/Gpz7wTXKFzpAueqBMfZsy9KNC+0qT2uZ9HGUDMzNuKw0Se3bPCpL/gfD2Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.74.0.tgz", + "integrity": "sha512-fcWyM7BNfCkHqIf3kll8fJctbR/PseL4RnS2isD9Y3FFBhp4efGAzhDaxIUK5GK7kIcFh1P+puIRig8WJ6IMVQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.74.0.tgz", + "integrity": "sha512-AMY30z/C77HgiRRJX7YtVUaelKq1ex0aaj28XoJu4SCezdS8i0IftUNTtGS1UzGjGZB8zQz5SFwVy4dRu4GLwg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.74.0.tgz", + "integrity": "sha512-/RZAP24TgZo4vV/01TBlzRqs0R7E6xvatww4LnmZEBBulQBU/SkypDywfriFqWuFoa61WFXPV7sLcTjJGjim/w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.74.0.tgz", + "integrity": "sha512-620J1beNAlGSPBD+Msb3ptvrwxu04B8iULCH03zlf0JSLy/5sqlD6qBs0XUVkUJv1vbakUw1gfVnUQqv0UTuEg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.74.0.tgz", + "integrity": "sha512-WBFgQmGtFnPNzHyLKbC1wkYGaRIBxXGofO0+hz1xrrkPgbxbJS1Ukva1EB8sPaVBBQ52Bdc2GjLSp721NWRvww==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.74.0.tgz", + "integrity": "sha512-y4mapxi0RGqlp3t6Sm+knJlAEqdKDYrEue2LlXOka/F2i4sRN0XhEMPiSOB3ppHmvK4I2zY2XBYTsX1Fel0fAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.74.0.tgz", + "integrity": "sha512-yDS9bRDh5ymobiS2xBmjlrGdUuU61IZoJBaJC5fELdYT5LJNBXlbr3Yc6m2PWfRJwkH6Aq5fRvxAZ4wCbkGa8w==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.74.0.tgz", + "integrity": "sha512-XFWY52Rfb4N5wEbMCTSBMxRkDLGbAI9CBSL24BIDywwDJMl31gHEVlmHdCDRoXAmanCI6gwbXYTrWe0HvXJ7Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.74.0.tgz", + "integrity": "sha512-1D3x6iU2apLyfTQHygbdaNbX3nZaHu4yaXpD7ilYpoLo7f0MX0tUuoDrqJyJrVGqvyXgc0uz4yXz9tH9ZZhvvg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.74.0.tgz", + "integrity": "sha512-KOw/RZrVlHGhCXh1RufBFF7Nuo7HdY5w1lRJukM/igIl6x9qtz8QycDvZdzb4qnHO7znrPyo2sJrFJK2eKHgfQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1361,6 +1683,35 @@ "node": ">=14" } }, + "node_modules/@prettier/plugin-hermes": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@prettier/plugin-hermes/-/plugin-hermes-0.0.3.tgz", + "integrity": "sha512-ahQNCXlyL39xKT3hT5TSnbE4zGLEWTVlRbzDJmQdd+TRBAeunfDuqrL8JIlN/1ky9ZEUWZnT590/XRCFyxgc2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/@prettier/plugin-oxc": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@prettier/plugin-oxc/-/plugin-oxc-0.0.4.tgz", + "integrity": "sha512-UGXe+g/rSRbglL0FOJiar+a+nUrst7KaFmsg05wYbKiInGWP6eAj/f8A2Uobgo5KxEtb2X10zeflNH6RK2xeIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "oxc-parser": "0.74.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/@prettier/plugin-pug": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@prettier/plugin-pug/-/plugin-pug-3.2.0.tgz", @@ -1884,6 +2235,17 @@ "node": ">=0.10.0" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/argparse": { "version": "1.0.38", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", @@ -5086,6 +5448,39 @@ "os-tmpdir": "^1.0.0" } }, + "node_modules/oxc-parser": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.74.0.tgz", + "integrity": "sha512-2tDN/ttU8WE6oFh8EzKNam7KE7ZXSG5uXmvX85iNzxdJfMssDWcj3gpYzZi1E04XuE7m3v1dVWl/8BE886vPGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "^0.74.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-parser/binding-android-arm64": "0.74.0", + "@oxc-parser/binding-darwin-arm64": "0.74.0", + "@oxc-parser/binding-darwin-x64": "0.74.0", + "@oxc-parser/binding-freebsd-x64": "0.74.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.74.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.74.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.74.0", + "@oxc-parser/binding-linux-arm64-musl": "0.74.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.74.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.74.0", + "@oxc-parser/binding-linux-x64-gnu": "0.74.0", + "@oxc-parser/binding-linux-x64-musl": "0.74.0", + "@oxc-parser/binding-wasm32-wasi": "0.74.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.74.0", + "@oxc-parser/binding-win32-x64-msvc": "0.74.0" + } + }, "node_modules/p-event": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", diff --git a/package.json b/package.json index 30ab503..1101703 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,8 @@ "@babel/types": "^7.24.7", "@ianvs/prettier-plugin-sort-imports": "^4.1.0", "@microsoft/api-extractor": "^7.47.0", + "@prettier/plugin-hermes": "^0.0.3", + "@prettier/plugin-oxc": "^0.0.4", "@prettier/plugin-pug": "^3.0", "@shopify/prettier-plugin-liquid": "^1.4.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", @@ -78,6 +80,8 @@ }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", @@ -99,6 +103,12 @@ "@ianvs/prettier-plugin-sort-imports": { "optional": true }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, "@prettier/plugin-pug": { "optional": true }, diff --git a/src/index.ts b/src/index.ts index 0b4d8ff..bd7fc18 100644 --- a/src/index.ts +++ b/src/index.ts @@ -634,6 +634,10 @@ function isSortableCallExpression( return false } +// TODO: The `ast` types here aren't strictly correct. +// +// We cross several parsers that share roughly the same shape so things are +// good enough. The actual AST we should be using is probably estree + ts. function transformJavaScript( ast: import('@babel/types').Node, { env }: TransformerContext, @@ -1118,6 +1122,10 @@ export const parsers: Record = { staticAttrs: ['class', 'className'], }), + hermes: createParser('hermes', transformJavaScript, { + staticAttrs: ['class', 'className'], + }), + typescript: createParser('typescript', transformJavaScript, { staticAttrs: ['class', 'className'], }), @@ -1126,6 +1134,13 @@ export const parsers: Record = { staticAttrs: ['class', 'className'], }), + oxc: createParser('oxc', transformJavaScript, { + staticAttrs: ['class', 'className'], + }), + 'oxc-ts': createParser('oxc', transformJavaScript, { + staticAttrs: ['class', 'className'], + }), + acorn: createParser('acorn', transformJavaScript, { staticAttrs: ['class', 'className'], }), diff --git a/src/plugins.ts b/src/plugins.ts index d2e69d2..7aa1a10 100644 --- a/src/plugins.ts +++ b/src/plugins.ts @@ -128,24 +128,32 @@ async function loadBuiltinPlugins(): Promise { } async function loadThirdPartyPlugins(): Promise { - let [astro, liquid, marko, twig, pug, svelte] = await Promise.all([ - loadIfExistsESM('prettier-plugin-astro'), - loadIfExistsESM('@shopify/prettier-plugin-liquid'), - loadIfExistsESM('prettier-plugin-marko'), - loadIfExistsESM('@zackad/prettier-plugin-twig'), - loadIfExistsESM('@prettier/plugin-pug'), - loadIfExistsESM('prettier-plugin-svelte'), - ]) + let [astro, liquid, marko, twig, hermes, oxc, pug, svelte] = + await Promise.all([ + loadIfExistsESM('prettier-plugin-astro'), + loadIfExistsESM('@shopify/prettier-plugin-liquid'), + loadIfExistsESM('prettier-plugin-marko'), + loadIfExistsESM('@zackad/prettier-plugin-twig'), + loadIfExistsESM('@prettier/plugin-hermes'), + loadIfExistsESM('@prettier/plugin-oxc'), + loadIfExistsESM('@prettier/plugin-pug'), + loadIfExistsESM('prettier-plugin-svelte'), + ]) + return { parsers: { ...astro.parsers, ...liquid.parsers, ...marko.parsers, ...twig.parsers, + ...hermes.parsers, + ...oxc.parsers, ...pug.parsers, ...svelte.parsers, }, printers: { + ...hermes.printers, + ...oxc.printers, ...svelte.printers, }, } diff --git a/tests/plugins.test.ts b/tests/plugins.test.ts index 3e61c8d..e535ba6 100644 --- a/tests/plugins.test.ts +++ b/tests/plugins.test.ts @@ -1,6 +1,7 @@ import { createRequire } from 'node:module' import dedent from 'dedent' import { test } from 'vitest' +import { javascript } from './tests.js' import type { TestEntry } from './utils.js' import { format, no, pluginPath, t, yes } from './utils.js' @@ -166,6 +167,19 @@ let tests: PluginTest[] = [ ], }, }, + { + plugins: ['@prettier/plugin-hermes'], + tests: { + hermes: javascript, + }, + }, + { + plugins: ['@prettier/plugin-oxc'], + tests: { + oxc: javascript, + 'oxc-ts': javascript, + }, + }, { plugins: ['@prettier/plugin-pug'], tests: { From d16be899bff32fc43bd573042cdd26b0d7639d30 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 1 Jul 2025 11:15:44 -0400 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6707bb6..15bbc1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +- Add support for OXC + Hermes Prettier plugins ([#376](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/pull/376)) ## [0.6.13] - 2025-06-19