More from JSFormat
Guides
Frequently Asked Questions
Is my data safe on jsformat.dev?
Yes. Formatting is done in your browser; your source code is never uploaded.
Will formatting change what my code does?
No. The formatter changes whitespace and line breaks only, and leaves string literals untouched. Automatic semicolon insertion is preserved, so a reformat cannot silently change a statement boundary.
Does it handle TypeScript?
Not as a TypeScript formatter. The tokenizer reads TypeScript syntax as ordinary words and punctuation, so type annotations, generics and decorators come through uncorrupted, but they are not laid out with any understanding of types. Use Prettier or Biome for TypeScript layout.
🧭 Pro Tips & Gotchas
What this tool is
- A tokenizer plus a printer, not a text substitution. The scan classifies strings, template literals, comments, regex literals, numbers, and punctuation, so line breaks are only ever inserted at real token boundaries.
- The old version did
code.replace(/\{/g, "{\n"), which shredded every template literal and any string containing a brace or semicolon. That class of bug is what a token stream exists to prevent. - Two safety nets run on every format: the output must re-tokenize to an identical token stream, and every line break in your input must survive into the output. If either check fails the tool refuses and shows your original code instead of formatting it.
Why those two checks are the whole point
- Token equality catches a formatter that silently changes meaning — dropping a token, splitting an identifier, mis-joining an operator.
- Break preservation catches the subtler failure: newlines are load-bearing under ASI.
const s = 1\n-1;is two statements; joined onto one line it becomesconst s = 1 - 1. A formatter that only guarantees "same tokens" can still rewrite your program's meaning. - So the contract is one-directional: the formatter may add line breaks, never remove one. Refusing beats producing plausible wrong code.
- Template literals are printed verbatim, including any braces, semicolons, or newlines inside them. Interpolated expressions are preserved, not reformatted.
- Regex versus division is decided by the previous token, not by guessing:
/after a value or)/]is division, otherwise a regex.a / b / cand/{|;/gboth survive.
What it still cannot do
- It is not a parser, so it has no AST. Long expressions are not wrapped at a sensible operator, object literals do not get one-key-per-line unless you wrote them that way, and chained calls stay on one line.
- JSX and TypeScript type syntax are tokenized as generic words and punctuation. It will not corrupt them, but it will not lay them out well either.
- Comments are placed, not reflowed: a trailing block comment stays on its line, a line comment always claims its own line so it can never swallow the statement after it.
- The rule that applies to any formatter: if you cannot diff it, you cannot trust it. Format in a separate commit, or check the diff with whitespace ignored, so a formatter bug cannot hide inside a real change.
For anything large
Prettier and dprint are WASM-loadable, so a formatter with real parsing is available with no server cost: prettier/standalone plus parser-babel or parser-typescript, and Biome's WASM build does format and lint in one bundle. Reach for those when you need wrapping and JSX layout; keep this tool for un-minifying a blob in the browser with nothing installed.