-
-
Notifications
You must be signed in to change notification settings - Fork 964
feat(dx): add prettier-compare tool #8805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
9465485
feat(html): add various helpers to html syntax nodes
dyc3 d1d9f39
add prettier-compare tool
dyc3 19d3d8d
fix(compare): add html formatter option to match prettier
dyc3 388ca8b
feat(compare): make non watch mode work more reasonably
dyc3 53dc04b
feat(compare): support svelte
dyc3 a108ac4
refactor: move package, adjust readme
dyc3 298f88b
refactor: use `styleText` instead
dyc3 5f5c221
chore: update settings
dyc3 68364cc
refactor: drop biome reloading logic
dyc3 936a07f
refactor: remove commander
dyc3 edd716a
refactor: remove chokidar
dyc3 cef058c
refactor: use console.info instead of console.log
dyc3 5a49ee5
fix: type error
dyc3 a09fb1f
chore: format and lint
dyc3 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| # `prettier-compare` Package | ||
|
|
||
| ## Overview | ||
|
|
||
| A CLI tool that compares Prettier and Biome formatting output and IR side-by-side. Uses OpenTUI (with React renderer) for the terminal UI, including spinners during WASM rebuilds and debounced watch mode. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ``` | ||
| packages/prettier-compare/ | ||
| ├── src/ | ||
| │ ├── index.tsx # Main CLI entry point + React TUI app | ||
| │ ├── biome.ts # Biome formatting via @biomejs/js-api | ||
| │ ├── prettier.ts # Prettier formatting via npm package | ||
| │ ├── languages.ts # Language detection and config mapping | ||
| │ ├── components/ | ||
| │ │ ├── App.tsx # Main app component | ||
| │ │ ├── DiffView.tsx # Side-by-side diff display | ||
| │ │ ├── DiagnosticsView.tsx # Error/diagnostics section | ||
| │ │ └── Spinner.tsx # Loading spinner for rebuilds | ||
| │ └── watch.ts # Watch mode with cargo rebuild + debounce | ||
| ├── bin/ | ||
| │ └── prettier-compare.js # Bin script | ||
| ├── package.json | ||
| ├── tsconfig.json | ||
| └── README.md | ||
| ``` | ||
|
|
||
| ## Key Features | ||
|
|
||
| 1. **Multiple Input Sources**: Snippet argument, file (`--file`), or stdin | ||
| 2. **Language Detection**: Auto-detect from file extension or specify with `--language` | ||
| 3. **Side-by-Side Diff**: Show Biome vs Prettier formatted output | ||
| 4. **IR Comparison**: Show intermediate representation from both formatters | ||
| 5. **Diagnostics Section**: Display syntax errors from both tools | ||
| 6. **Watch Mode**: Rebuild WASM on Rust file changes with debounce and spinner | ||
| 7. **All Languages**: Support JS/TS, JSON, CSS, HTML, GraphQL, etc. | ||
|
|
||
| ## Usage | ||
|
|
||
| In order to run the tool, you must have the WASM build of Biome available. You can use the `--rebuild` flag to build it automatically if needed, or you can run `just build-wasm-node-dev`. | ||
|
|
||
| To run the tool, from the repo root run: | ||
|
|
||
| ```bash | ||
| # Format a snippet | ||
| bun packages/prettier-compare/bin/prettier-compare.js "const x={a:1,b:2}" | ||
|
|
||
| # Specify language | ||
| bun packages/prettier-compare/bin/prettier-compare.js -l ts "const x: number = 1" | ||
|
|
||
| # From file | ||
| bun packages/prettier-compare/bin/prettier-compare.js -f src/example.tsx | ||
|
|
||
| # From stdin | ||
| echo "const x = 1" | bun packages/prettier-compare/bin/prettier-compare.js -l js | ||
|
|
||
| # Watch mode (rebuilds WASM on Rust changes) | ||
| bun --hot packages/prettier-compare/bin/prettier-compare.js -w --watch "function f() { return 1 }" | ||
| bun --hot packages/prettier-compare/bin/prettier-compare.js -l html --watch '<tr> <th> A </th> <th> B </th> <th> C </th> </tr>' | ||
| ``` | ||
|
|
||
| Note: In watch mode, if you want it to reload the wasm after building biome, then you must use `bun --hot` to run the bin script. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| #!/usr/bin/env -S bun --hot | ||
| import "../src/index.tsx"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "name": "@biomejs/prettier-compare", | ||
| "version": "0.0.0", | ||
| "private": true, | ||
| "type": "module", | ||
| "description": "Compare Biome and Prettier formatting output and IR side-by-side", | ||
| "bin": { | ||
| "prettier-compare": "./bin/prettier-compare.js" | ||
| }, | ||
| "dependencies": { | ||
| "@biomejs/js-api": "workspace:*", | ||
| "@biomejs/wasm-nodejs": "workspace:*", | ||
| "@opentui/core": "^0.1.72", | ||
| "@opentui/react": "^0.1.72", | ||
| "prettier": "^3.7.0", | ||
| "prettier-plugin-svelte": "^3.4.0", | ||
| "react": "^19.0.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^22.0.0", | ||
| "@types/react": "^19.0.0", | ||
| "typescript": "5.7.3" | ||
| }, | ||
| "license": "MIT OR Apache-2.0" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| /** | ||
| * Biome formatting integration using @biomejs/js-api | ||
| */ | ||
|
|
||
| import { Biome, Distribution } from "@biomejs/js-api"; | ||
|
|
||
| export interface BiomeDiagnostic { | ||
| description: string; | ||
| severity: string; | ||
| } | ||
|
|
||
| export interface BiomeResult { | ||
| /** The formatted output */ | ||
| output: string; | ||
| /** The formatter IR (intermediate representation) */ | ||
| ir: string; | ||
| /** Any diagnostics/errors encountered */ | ||
| diagnostics: BiomeDiagnostic[]; | ||
| } | ||
|
|
||
| let biomeInstance: Biome | null = null; | ||
|
|
||
| /** | ||
| * Get or create a Biome instance. | ||
| */ | ||
| async function getBiome(): Promise<Biome> { | ||
| if (!biomeInstance) { | ||
| biomeInstance = await Biome.create({ distribution: Distribution.NODE }); | ||
| } | ||
| return biomeInstance; | ||
| } | ||
|
|
||
| /** | ||
| * Format code using Biome and return the result with IR. | ||
| * | ||
| * @param code - The source code to format | ||
| * @param filePath - Virtual file path for language detection | ||
| * @returns The formatting result including output, IR, and diagnostics | ||
| */ | ||
| export async function formatWithBiome( | ||
| code: string, | ||
| filePath: string, | ||
| ): Promise<BiomeResult> { | ||
| const biome = await getBiome(); | ||
| const { projectKey } = biome.openProject(); | ||
|
|
||
| try { | ||
| biome.applyConfiguration(projectKey, { | ||
| formatter: { | ||
| indentStyle: "space", | ||
| indentWidth: 2, | ||
| }, | ||
| html: { | ||
| experimentalFullSupportEnabled: true, | ||
| formatter: { | ||
| enabled: true, | ||
| selfCloseVoidElements: "always", | ||
| }, | ||
dyc3 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }, | ||
| }); | ||
|
|
||
| const result = biome.formatContent(projectKey, code, { | ||
| filePath, | ||
| debug: true, | ||
| }); | ||
|
|
||
| return { | ||
| output: result.content, | ||
| ir: result.ir ?? "", | ||
| diagnostics: result.diagnostics.map((d) => ({ | ||
| description: | ||
| typeof d === "object" && d !== null && "description" in d | ||
| ? String(d.description) | ||
| : String(d), | ||
| severity: | ||
| typeof d === "object" && d !== null && "severity" in d | ||
| ? String(d.severity) | ||
| : "error", | ||
| })), | ||
| }; | ||
| } catch (err) { | ||
| return { | ||
| output: code, | ||
| ir: "", | ||
| diagnostics: [ | ||
| { | ||
| description: err instanceof Error ? err.message : String(err), | ||
| severity: "error", | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.