gizmobench

JavaScript Beautifier

Paste a minified bundle, a squashed one-liner or a file somebody else indented with tabs and spaces at once, and read it back laid out. What is different here is what does not happen: this is a scanner and a printer, not a parser and a code generator, so nothing is rebuilt from a syntax tree. The tokens that come out are the tokens that went in, in the same order and with the same text, which means your quotes stay the quotes you chose, a semicolon you left out stays left out, and the contents of every string and template literal come back byte for byte, down to the indentation inside a template. Only the whitespace between tokens moves. The page checks that claim in front of you: the output is formatted a second time on every keystroke and compared with the first, and the Idempotent cell reports the result of that comparison rather than a promise.

formattedjavascript, 2 spaces, width 80
const f = (a, b) => { if (a > b) { return a } else { return b } }
Parser
Indent
Columns a bracketed list may fill before it breaks, from 40 to 200.
Idempotent
Yes

7 lines out, 26 tokens, and formatting it again changes nothing.

  • A one-line arrow functionJavaScript parser
    const f = (a, b) => { if (a > b) { return a } else { return b } }
  • That output, formatted againsame settings, second pass
    const f = (a, b) => { if (a > b) { return a } else { return b } }
  • TypeScript under the JavaScript parserthe wrong parser for the file
    Line 1: the interface keyword is TypeScript, not JavaScript. Switch the parser to TypeScript and format again.
What moves, and what does not. Only the whitespace between tokens. A line break you wrote is kept, because a line break can end a statement in JavaScript and taking one out would change the program; runs of blank lines collapse to one. A line break is added only where the grammar reads it as whitespace: inside a block, after a semicolon, after a line comment, and between the items of a bracketed list wider than the print width. Nothing is renamed, no quote is swapped, no semicolon is inserted, and the inside of a string or a template literal is never touched. A comment keeps its words; if it is a block comment whose lines all start with a star, it is realigned to the new indentation.

Up to 1,000,000 characters in one pass, read here in your browser with nothing uploaded, nothing executed and no account. The print width counts columns, with a tab counted as 2; it decides when a bracketed list breaks, and it never rewraps the text inside a string or a comment. The parser, the indent, the width and the draft are kept in this browser alone, drafts up to 200,000 characters, and the Start over button above the tool forgets them.

Accuracy. Layout only: every token comes back exactly as you wrote it, so strings, template literals and comments keep their contents and no semicolon or bracket is invented; the one exception is a block comment whose lines all start with a star, which is realigned to the new indentation. A line break you wrote is kept, only the whitespace between tokens moves, and formatting the result again returns the same bytes. It checks that brackets, strings, comments and regular expressions are closed but parses no further, so a source it formats can still fail to run; nothing is executed, nothing leaves this page, and a source may be up to 1,000,000 characters.

Common questions

Can beautifying change what my code does?
The formatter is built so that it cannot. Two rules do the work. First, every token is copied out exactly as it was read, so nothing is renamed, no quote is swapped and no punctuation is invented; where two tokens would fuse into a third if they were printed together, a space goes between them. Second, a line break you wrote is kept. That second rule matters more than it looks: JavaScript ends a statement at a line break in some places, so a formatter that rejoined your lines could quietly change the meaning of the file. Runs of blank lines collapse to one and trailing spaces go. A line break is only ever added where the grammar reads it as plain whitespace: inside a block, after a semicolon that has already ended a statement, after a line comment, and between the items of a bracketed list wider than the print width.
Why does it not add the semicolons my code is missing?
Because adding one is writing code, not laying it out. A missing semicolon is either deliberate, in which case inserting them is an edit you did not ask for, or a mistake, in which case you want to see it rather than have it papered over. So a statement that ended without a semicolon still ends without one, and the indentation shows you exactly where the file thinks each statement stops. The same rule keeps the other direction honest: a semicolon you wrote is printed where you wrote it, including an empty statement on a line of its own.
What happens to strings and template literals?
Nothing at all. A string keeps its quote character, its escapes and every space inside it. A template literal is read as a single token from its opening backtick to its closing one, holes and nested templates included, so its bytes cannot move. That is not a shortcut, it is the only safe answer: the line breaks and indentation inside a template literal are part of the string the program produces, so re-indenting them would change what your code returns. Comments are copied out the same way, with one deliberate exception: a block comment whose continuation lines all begin with a star, the documentation convention, is realigned to the new indentation.
What does the Idempotent cell mean?
It is a check, run in front of you, not a claim. Every time the output changes, the page formats that output a second time with the same settings and compares the two, character for character. Yes means the second pass produced identical bytes, which is what you want from a formatter: running it twice, or running it on a file a colleague already ran it on, leaves the file alone and produces no diff noise in review. The three rows under the tool show the same thing from the other side: the second row is the first row's output fed back in.
Which parser should I choose, and what happens if I choose the wrong one?
JavaScript for plain JS, TypeScript for annotations, generics, interfaces and enums, and JSON for data. Choosing wrongly gives you a message rather than a mangled file. JSON is read strictly, so a trailing comma, a single-quoted string, an unquoted property name, a comment or a leading zero is refused with the line it sits on. A TypeScript file read as JavaScript stops at the first construct that is TypeScript only, an interface, a type alias, an enum, a type annotation, an as assertion or a non-null assertion, and names it. That check names what it finds rather than parsing the whole file, so a file whose only TypeScript is a generic call can pass through it unnoticed.
What does the print width do?
It sets how wide a line may get before a bracketed list is opened out, one item per line. The default is 80 columns and you can set anything from 40 to 200. It is measured in columns, with a tab counted as 2, and it only ever decides whether brackets break: text is never rewrapped, so a long string, a long comment or a long chain of names stays on one line whatever the setting. A bracket pair that holds a single nested list keeps its brackets against that list rather than adding two more lines of its own.
Is my code uploaded, executed or logged anywhere?
No. The formatter runs in your browser, which is the point when the file is a client bundle or something under an agreement. There is no account, no sign-up and no upload, the page makes no network request of its own, and nothing you paste is ever evaluated: the scanner reads characters and the printer writes them, so a source with a call to something dangerous in it is text, not a program. Your draft is remembered on this device alone, up to 200,000 characters of it, and the Start over button above the tool forgets the draft along with the parser, the indent and the width.
How much can I paste at once?
Up to 1,000,000 characters in a single pass, which is a large bundle. Past that the page tells you how large your paste is and how large it may be, and formats nothing until you split it. It never truncates: a formatter that silently dropped the end of your file would be worse than one that refused it.
Does it handle JSX or a framework file?
No, and it says so instead of guessing. JSX is refused, with the line it was found on, because the whitespace between JSX children is content rather than layout, and a formatter that moves it changes what the page renders. The same goes for a Vue or Svelte single-file component: paste the script body on its own and it formats like any other source. What is supported is plain JavaScript including modern syntax, TypeScript, and JSON.
What does it tell me when the file will not format?
It names the line and what is wrong there. An unclosed string, template literal, block comment or regular expression, a bracket that is never closed, a bracket that closes one of a different kind and a closing bracket with nothing open are each reported with the line they begin on, and nothing is rewritten. That is a lexical check, not a full parse: this page will not tell you that an argument list is missing a comma, so a source it formats happily can still fail to run.

Layout only: every token comes back exactly as you wrote it, so strings, template literals and comments keep their contents and no semicolon or bracket is invented; the one exception is a block comment whose lines all start with a star, which is realigned to the new indentation. A line break you wrote is kept, only the whitespace between tokens moves, and formatting the result again returns the same bytes. It checks that brackets, strings, comments and regular expressions are closed but parses no further, so a source it formats can still fail to run; nothing is executed, nothing leaves this page, and a source may be up to 1,000,000 characters.