00
Prettier's style, at native speed.
tidy is a code formatter written in Rust. One binary prints what Prettier prints, for every language below. It does not shell out to Node — though there is a Node binding if you want one.
curl -fsSL https://tidy.lukeed.com |
shor build it with cargo — every way to install
01 / Speed
M1 Max, all cores, mean of both run orders. Bars compare the three native tools; Prettier is off that scale. every corpus and the method →
02 / Output
Byte for byte what Prettier prints
Not a lookalike style. tidy's tests run Prettier over the same corpus and compare the bytes, so a difference is a bug — unless it is one of the documented deviations.
routes.tsas written
import {readFile} from 'node:fs/promises'
type Route={
path:string,run:(req:Request)=>Promise<Response>}
const routes:Route[]=[
{path:'/',run:()=>page("index.html")},
{path:"/up",run:async()=>new Response('ok')},
]
export function match(path:string){
return routes.find(r=>r.path===path)??null}
async function page(file:string){
const body=await readFile(file,"utf8")
const type={"content-type":'text/html'}
return new Response(body,{headers:type})}routes.tstidy up
import { readFile } from "node:fs/promises";
type Route = {
path: string;
run: (req: Request) => Promise<Response>;
};
const routes: Route[] = [
{ path: "/", run: () => page("index.html") },
{ path: "/up", run: async () => new Response("ok") },
];
export function match(path: string) {
return routes.find((r) => r.path === path) ?? null;
}
async function page(file: string) {
const body = await readFile(file, "utf8");
const type = { "content-type": "text/html" };
return new Response(body, { headers: type });
}03 / Why
Every release is checked against Prettier 3.9.9 over a 12,000-file corpus: 100% of 3,906 JavaScript files and 3,308 of 3,309 TypeScript files.
Styles and scripts in HTML and Vue. Markdown code blocks and front matter. CSS, GraphQL, HTML and Markdown in JS template literals.
Reads tidy.json, tidy.jsonc or tidy.toml, on top of .editorconfig. The defaults are Prettier’s.
Where Prettier would change its mind on the next run, tidy prints where it settles, so tidy check stays green in CI.
04 / Languages
Every language Prettier formats
Plus the ones its plugins cover, built into the same binary. Nothing to install, nothing to register.
- JavaScript, TypeScript, JSXPrettier
- HTML, Vue, Handlebars, MJMLPrettier
- CSS, SCSS, LessPrettier
- JSON, JSONC, JSON5Prettier
- YAML, GraphQL, MarkdownPrettier
- XML, SVG@prettier/plugin-xml
- TOMLtaplo
- Dockerfilesdprint-plugin-dockerfile
- INI, .editorconfig, .npmrcprettier-plugin-ini
05 / Config
Configurable, if you need it
Each file takes the nearest
tidy.json,
tidy.jsonc
or
tidy.toml, on top of
.editorconfig. Shared keys apply everywhere, and a
language section overrides them. See
every option.
{
"width": 100,
"js": { "semi": false, "quote": "single" },
"markdown": { "wrap": "always" }
}Then run it:
# print one file, formatted
$ tidy index.html
# list what isn't formatted; exits 1 if any
$ tidy check src
# rewrite everything in place
$ tidy up .
# only what this branch changed
$ tidy up --changed