What this tool does
The tool splits your code into tokens the way a JavaScript engine does: names, numbers, strings, template literals with their ${…} parts, regular expressions, punctuators, comments and JSX. Whether a / starts a regex or divides, and whether a < starts a JSX tag, is decided from the token before it, as parsers do. Formatting then lays the tokens out again: one statement per line, braces on the same line as if, function and class, blocks and object literals indented, a space around operators and after commas, and at most one blank line where you had blank lines. Objects and arrays stay on one line when they are short and were written on one line; otherwise they get one item per line. Line breaks you wrote inside an expression, such as a long condition or a chain of .then() calls, are kept and indented. Only whitespace, line breaks and comments ever change: no semicolon is added or removed, quotes and numbers stay as written, and nothing is renamed. Minified mode removes comments, except /*! … */ and @license comments, and every space that cannot matter. It keeps a line break where JavaScript's automatic semicolon insertion depends on it, for example after return or before a line that starts with ++, and a space where two tokens would merge, as in a - -b. The check covers tokens and brackets, not the full grammar: a mistake such as const = 5 is formatted, not reported.
Example input and output
function greet(e){const t=e.trim();if(!t)throw new Error("name is required");return`Hello, ${t}!`}const users=["Ada","Linus"];for(const u of users)console.log(greet(u));function greet(e) {
const t = e.trim();
if (!t) throw new Error("name is required");
return `Hello, ${t}!`
}
const users = ["Ada", "Linus"];
for (const u of users) console.log(greet(u));The return statement has no semicolon in the input, so it has none in the output: adding one would change your code, not just its layout.
export function Price({ amount, currency = "EUR" }) {
const text = formatMoney(amount, currency);
return (
<p className="price">
Total: <strong>{text}</strong>
{amount > 100 && <span className="badge">Free shipping</span>}
</p>
);
}export function Price({ amount, currency = "EUR" }) {
const text = formatMoney(amount, currency);
return (
<p className="price">
Total: <strong>{text}</strong>
{amount > 100 && <span className="badge">Free shipping</span>}
</p>
);
}JSX lines are re-indented by nesting. The space after Total: is part of the text React renders, so it is kept exactly; only whitespace that holds a line break, which JSX ignores, is changed.
/*! widget v2 | MIT */
// Count clicks
let count = 0
const button = document.querySelector("#save")
button.addEventListener("click", () => {
count++
render()
})/*! widget v2 | MIT */let count=0
const button=document.querySelector("#save")
button.addEventListener("click",()=>{count++
render()})This code has no semicolons, so its line breaks end the statements. Joining count++ and render() into one line would be a syntax error, so those breaks stay. The licence comment stays and the other comment goes.
Common errors and fixes
- Unclosed string: the line ends before the closing "
- A quote is missing. A string in single or double quotes cannot span lines, so everything after the opening quote is read as part of it up to the end of the line. Add the closing quote, or use a template literal (`…`) for text over several lines.
- Unclosed {: it has no matching }
- A } is missing, often at the end of a function or an if block. Everything after the { is still inside it, so the formatted output shows the rest of the file indented one level too deep: look for the point where the indentation stops matching what you meant, and add the } there.
- Expected ) to close the ( on line 3, but found }
- Brackets close in the reverse order they were opened. Here a call or condition that starts on line 3 is still open when a } arrives. Add the missing ), or remove the extra }. The message names the line of the opener, so you know which pair is wrong.
- Unclosed ${ in a template literal: there is no } to end it
- A substitution such as ${user.name has no closing }, so the backtick meant to end the template starts a new one instead. Add the }, then check that the template still ends with a backtick.
- Unclosed regular expression: the line ends before the closing /
- A / was read as the start of a regex. If you meant division, a value or a ) is probably missing just before it. If it is a regex, a / inside it must be written \/, unless it is inside a character class like [/].
- Unexpected character “: curly quotes do not start or end strings in JavaScript
- Code copied from a word processor, a slide or a chat app often has “ ” or ‘ ’ instead of straight quotes. Replace them with " or '. The same goes for invisible characters such as zero-width spaces, which the Invisible Character Finder shows.
- Expected </span> to close <span> on line 2, but found </div>
- In JSX every tag must be closed, and in the reverse order it was opened. Add the missing </span>, or write elements without children as <span />. A > or } in JSX text must be written {'>'} or {'}'}.
Common use cases
- Reading a minified bundle or library from a CDN, an npm package or a production build
- Tidying JavaScript copied from DevTools, Stack Overflow, a chat or an AI assistant
- Re-indenting a React component whose JSX was pasted with broken indentation
- Finding the unclosed string, bracket or template literal that breaks everything after it
- Minifying a snippet for a bookmarklet, an inline <script> or a CMS field
- Making two versions of a script comparable before diffing them
Privacy and security notes
- Your code is formatted by JavaScript in this browser tab. It is not sent to DevPrix or stored on a server.
- The code is never run: it is read as text and split into tokens, so formatting a script cannot execute it or make a network request.
- Share copies a link that carries your input after the # in the URL. Browsers do not send that part to servers, but anyone you give the link to can read it.
Frequently asked questions
Can formatting or minifying change what my code does?
It should not. Only whitespace, line breaks and comments change, so the tokens of your code, and the order they come in, stay exactly the same. The one thing that could still change meaning is a line break, because JavaScript inserts semicolons at some of them. The tool only removes a line break where it cannot matter, and only adds one where it cannot matter. This has been checked against TypeScript's parser on 3,730 files (65 MB), most of them from npm packages, including the React DOM, webpack and Babel bundles: the syntax tree was identical after formatting and after minifying, and formatting a second time changed nothing.
Does it support JSX and TypeScript?
JSX, yes: elements, fragments, attributes, spread props and {expressions}, with JSX inside expressions inside JSX. JSX text keeps its meaning, so a space between words or before a tag is never added or removed. TypeScript is formatted on a best-effort basis. Its tokens are the same as JavaScript's, so type annotations, interfaces, generics and enums come out intact, and in practice they are spaced well, but the layout is not tuned for every TypeScript construct. Nothing is type-checked, and Flow is not specifically supported.
Does it check my code for errors?
Partly. It finds problems in tokens and brackets: an unclosed string, template literal, comment or regex, a bracket that is never closed or closes the wrong opener, a mismatched JSX tag, curly quotes and other stray characters. It is not a full parser, so a grammar mistake such as const = 5 or a missing comma between two object properties is formatted, not reported. Your browser's console, Node.js (node --check file.js) or a linter such as ESLint will catch those.
Is this the same as Prettier?
No. Prettier rewraps every expression to fit a line width and adds or removes semicolons, parentheses and quotes to match its style. This tool keeps your code as written and only changes its layout: line breaks you put inside an expression stay, objects and arrays are expanded when they were multi-line or are long, and short ones stay on one line. For a project, use Prettier with a config; to read or tidy one file quickly, without installing anything, use this.
How much smaller does minifying make a file?
It depends on how much of the file is whitespace and comments. Across 1,188 readable files from npm packages, half shrank by 24 to 45 percent, and the median was 34 percent. React DOM's development build goes from 1,065,698 to 694,822 bytes here, 35 percent smaller. Minifiers such as Terser and esbuild save much more, because they also rename variables and rewrite code; this tool never renames or rewrites anything, so the result stays readable enough to debug. Serving files with gzip or Brotli compression saves more than either.
Can it format large files?
Yes. A 1 MB bundle formats in well under a second on a typical laptop. Above 1,000,000 characters the output is shown without syntax highlighting, so the page stays responsive; copy and download still give you the full result.