ECMAScript code beautifier/formatter
ECMAScript code beautifier/formatter.
Live preview: lloiser/esformatter-visualize
This tool is still on early development and is missing support for many important features.
We are looking for contributors!!
This tool could also be reused by other node.js libs like escodegen to format the output (so each lib has a single responsibility).
For more reasoning behind it and history of the project see: esformatter & rocambole
This tool uses rocambole (based on Esprima) to recursively parse the tokens and transform it in place.
- granular control about white spaces, indent and line breaks.
- command line interface (cli).
- be non-destructive.
- support for local/global config file so settings can be shared between team members.
- presets for the most popular style guides (Google, jQuery, Idiomatic.js).
format() method receives a string containing the code that you would like to
format and the configuration options that you would like to use and returns
a string with the result.
var esformatter = require'esformatter';// for a list of available options check "lib/preset/default.json"var options =// inherit from the default presetpreset : 'default'indent :value : ' 'lineBreak :before :// at least one line break before BlockStatementBlockStatement : '>=1'// only one line break before BlockStatementDoWhileStatementOpeningBrace : 1// ...whiteSpace :// ...;var fs = require'fs';var codeStr = fsreadFileSync'path/to/js/file.js'toString;// return a string with the formatted codevar formattedCode = esformatterformatcodeStr options;
or you can use the
transform() method to manipulate an AST in place (allows
pipping other tools that manipulates the AST). - so far only supports
rocambole generated ASTs, but we
will work to fix this limitation in the future (see issue #86).
var inputAST = rocamboleparse'var foo=123;';// you can also pass the formatting options as second argument like the// `format` methodvar outputAST = esformattertransforminputAST;assertoutputAST === inputAST 'edits AST in place';assertoutputASTtoString === 'var foo = 123;' 'formats input';
Used by task runners and/or plugin authors to retrieve the configuration stored
package.json files relative to the
global config file (
~/.esformatter) if it can't find any config file until
the root path.
You can also pass an object with
customOptions to override the default
rc will merge the options from multiple config files.
// will start search from the "foo/bar" directoryvar baseConfig = esformatterrc'foo/bar/baz.js';// will start the search from cwdvar otherConfig = esformatterrc;// merge some custom options to the user settingsvar override = esformatterrcindent: value: '\t';
Register a plugin module.
var plugin =// called once for each node, after the esformatter manipulation;esformatterregisterplugin;
Remove plugin from the execution queue.
Remove all the registered plugins from the execution queue; useful in case you want to edit multiple files using different plugins each time.
You can also use the simple command line interface to process
stdout or read from a file.
npm install -g esformatter
esformatter [OPTIONS] [FILES]Options:-c, --config Path to custom configuration file.-p, --preset Set style guide preset .-h, --help Display help and usage details.-v, --version Display the current version.
# format "test.js" and output result to stdoutesformatter test.js# you can also pipe other shell commands (read file from stdin)cat test.js | esformatter# format "test.js" using options in "options.json" and output result to stdoutesformatter --config options.json test.js# process "test.js" and writes to "test.out.js"esformatter test.js > test.out.js# you can override the default settings, see lib/preset/default.json for# a list of available optionsesformatter test.js --indent.value="\t" --lineBreak.before.IfStatementOpeningBrace=0
For a live preview check esformatter-visualize
esformatter will look for the closest
.esformatter file and use that as
a setting unless you specify
You also have the option to put your
esformatter settings inside the
package.json file under the
Settings from multiple files will be merged until it finds a config file that
contains the property
"root": true; that makes it easy to
define exceptions to the project rules without needing to copy all the shared
properties. - for an example see test files inside the
"preset" property is used to set the
prototype of the config file,
enabling inheritance. For instance, you can say your config inherits from the
jquery preset and only override the settings you need:
PS: the jQuery preset is still under development.
Configuration in esformatter consists of three main building blocks:
Indent is responsible for whitespace at the front of each line.
indent.value is used for each indentation. The default indents with two spaces. Setting
"\t" will switch to indentation using tabs.
0), esformattter will not indent top level function blocks (used by the jQuery preset).
Both of these have
lineBreak's value is
"\n" by default, while whiteSpace uses a single space (
" "). Its unlikely that you ever need to change these.
More interesting are all the properties nested under
Documenting each property here wouldn't be practical. For now we recommend you look at the existing presets (default and jquery) to find the properties you need to adjust for your specific needs. Better yet, adopt one of the presets to avoid having to configure anything beyond the most basic settings (like
lineBreak you can use ranges or integers:
- positive integer (
99): "add or keep
-1: keep original line breaks.
">2": add linebreaks until it's over
">=1": add line breaks until it's equal or greater than
"<2": remove linebreaks until it's smaller than
"<=1": remove/add line breaks until it's smaller or equal to
whiteSpace you can only use positive integers for now (any positive number between
-1 when you want to keep the original value.
Esformatter also have support for plugins (v0.2.0+).
Plugins are automatically loaded from
node_modules if you pass the module id
in the config file:
List of plugins and plugins wish list: https://github.com/millermedeiros/esformatter/wiki/Plugins
You also have the option to
register a plugin programmatically:
var plugin =// transform node here;esformatterregisterplugin;
Plugins are executed in the same order as they are registered (first in, first out).
The plugin methods are executed on the following order:
All plugin methods are optional.
Called once before any manipulation, the object is shared with the esformatter which means you can use this method to override default options if needed.
var options;// override the default settings (objects are passed by reference, changing// the value here will also change the value used by esformatter)optsindentvalue = ' ';// store the options to be used lateroptions = opts;;
A way to replace the input string, it should ALWAYS return a string.
// prepend a variable declaration to the filereturn 'var foo = "bar";\n' + str;;
Replaces the output string.
PS: using regular expressions or string manipulation methods to process code is very error-prone! BEWARE!
// replaces all the occurances of "foo" with "bar" (very naive)return strreplace/foo/g 'bar';;
Called once for each token (eg. Keyword, Punctuator, WhiteSpace, Indent...) before processing the nodes. Can be used to manipulate the token value or add/remove/replace the token or tokens around it.
var tk = require'rocambole-token';if tkisSemiColontoken && tkisSemiColontokennext// remove semicolon if next token is also a semicolontkremovetoken;;
Called once for each token (eg. Keyword, Punctuator, WhiteSpace, Indent...) after processing all the nodes. Can be used to manipulate the token value or add/remove/replace the token or tokens around it.
Called once for each
node of the program (eg. VariableDeclaration,
IfStatement, FunctionExpression...) before the esformatter default
Called once for each
node of the program (eg. VariableDeclaration,
IfStatement, FunctionExpression...) after the esformatter default
var tk = require'rocambole-token';if nodetype === 'FunctionExpression' || nodetype === 'FunctionDeclaration'if nodebody// insert a line break before the function bodytkbeforenodebodystartTokentype: 'LineBreak'value: optionslineBreakvalue;;
Called before esformatter loops through all the nodes, allows plugin authors to modify the AST before esformatter. This is the ideal place to add/replace nodes.
Called after all nodes and tokens are processed, allows overriding all the changes (including indentation).
var rocambole = require'rocambole';// if you need to manipulate multiple nodes you can use the// rocambole.moonwalk or rocambole.recusive methods. we don't do it// automatically since you might have very specific needsrocambolemoonwalkastdoStuffnode;;;
We have an IRC channel #esformatter on irc.freenode.net for quick discussions about the project development/structure.
See project Wiki for more info: https://github.com/millermedeiros/esformatter/wiki
Released under the MIT license