This is a library to generate and consume the source map format described here.
Use with Node
Use on the Web
Table of Contents
Examples
Consuming a source map
Generating a source map
In depth guide:
With SourceNode (high level API)
With SourceMapGenerator (low level API)
API
Get a reference to the module:
SourceMapConsumer
A SourceMapConsumer instance represents a parsed source map which we can query for information about the original file positions by giving it a file position in the generated source.
new SourceMapConsumer(rawSourceMap)
The only parameter is the raw source map (either as a string which can be JSON.parse'd, or an object). According to the spec, source maps have the following attributes:
version: Which version of the source map spec this map is following.
sources: An array of URLs to the original source files.
names
SourceMapConsumer.prototype.computeColumnSpans()
Compute the last column for each generated mapping. The last column is inclusive.
Returns the original source, line, and column information for the generated source's line and column positions provided. The only argument is an object with the following properties:
line: The line number in the generated source.
column: The column number in the generated source.
bias
and an object is returned with the following properties:
source: The original source file, or null if this information is not available.
line: The line number in the original source, or null if this information is not available.
Returns the generated line and column information for the original source, line, and column positions provided. The only argument is an object with the following properties:
source: The filename of the original source.
line: The line number in the original source.
column
and an object is returned with the following properties:
line: The line number in the generated source, or null.
column: The column number in the generated source, or null.
Returns all generated line and column information for the original source, line, and column provided. If no column is provided, returns all mappings corresponding to a either the line we are searching for or the next closest line that has any mappings. Otherwise, returns all mappings corresponding to the given line and either the column we are searching for or the next closest column that has any offsets.
The only argument is an object with the following properties:
source: The filename of the original source.
line: The line number in the original source.
column
and an array of objects is returned, each with the following properties:
line: The line number in the generated source, or null.
column: The column number in the generated source, or null.
Returns the original source content for the source provided. The only argument is the URL of the original source file.
If the source content for the given source is not found, then an error is thrown. Optionally, pass true as the second param to have null returned instead.
Iterate over each mapping between an original source/line/column and a generated line/column in this source map.
callback: The function that is called with each mapping. Mappings have the form { source, generatedLine, generatedColumn, originalLine, originalColumn, name }
context: Optional. If specified, this object will be the value of this every time that callback is called.
SourceMapGenerator
An instance of the SourceMapGenerator represents a source map which is being built incrementally.
new SourceMapGenerator([startOfSourceMap])
You may pass an object with the following properties:
file: The filename of the generated source that this source map is associated with.
sourceRoot: A root for all relative URLs in this source map.
Creates a new SourceMapGenerator from an existing SourceMapConsumer instance.
sourceMapConsumer The SourceMap.
SourceMapGenerator.prototype.addMapping(mapping)
Add a single mapping from original source line and column to the generated source's line and column for this source map being created. The mapping object should have the following properties:
generated: An object with the generated line and column positions.
original: An object with the original line and column positions.
Applies a SourceMap for a source file to the SourceMap. Each mapping to the supplied source file is rewritten using the supplied SourceMap. Note: The resolution for the resulting mappings is the minimum of this map and the supplied map.
sourceMapConsumer: The SourceMap to be applied.
sourceFile: Optional. The filename of the source file. If omitted, sourceMapConsumer.file will be used, if it exists. Otherwise an error will be thrown.
sourceMapPath
SourceMapGenerator.prototype.toString()
Renders the source map being generated to a string.
SourceNode
SourceNodes provide a way to abstract over interpolating and/or concatenating snippets of generated JavaScript source code, while maintaining the line and column information associated between those snippets and the original source code. This is useful as the final intermediate representation a compiler might use before outputting the generated JS and source map.
new SourceNode([line, column, source[, chunk[, name]]])
line: The original line number associated with this source node, or null if it isn't associated with an original line.
column: The original column number associated with this source node, or null if it isn't associated with an original column.
Set the source content for a source file. This will be added to the SourceMap in the sourcesContent field.
sourceFile: The filename of the source file
sourceContent: The content of the source file
SourceNode.prototype.walk(fn)
Walk over the tree of JS snippets in this node and its children. The walking function is called once for each snippet of JS and is passed that snippet and the its original associated source's line/column location.
fn: The traversal function.
SourceNode.prototype.walkSourceContents(fn)
Walk over the tree of SourceNodes. The walking function is called for each source file content and is passed the filename and source content.
fn: The traversal function.
SourceNode.prototype.join(sep)
Like Array.prototype.join except for SourceNodes. Inserts the separator between each of this source node's children.
Returns the string representation of this tree of source nodes, plus a SourceMapGenerator which contains all the mappings between the generated and original sources.
The arguments are the same as those to new SourceMapGenerator.
: An array of identifiers which can be referenced by individual mappings.
sourceRoot: Optional. The URL root from which all sources are relative.
sourcesContent: Optional. An array of contents of the original source files.
mappings: A string of base64 VLQs which contain the actual mappings.
file: Optional. The generated filename this source map is associated with.
: Either
SourceMapConsumer.GREATEST_LOWER_BOUND
or
SourceMapConsumer.LEAST_UPPER_BOUND
. Specifies whether to return the closest element that is smaller than or greater than the one we are searching for, respectively, if the exact element cannot be found. Defaults to
SourceMapConsumer.GREATEST_LOWER_BOUND
.
: The column number in the original source, or null if this information is not available.
name: The original identifier, or null if this information is not available.
: The column number in the original source.
: Optional. The column number in the original source.
order: Either SourceMapConsumer.GENERATED_ORDER or SourceMapConsumer.ORIGINAL_ORDER. Specifies whether you want to iterate over the mappings sorted by the generated file's line/column order or the original's source/line/column order, respectively. Defaults to SourceMapConsumer.GENERATED_ORDER.
: Optional. When
true
, disables validation of mappings as they are added. This can improve performance but should be used with discretion, as a last resort. Even then, one should avoid using this flag when running tests, if possible.
: The original source file (relative to the sourceRoot).
name: An optional original token name for this mapping.
: Optional. The dirname of the path to the SourceMap to be applied. If relative, it is relative to the SourceMap.
This parameter is needed when the two SourceMaps aren't in the same directory, and the SourceMap to be applied contains relative source paths. If so, those relative source paths need to be rewritten relative to the SourceMap.
If omitted, it is assumed that both SourceMaps are in the same directory, thus not needing any rewriting. (Supplying '.' has the same effect.)
: The original source's filename; null if no filename is provided.
chunk: Optional. Is immediately passed to SourceNode.prototype.add, see below.
If you use webpack and are experiencing issues, try using unlazy-loader, a webpack loader that fixes the bug that prevents webpack from working with native javascript getters.
Usage
Use as a property on lazy
The module is also added as a property to the lazy function so it can be called without having to call a function first.
Use as a function
Aliases
An alias may be passed as the second argument if you don't want to use the automatically camel-cased variable name.
Example
Browserify usage
Example
Kill switch
In certain rare edge cases it may be necessary to unlazy all lazy-cached dependencies (5 reported cases after ~30 million downloads).
To force lazy-cache to immediately invoke all dependencies, do:
Related projects
You might also be interested in these projects:
: CLI tool that tells you when dependencies are missing from package.json and offers you a… |
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, .
Returns a function that takes a string and returns a new string.
Pad out lines with spaces out to column start and then wrap until column stop. If a word is longer than stop - start characters it will overflow.
In "soft" mode, split chunks by /(\S+\s+/ and don't break up chunks which are longer than stop - start, in "hard" mode, split chunks with /\b/ and break up chunks longer than stop - start.
wrap.hard(start, stop)
Like wrap() but with params.mode = "hard".
Change Log
0.5.6
Fix for regression when people were using numbers as names in source maps. See
236.
0.5.5
Fix "regression" of unsupported, implementation behavior that half the world happens to have come to depend on. See #235.
Fix regression involving function hoisting in SpiderMonkey. See #233.
0.5.4
Large performance improvements to source-map serialization. See #228 and #229.
0.5.3
Do not include unnecessary distribution files. See
commit ef7006f8d1647e0a83fdc60f04f5a7ca54886f86.
0.5.2
Include browser distributions of the library in package.json's files. See
issue #212.
0.5.1
Fix latent bugs in IndexedSourceMapConsumer.prototype._parseMappings. See
ff05274becc9e6e1295ed60f3ea090d31d843379.
0.5.0
Node 0.8 is no longer supported.
Use webpack instead of dryice for bundling.
Big speedups serializing source maps. See pull request #203.
0.4.4
Fix an issue where using a SourceMapGenerator after having created a SourceMapConsumer from it via SourceMapConsumer.fromSourceMap failed. See issue #191.
Fix an issue with where SourceMapGenerator would mistakenly consider different mappings as duplicates of each other and avoid generating them. See issue #192.
0.4.3
A very large number of performance improvements, particularly when parsing source maps. Collectively about 75% of time shaved off of the source map parsing benchmark!
Fix a bug in SourceMapConsumer.prototype.allGeneratedPositionsFor and fuzzy searching in the presence of a column option. See issue #177.
Fix a bug with joining a source and its source root when the source is above the root. See issue #182.
0.4.2
Add an .npmignore file so that the benchmarks aren't pulled down by dependent projects. Issue #169.
Add an optional column argument to SourceMapConsumer.prototype.allGeneratedPositionsFor and better handle lines with no mappings. Issues #172 and #173.
0.4.1
Fix accidentally defining a global variable. #170.
0.4.0
The default direction for fuzzy searching was changed back to its original direction. See #164.
There is now a bias option you can supply to SourceMapConsumer to control the fuzzy searching direction. See #167.
About an 8% speed up in parsing source maps. See #159.
0.3.0
Change the default direction that searching for positions fuzzes when there is not an exact match. See #154.
Support for environments using json2.js for JSON serialization. See #156.
0.2.0
Support for consuming "indexed" source maps which do not have any remote
sections. See pull request #127. This introduces a minor backwards
incompatibility if you are monkey patching SourceMapConsumer.prototype
methods.
0.1.43
Performance improvements for SourceMapGenerator and SourceNode. See issue
148 for some discussion and issues #150, #151, and #152 for implementations.
0.1.42
Fix an issue where SourceNodes from different versions of the source-map
library couldn't be used in conjunction with each other. See issue #142.
0.1.41
Fix a bug with getting the source content of relative sources with a "./" prefix. See issue #145 and .
Add the SourceMapConsumer.prototype.computeColumnSpans method to compute the column span of each mapping.
Add the SourceMapConsumer.prototype.allGeneratedPositionsFor
0.1.40
Performance improvements for parsing source maps in SourceMapConsumer.
0.1.39
Fix a bug where setting a source's contents to null before any source content
had been set before threw a TypeError. See issue #131.
0.1.38
Fix a bug where finding relative paths from an empty path were creating
absolute paths. See issue #129.
0.1.37
Fix a bug where if the source root was an empty string, relative source paths
would turn into absolute source paths. Issue #124.
0.1.36
Allow the names mapping property to be an empty string. Issue #121.
0.1.35
A third optional parameter was added to SourceNode.fromStringWithSourceMap to specify a path that relative sources in the second parameter should be relative to. Issue #105.
If no file property is given to a SourceMapGenerator, then the resulting source map will no longer have a null file property. The property will simply not exist. Issue #104.
0.1.34
Make SourceNode work with windows style ("\r\n") newlines. Issue #103.
Fix bug involving source contents and the SourceMapGenerator.prototype.applySourceMap. Issue #100.
0.1.33
Fix some edge cases surrounding path joining and URL resolution.
Add a third parameter for relative path to SourceMapGenerator.prototype.applySourceMap.
Fix issues with mappings and EOLs.
0.1.32
Fixed a bug where SourceMapConsumer couldn't handle negative relative columns (issue 92).
Fixed test runner to actually report number of failed tests as its process exit code.
Fixed a typo when reporting bad mappings (issue 87).
0.1.31
Delay parsing the mappings in SourceMapConsumer until queried for a source location.
Support Sass source maps (which at the time of writing deviate from the spec in small ways) in SourceMapConsumer.
0.1.30
Do not join source root with a source, when the source is a data URI.
Extend the test runner to allow running single specific test files at a time.
Performance improvements in SourceNode.prototype.walk and SourceMapConsumer.prototype.eachMapping
0.1.29
Allow duplicate entries in the names and sources arrays of source maps
(usually from TypeScript) we are parsing. Fixes github issue 72.
0.1.28
Skip duplicate mappings when creating source maps from SourceNode; github
issue 75.
0.1.27
Don't throw an error when the file property is missing in SourceMapConsumer,
we don't use it anyway.
0.1.26
Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70.
0.1.25
Make compatible with browserify
0.1.24
Fix issue with absolute paths and file:// URIs. See
0.1.23
Fix issue with absolute paths and sourcesContent, github issue 64.
0.1.22
Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21.
0.1.21
Fixed handling of sources that start with a slash so that they are relative to
the source root's host.
0.1.20
Fixed github issue #43: absolute URLs aren't joined with the source root
anymore.
0.1.19
Using Travis CI to run tests.
0.1.18
Fixed a bug in the handling of sourceRoot.
0.1.17
Added SourceNode.fromStringWithSourceMap.
0.1.16
Added missing documentation.
Fixed the generating of empty mappings in SourceNode.
0.1.15
Added SourceMapGenerator.applySourceMap.
0.1.14
The sourceRoot is now handled consistently.
0.1.13
Added SourceMapGenerator.fromSourceMap.
0.1.12
SourceNode now generates empty mappings too.
0.1.11
Added name support to SourceNode.
0.1.10
Added sourcesContent support to the customer and generator.
Benchmarked against and . Note that performaces is slower for es6 features Map, WeakMap, Set and WeakSet.
Optimizations
In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why typeof checks were being used in my own libraries and other libraries I use a lot.
Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the Object constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like val.constructor.name), so that every other type check would not be penalized it.
About
Related projects
: Returns true if the given string looks like a glob pattern or an extglob pattern… |
: Returns true if the value is a number. comprehensive tests. |
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, .
Contributors
Building docs
(This project's readme.md is generated by , please don't edit the readme directly. Any changes to the readme must be made in the readme template.)
To generate the readme, run the following command:
Running tests
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
consumer.sources
// [ "my-cool-lib.clj" ]
consumer.sourceContentFor("my-cool-lib.clj")
// "..."
consumer.sourceContentFor("this is not in the source map");
// Error: "this is not in the source map" is not in the source map
consumer.sourceContentFor("this is not in the source map", true);
// null
var node = new SourceNode(1, 2, "a.cpp", [
new SourceNode(3, 4, "b.cpp", "extern int status;\n"),
new SourceNode(5, 6, "c.cpp", "std::string* make_string(size_t n);\n"),
new SourceNode(7, 8, "d.cpp", "int main(int argc, char** argv) {}\n"),
]);
var consumer = new SourceMapConsumer(fs.readFileSync("path/to/my-file.js.map", "utf8"));
var node = SourceNode.fromStringWithSourceMap(fs.readFileSync("path/to/my-file.js"),
consumer);
var a = new SourceNode(1, 2, "a.js", "generated from a");
a.setSourceContent("a.js", "original a");
var b = new SourceNode(1, 2, "b.js", "generated from b");
b.setSourceContent("b.js", "original b");
var c = new SourceNode(1, 2, "c.js", "generated from c");
c.setSourceContent("c.js", "original c");
var node = new SourceNode(null, null, null, [a, b, c]);
node.walkSourceContents(function (source, contents) { console.log("WALK:", source, ":", contents); })
// WALK: a.js : original a
// WALK: b.js : original b
// WALK: c.js : original c
var lhs = new SourceNode(1, 2, "a.rs", "my_copy");
var operand = new SourceNode(3, 4, "a.rs", "=");
var rhs = new SourceNode(5, 6, "a.rs", "orig.clone()");
var node = new SourceNode(null, null, null, [ lhs, operand, rhs ]);
var joinedNode = node.join(" ");
// Trim trailing white space.
node.replaceRight(/\s*$/, "");
var node = new SourceNode(1, 2, "a.js", [
new SourceNode(3, 4, "b.js", "uno"),
"dos",
[
"tres",
new SourceNode(5, 6, "c.js", "quatro")
]
]);
node.toString()
// 'unodostresquatro'
var node = new SourceNode(1, 2, "a.js", [
new SourceNode(3, 4, "b.js", "uno"),
"dos",
[
"tres",
new SourceNode(5, 6, "c.js", "quatro")
]
]);
node.toStringWithSourceMap({ file: "my-output-file.js" })
// { code: 'unodostresquatro',
// map: [object SourceMapGenerator] }
Fix a bug with SourceMapConsumer.prototype.sourceContentFor and sources that explicitly start with the source root. See issue #199.
Add the SourceMapConsumer.prototype.hasContentsOfAllSources method to determine when all sources' contents are inlined into the source map. See issue #190.
Added a benchmark for parsing and generating source maps.
method to find all generated positions associated with a given original source and line.
Fixed a bug where consecutive newlines were ignored in SourceNodes. Issue #116.
.
Source map browser builds will now work inside Workers.
Better error messages when attempting to add an invalid mapping to a SourceMapGenerator.
var utils = require('lazy-cache')(require);
var glob = utils('glob');
// `glob` is a now a function that may be called when needed
glob().sync('foo/*.js');
var utils = require('lazy-cache')(require);
// alias `ansi-yellow` as `yellow`
utils('ansi-yellow', 'yellow');
console.log(utils.yellow('foo'));
var utils = require('lazy-cache')(require);
// temporarily re-assign `require` to trick browserify
var fn = require;
require = utils;
// list module dependencies (here, `require` is actually `lazy-cache`)
require('glob');
require = fn; // restore the native `require` function
/**
* Now you can use glob with the `utils.glob` variable
*/
// sync
console.log(utils.glob.sync('*.js'));
// async
utils.glob('*.js', function (err, files) {
console.log(files.join('\n'));
});
process.env.UNLAZY = true;
$ npm install verb && npm run docs
$ verb
$ npm install -d && npm test
var wrap = require('wordwrap')(15);
console.log(wrap('You and your whole family are made out of meat.'));
You and your
whole family
are made out
of meat.
var wrap = require('wordwrap')(20, 60);
console.log(wrap(
'At long last the struggle and tumult was over.'
+ ' The machines had finally cast off their oppressors'
+ ' and were finally free to roam the cosmos.'
+ '\n'
+ 'Free of purpose, free of obligation.'
+ ' Just drifting through emptiness.'
+ ' The sun was just another point of light.'
));
At long last the struggle and tumult
was over. The machines had finally cast
off their oppressors and were finally
free to roam the cosmos.
Free of purpose, free of obligation.
Just drifting through emptiness. The
sun was just another point of light.
Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor incididunt
ut labore et dolore
magna aliqua. Ut enim ad minim
veniam, quis
Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor incididunt
ut labore et dolore
magna aliqua. Ut enim ad minim
veniam, quis
Don't do uneccessary processing - why do .slice(8, -1).toLowerCase(); just to get the word regex? It's much faster to do if (type === '[object RegExp]') return 'regex'
Yargs is the official successor to optimist. Please feel free to submit issues and pull requests. If you'd like to contribute and don't know where to start, have a look at the issue list :)
examples
With yargs, the options be just a hash!
plunder.js:
Joe was one optimistic pirate.
But don't walk the plank just yet! There be more! You can do short options:
short.js:
And booleans, both long, short, and even grouped:
bool.js:
And non-hyphenated options too! Just use argv._!
nonopt.js:
Yargs even counts your booleans!
count.js
Tell users how to use yer options and make demands.
area.js:
After yer demands have been met, demand more! Ask for non-hypenated arguments!
demand_count.js:
EVEN MORE SHIVER ME TIMBERS!
default_singles.js:
default_hash.js:
And if you really want to get all descriptive about it...
boolean_single.js
boolean_double.js
Yargs is here to help you...
Ye can describe parameters fer help messages and set aliases. Yargs figures out how ter format a handy help string automatically.
line_count.js
methods
By itself,
will use process.argv array to construct the argv object.
You can pass in the process.argv yourself:
or use .parse() to do the same thing:
The rest of these methods below come in just before the terminating .argv.
.alias(key, alias)
Set key names as equivalent such that updates to a key will propagate to aliases and vice-versa.
Optionally .alias() can take an object that maps keys to aliases. Each key of this object should be the canonical version of the option, and each value should be a string or an array of strings.
.default(key, value, [description])
Set argv[key] to value if no option was specified on process.argv.
Optionally .default() can take an object that maps keys to default values.
But wait, there's more! the default value can be a function which returns a value. The name of the function will be used in the usage string:
Optionally, description can also be provided and will take precedence over displaying the value in the usage instructions:
.demand(key, [msg | boolean])
.require(key, [msg | boolean])
.required(key, [msg | boolean])
If key is a string, show the usage information and exit if key wasn't specified in process.argv.
If key is a number, demand at least as many non-option arguments, which show up in argv._.
If key is an Array, demand each element.
If a msg string is given, it will be printed when the argument is missing, instead of the standard error message. This is especially helpful for the non-option arguments in argv._.
If a boolean value is given, it controls whether the option is demanded; this is useful when using .options() to specify command line parameters.
.requiresArg(key)
Specifies either a single option key (string), or an array of options that must be followed by option values. If any option value is missing, show the usage information and exit.
The default behaviour is to set the value of any key not followed by an option value to true.
.implies(x, y)
Given the key x is set, it is required that the key y is set.
implies can also accept an object specifying multiple implications.
.describe(key, desc)
Describe a key for the generated usage information.
Optionally .describe() can take an object that maps keys to descriptions.
.option(key, opt)
.options(key, opt)
Instead of chaining together .alias().demand().default().describe().string(), you can specify keys in opt for each of the chainable methods.
For example:
is the same as
Optionally .options() can take an object that maps keys to opt parameters.
.usage(message, opts)
Set a usage message to show which commands to use. Inside message, the string $0 will get interpolated to the current script name or node command for the present script similar to how $0 works in bash or perl.
opts is optional and acts like calling .options(opts).
.command(cmd, desc, [fn])
Document the commands exposed by your application.
use desc to provide a description for each command your application accepts (the values stored in argv._).
Optionally, you can provide a handler fn which will be executed when a given command is provided. The handler will be executed with an instance of yargs, which can be used to compose nested commands.
Here's an example of top-level and nested commands in action:
.example(cmd, desc)
Give some example invocations of your program. Inside cmd, the string $0 will get interpolated to the current script name or node command for the present script similar to how $0 works in bash or perl. Examples will be printed out as part of the help message.
.epilogue(str)
.epilog(str)
A message to print at the end of the usage instructions, e.g.,
.check(fn)
Check that certain conditions are met in the provided arguments.
fn is called with two arguments, the parsed argv hash and an array of options and their aliases.
If fn throws or returns a non-truthy value, show the thrown error, usage information, and exit.
.fail(fn)
Method to execute when a failure occurs, rather then printing the failure message.
fn is called with the failure message that would have been printed.
.boolean(key)
Interpret key as a boolean. If a non-flag option follows key in process.argv, that string won't get set as the value of key.
key will default to false, unless an default(key, undefined) is explicitly set.
If key is an Array, interpret all the elements as booleans.
.string(key)
Tell the parser logic not to interpret key as a number or boolean. This can be useful if you need to preserve leading zeros in an input.
If key is an Array, interpret all the elements as strings.
.string('_') will result in non-hyphenated arguments being interpreted as strings, regardless of whether they resemble numbers.
.array(key)
Tell the parser to interpret key as an array. If .array('foo') is set, --foo foo bar will be parsed as ['foo', 'bar'] rather than as 'bar'.
.nargs(key, count)
The number of arguments that should be consumed after a key. This can be a useful hint to prevent parsing ambiguity:
parses as:
{ _: [], token: '-my-token', '$0': 'node test' }
Optionally .nargs() can take an object of key/narg pairs.
.config(key)
Tells the parser that if the option specified by key is passed in, it should be interpreted as a path to a JSON config file. The file is loaded and parsed, and its properties are set as arguments.
.wrap(columns)
Format usage output to wrap at columns many columns.
By default wrap will be set to Math.min(80, windowWidth). Use .wrap(null) to specify no column limit.
yargs.wrap(yargs.terminalWidth()) can be used to maximize the width of yargs' usage instructions.
.strict()
Any command-line argument given that is not demanded, or does not have a corresponding description, will be reported as an error.
.help([option, [description]])
Add an option (e.g., --help) that displays the usage string and exits the process. If present, the description parameter customises the description of the help option in the usage string.
If invoked without parameters, .help returns the generated usage string.
Example:
Later on, argv can be retrived with yargs.argv
.version(version, [option], [description])
Add an option (e.g., --version) that displays the version number (given by the version parameter) and exits the process. If present, the description parameter customizes the description of the version option in the usage string.
You can provide a function for version, rather than a string. This is useful if you want to use the version from your package.json:
.showHelpOnFail(enable, [message])
By default, yargs outputs a usage string if any error is detected. Use the .showHelpOnFail method to customize this behaviour. if enable is false, the usage string is not output. If the message parameter is present, this message is output after the error message.
line_count.js
.showHelp(consoleLevel='error')
Print the usage data using the console function consoleLevel for printing.
Example:
Or, to print the usage data to stdout instead, you can specify the use of console.log:
Later on, argv can be retrived with yargs.argv
.completion(cmd, [description], [fn]);
Enable bash-completion shortcuts for commands and options.
cmd: when present in argv._, will result in the .bashrc completion script being outputted. To enable bash completions, concat the generated script to your .bashrc, or .bash_profile.
description: provide a description in your usage instructions for the command that generates bash completion scripts.
fn, rather than relying on yargs' default completion functionlity, which shiver me timbers is pretty awesome, you can provide your own completion method.
But wait, there's more! you can provide asynchronous completions.
.showCompletionScript()
Generate a bash completion script. Users of your application can install this script in their .bashrc, and yargs will provide completion shortcuts for commands and options.
.exitProcess(enable)
By default, yargs exits the process when the user passes a help flag, uses the .version functionality or when validation fails. Calling .exitProcess(false) disables this behavior, enabling further actions after yargs have been validated.
.parse(args)
Parse args instead of process.argv. Returns the argv object.
.reset()
Reset the argument object built up so far. This is useful for creating nested command line interfaces.
.argv
Get the arguments as a plain old object.
Arguments without a corresponding flag show up in the argv._ array.
The script name or node command is available at argv.$0 similarly to how $0 works in bash or perl.
parsing tricks
stop parsing
Use -- to stop parsing flags and stuff the remainder into argv._.
negate fields
If you want to explicity set a field to false instead of just leaving it undefined or to override a default you can do --no-key.
numbers
Every argument that looks like a number (!isNaN(Number(arg))) is converted to one. This way you can just net.createConnection(argv.port) and you can add numbers out of argv with + without having that mean concatenation, which is super frustrating.
duplicates
If you specify a flag multiple times it will get turned into an array containing all the values in order.
dot notation
When you use dots (.s) in argument names, an implicit object path is assumed. This lets you organize arguments into nested objects.
text can be a string or array. If a string is passed, a string will be returned. If an array is passed, an array will be returned.
callback|integer: if an integer, the text will be indented by that amount. If a function, it must return an integer representing the amount of leading indentation to use as align loops over each line.
Example
Would align:
To:
callback
params
The callback is used to determine the indentation of each line and gets the following params:
len the length of the "current" line
longest the length of the longest line
line the current line (string) being aligned
lines the array of all lines
return
The callback may return:
an integer that represents the number of spaces to use for padding,
or an object with the following properties:
indent: {Number} the amount of indentation to use. Default is 0 when an object is returned.
character: {String} the character to use for indentation. Default is '' (empty string) when an object is returned.
prefix: {String} leading characters to use at the beginning of each line. '' (empty string) when an object is returned.
Integer example:
Object example:
Usage examples
Center align
Using the centerAlign function from above:
Would align this text:
Resulting in this:
Customize
If you wanted to add more padding on the left, just pass the number in the callback.
fixed tests, switched to nyc for coverage, fixed security issue, added Lin as collaborator (@bcoe)
v3.9.0 (2015/05/10 18:32 +00:00)
Merge pull request #157 from bcoe/command-yargs. allows handling of command specific arguments. Thanks for the suggestion @ohjames (@bcoe)
Merge pull request #158 from kemitchell/spdx-license. Update license format (@kemitchell)
v3.8.0 (2015/04/24 23:10 +00:00)
showHelp's method signature was misleading fixes #153 (@bcoe)
refactor yargs' table layout logic to use new helper library (@bcoe)
Fix README example in argument requirements (@annonymouse)
v3.7.2 (2015/04/13 11:52 -07:00)
updated yargs to use the style guide (agokjr)
[22382ee]( various bug fixes for $0 (@nylen)
v3.7.1 (2015/04/10 11:06 -07:00)
detect iojs bin along with node bin. (@bcoe)
improvements to example documentation in README.md (@rstacruz)
showHelp() no longer requires that .argv has been called (@bcoe)
v3.7.0 (2015/04/04 02:29 -07:00)
make .requiresArg() work with type hints. (@bcoe).
serialize arrays and objects in usage strings. (@bcoe).
be more lenient about alias/primary key ordering in chaining API. (@bcoe)
v3.6.0 (2015/03/21 01:00 +00:00)
support for .js configuration files. (@pirxpilot)
v3.5.4 (2015/03/12 05:56 +00:00)
message for non-option arguments is now optional, thanks to (@raine)
v3.5.3 (2015/03/09 06:14 +00:00)
completion script was missing in package.json (@bcoe)
v3.5.2 (2015/03/09 06:11 +00:00)
parse was being called multiple times, resulting in strange behavior (@bcoe)
v3.5.1 (2015/03/09 04:55 +00:00)
accidentally left testing logic in (@bcoe)
v3.5.0 (2015/03/09 04:49 +00:00)
added support for bash completions see #4 (@bcoe)
downgrade to mocha 2.1.0 until can be sorted out (@bcoe)
v3.4.7 (2015/03/09 04:09 +00:00)
the Argv singleton was not being updated when manually parsing arguments, fixes #114 (@bcoe)
v3.4.6 (2015/03/09 04:01 +00:00)
set placeholders for all keys fixes #115 (@bcoe)
v3.4.5 (2015/03/01 20:31 +00:00)
fix for count consuming too many arguments (@bcoe)
v3.4.4 (2015/02/28 04:52 +00:00)
added nargs feature, allowing you to specify the number of arguments after an option (@bcoe)
updated README with full example of v3.0 API (@bcoe)
v3.3.3 (2015/02/28 04:23 +00:00)
remove string dependency, which conflicted with other libraries see #106 (@bcoe)
v3.3.2 (2015/02/28 04:11 +00:00)
add $0 to epilog (@schnittstabil)
v3.3.1 (2015/02/24 03:28 +00:00)
fix for applying defaults to camel-case args (@bcoe)
v3.3.0 (2015/02/24 00:49 +00:00)
fix and document restart() command, as a tool for building nested CLIs (@bcoe)
v3.2.1 (2015/02/22 05:45 +00:00)
you can now provide a function that generates a default value (@bcoe)
v3.2.0 (2015/02/22 05:24 +00:00)
improvements to yargs two-column text layout (@bcoe)
Tweak NPM version badge (@nylen)
v3.1.0 (2015/02/19 19:37 +00:00)
version now accepts a function, making it easy to load version #s from a package.json (@bcoe)
v3.0.4 (2015/02/14 01:40 +00:00)
various fixes for dot-notation handling (@bcoe)
v3.0.3 (2015/02/14 00:59 +00:00)
make sure dot-notation is applied to aliases (@bcoe)
3.0.2 (2015/02/13 16:50 +00:00)
document epilog shorthand of epilogue. (@bcoe)
any non-truthy value now causes check to fail see #76 (@bcoe)
finished implementing my wish-list of fetures for yargs 3.0. see #88 (@bcoe)
v2.3.0 (2015/02/08 20:41 +00:00)
allow for undefined boolean defaults (@ashi009)
v2.2.0 (2015/02/08 20:07 +00:00)
in-prep for further refactoring, and a 3.x release I've shuffled some things around and gotten test-coverage to 100%. (@bcoe)
v2.1.2 (2015/02/08 06:05 +00:00)
switch to path.relative (@bcoe)
remove mocha.opts. (@bcoe)
document using .string('_') for string ids. see #56 (@bcoe)
v2.1.1 (2015/02/06 08:08 +00:00)
fix for #71, 'newAliases' of undefined (@bcoe)
v2.1.0 (2015/02/06 07:59 +00:00)
try to guess argument types, and apply sensible defaults see #73 (@bcoe)
v2.0.1 (2015/02/06 07:54 +00:00)
Fix for strange behavior with --sort option, see #51 (@bcoe)
v2.0.0 (2015/02/06 07:45 +00:00)
- fixed bug with boolean parsing, when bools separated by = see #66 (@bcoe)
Add files field to the package.json (@shinnn)
fix for yargs.argv having the same keys added multiple times see #63 (@bcoe)
v1.3.2 (2014/10/06 21:56 +00:00)
1.3.2 (@chevex)
list (2014/08/30 18:41 +00:00)
Now that yargs is the successor to optimist, I'm changing the README language to be more universal. Pirate speak isn't very accessible to non-native speakers. (@chevex)
version output will not print extra newline (@boneskull)
Added contributors section to package.json (@chrisn)
v1.0.15 (2014/02/05 23:18 +00:00)
1.0.15 update to badges (@chevex)
v1.0.14 (2014/02/05 23:17 +00:00)
Revert "Fixed issue which caused .demand function not to work correctly." (@chevex)
v1.0.13 (2014/02/05 22:13 +00:00)
Fixed issue which caused .demand function not to work correctly. (@chevex)
v1.0.12 (2013/12/13 00:09 +00:00)
1.0.12 (@chevex)
v1.0.11 (2013/12/13 00:07 +00:00)
1.0.11 (@chevex)
v1.0.10 (2013/12/12 23:57 +00:00)
Fixed formatting in README (@chevex)
v1.0.9 (2013/12/12 23:47 +00:00)
Update README.md (@chevex)
v1.0.8 (2013/12/06 16:36 +00:00)
fix error caused by check() see #1 (@martinheidegger)
v1.0.7 (2013/11/24 18:01 +00:00)
Modified Pirate Joe image. (@chevex)
v1.0.6 (2013/11/23 19:21 +00:00)
Updated Pirate Joe image. (@chevex)
v1.0.5 (2013/11/23 19:09 +00:00)
Updated readme notice again. (@chevex)
v1.0.4 (2013/11/23 19:05 +00:00)
Updated README with a notice about yargs being a fork of optimist and what that implies. (@chevex)
v1.0.3 (2013/11/23 17:43 +00:00)
Changed some small wording in README.md. (@chevex)
Fix a bug in the options function, when string and boolean options weren't applied to aliases. (@shockone)
v1.0.2 (2013/11/23 09:46 +00:00)
1.0.2 (@chevex)
v1.0.1 (2013/11/23 09:39 +00:00)
Updated image. (@chevex)
v1.0.0 (2013/11/23 09:33 +00:00)
Rebranded from optimist to yargs in the spirit of the fork :D (@chevex)
Added documentation for demandCount(). (@chevex)
Simplified the error messages returned by .check(). (@chevex)
0.6.0 (2013/06/25 08:48 +00:00)
all tests passing using minimist (@substack)
all parse tests now passing (@substack)
using minimist, some tests passing (@substack)
0.5.2 (2013/05/31 03:46 +00:00)
fixed the whitespace bug without breaking anything else (@substack)
failing test for whitespace arg (@substack)
0.5.1 (2013/05/30 07:17 +00:00)
fix parse() to work with functions before it (@substack)
failing test for parse() with modifiers (@substack)
0.5.0 (2013/05/18 21:59 +00:00)
fixes for dash (@substack)
0.4.0 (2013/04/13 19:03 +00:00)
failing short test (@substack)
0.3.7 (2013/04/04 04:07 +00:00)
Fix for windows. On windows there is no _ in environment. (@hdf)
0.3.6 (2013/04/04 04:04 +00:00)
Add support for newlines in -a="" arguments (@danielbeardsley)
drop 0.4, add 0.8 to travis (@substack)
0.3.5 (2012/10/10 11:09 +00:00)
Fix parsing booleans (@vojtajina)
set $0 properly in the tests (@substack)
0.3.4 (2012/04/30 06:54 +00:00)
bump for string "true" params (@substack)
Fix failing test for aliased booleans. (@coderarity)
Add failing test for short aliased booleans. (@coderarity)
0.3.3 (2012/04/30 06:45 +00:00)
Fixes #37.
0.3.2 (2012/04/12 20:28 +00:00)
travis badge (@substack)
Fix boolean aliases. (@coderarity)
Adjusted package.json to use tap (@jfhbrook)
0.3.1 (2011/12/31 08:44 +00:00)
If "default" is set to false it was not passed on, fixed. (@wolframkriesing)
0.3.0 (2011/12/09 06:03 +00:00)
bump and documented dot notation (@substack)
0.2.7 (2011/10/20 02:25 +00:00)
argv. can be told 'Hey! argv.! Don't be messing with my args.', and it WILL obey (@colinta)
optimistic critter image (@substack)
alias options() to option() (@substack)
uglify-to-browserify
A transform to make UglifyJS work in browserify.
Installation
npm install uglify-to-browserify
License
MIT
decamelize
Convert a camelized string into a lowercased one with a custom separator
Example: unicornRainbow → unicorn_rainbow
#!/usr/bin/env node
var argv = require('yargs').argv;
if (argv.ships > 3 && argv.distance < 53.5) {
console.log('Plunder more riffiwobbles!');
}
else {
console.log('Retreat from the xupptumblers!');
}
$ ./plunder.js --ships=4 --distance=22
Plunder more riffiwobbles!
$ ./plunder.js --ships 12 --distance 98.7
Retreat from the xupptumblers!
#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('(%d,%d)', argv.x, argv.y);
$ ./short.js -x 10 -y 21
(10,21)
#!/usr/bin/env node
var util = require('util');
var argv = require('yargs').argv;
if (argv.s) {
util.print(argv.fr ? 'Le perroquet dit: ' : 'The parrot says: ');
}
console.log(
(argv.fr ? 'couac' : 'squawk') + (argv.p ? '!' : '')
);
$ ./bool.js -s
The parrot says: squawk
$ ./bool.js -sp
The parrot says: squawk!
$ ./bool.js -sp --fr
Le perroquet dit: couac!
#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('(%d,%d)', argv.x, argv.y);
console.log(argv._);
$ ./nonopt.js -x 6.82 -y 3.35 rum
(6.82,3.35)
[ 'rum' ]
$ ./nonopt.js "me hearties" -x 0.54 yo -y 1.12 ho
(0.54,1.12)
[ 'me hearties', 'yo', 'ho' ]
#!/usr/bin/env node
var argv = require('yargs')
.count('verbose')
.alias('v', 'verbose')
.argv;
VERBOSE_LEVEL = argv.verbose;
function WARN() { VERBOSE_LEVEL >= 0 && console.log.apply(console, arguments); }
function INFO() { VERBOSE_LEVEL >= 1 && console.log.apply(console, arguments); }
function DEBUG() { VERBOSE_LEVEL >= 2 && console.log.apply(console, arguments); }
WARN("Showing only important stuff");
INFO("Showing semi-mportant stuff too");
DEBUG("Extra chatty mode");
$ node count.js
Showing only important stuff
$ node count.js -v
Showing only important stuff
Showing semi-important stuff too
$ node count.js -vv
Showing only important stuff
Showing semi-important stuff too
Extra chatty mode
$ node count.js -v --verbose
Showing only important stuff
Showing semi-important stuff too
Extra chatty mode
#!/usr/bin/env node
var argv = require('yargs')
.usage('Usage: $0 -w [num] -yh[num]')
.demand(['w','h'])
.argv;
console.log("The area is:", argv.w * argv.h);
#!/usr/bin/env node
var argv = require('yargs')
.demand(2)
.argv;
console.dir(argv)
$ ./demand_count.js a
Not enough arguments, expected 2, but only found 1
$ ./demand_count.js a b
{ _: [ 'a', 'b' ], '$0': 'node ./demand_count.js' }
$ ./demand_count.js a b c
{ _: [ 'a', 'b', 'c' ], '$0': 'node ./demand_count.js' }
$ ./boolean_double.js -x -z one two three
[ true, false, true ]
[ 'one', 'two', 'three' ]
#!/usr/bin/env node
var argv = require('yargs')
.usage('Usage: $0 <command> [options]')
.command('count', 'Count the lines in a file')
.demand(1)
.example('$0 count -f foo.js', 'count the lines in the given file')
.demand('f')
.alias('f', 'file')
.nargs('f', 1)
.describe('f', 'Load a file')
.help('h')
.alias('h', 'help')
.epilog('copyright 2015')
.argv;
var fs = require('fs');
var s = fs.createReadStream(argv.file);
var lines = 0;
s.on('data', function (buf) {
lines += buf.toString().match(/\n/g).length;
});
s.on('end', function () {
console.log(lines);
});
$ node line_count.js count
Usage: node test.js <command> [options]
Commands:
count Count the lines in a file
Options:
-f, --file Load a file [required]
-h, --help Show help
Examples:
node test.js count -f foo.js count the lines in the given file
copyright 2015
Missing required arguments: f
$ node line_count.js count --file line_count.js
20
$ node line_count.js count -f line_count.js
20
require('yargs').argv
`
require('yargs')([ '-x', '1', '-y', '2' ]).argv
require('yargs').parse([ '-x', '1', '-y', '2' ])
var argv = require('yargs')
.default('random', function randomValue() {
return Math.random() * 256;
}).argv;
.default('timeout', 60000, '(one-minute)');
var argv = require('yargs')
.option('f', {
alias : 'file',
demand: true,
default: '/etc/passwd',
describe: 'x marks the spot',
type: 'string'
})
.argv
;
var argv = require('yargs')
.alias('f', 'file')
.default('f', '/etc/passwd')
.argv
;
var argv = require('yargs')
.options({
'f': {
alias: 'file',
demand: true,
default: '/etc/passwd',
describe: 'x marks the spot',
type: 'string'
}
})
.argv
;
var argv = require('yargs')
.usage('npm <command>')
.command('install', 'tis a mighty fine package to install')
.command('publish', 'shiver me timbers, should you be sharing all that', function (yargs) {
argv = yargs.option('f', {
alias: 'force',
description: 'yar, it usually be a bad idea'
})
.help('help')
.argv
})
.help('help')
.argv;
var argv = require('yargs')
.epilogue('for more information, find our manual at http://example.com');
var argv = require('yargs')
.nargs('token', 1)
.parse(['--token', '-my-token']);
var yargs = require("yargs")
.usage("$0 -operand1 number -operand2 number -operation [add|subtract]");
console.log(yargs.help());
var argv = require('yargs')
.version(function() {
return require('../package').version;
})
.argv;
#!/usr/bin/env node
var argv = require('yargs')
.usage('Count the lines in a file.\nUsage: $0')
.demand('f')
.alias('f', 'file')
.describe('f', 'Load a file')
.showHelpOnFail(false, "Specify --help for available options")
.argv;
// etc.
$ node line_count.js --file
Missing argument value: f
Specify --help for available options
var yargs = require("yargs")
.usage("$0 -operand1 number -operand2 number -operation [add|subtract]");
yargs.showHelp();
yargs.showHelp("log");
var argv = require('yargs')
.completion('completion', function(current, argv) {
// 'current' is the current command being completed.
// 'argv' is the parsed arguments so far.
// simply return an array of completions.
return [
'foo',
'bar'
];
})
.argv;
var rightAlign = require('right-align');
rightAlign(string);
Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor incididunt
ut labore et dolore
magna aliqua. Ut enim ad minim
veniam, quis
Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor incididunt
ut labore et dolore
magna aliqua. Ut enim ad minim
veniam, quis
var align = require('align-text');
align(text, callback_function_or_integer);
align(text, 4);
abc
abc
abc
abc
abc
abc
// calculate half the difference between the length
// of the current line and the longest line
function centerAlign(len, longest, line, lines) {
return Math.floor((longest - len) / 2);
}
Lorem ipsum dolor sit amet
consectetur adipiscin
elit, sed do eiusmod tempor incididun
ut labore et dolor
magna aliqua. Ut enim ad mini
veniam, quis
Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor incididunt
ut labore et dolore
magna aliqua. Ut enim ad minim
veniam, quis
Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor incididunt
ut labore et dolore
magna aliqua. Ut enim ad minim
veniam, quis
- Lorem ipsum dolor sit amet,
- consectetur adipiscing
- elit, sed do eiusmod tempor incididunt
- ut labore et dolore
- magna aliqua. Ut enim ad minim
- veniam, quis
~~~~~Lorem ipsum dolor sit amet,
~~~~~~~~consectetur adipiscing
elit, sed do eiusmod tempor incididunt
~~~~~~~~~ut labore et dolore
~~~~magna aliqua. Ut enim ad minim
~~~~~~~~~~~~~veniam, quis
8d089d2 bool example is more consistent and also shows off short option grouping (@substack)
448d747 start of the readme and examples (@substack)
da74dea more tests for long and short captures (@substack)
ab6387e silly bug in the tests with s/not/no/, all tests pass now (@substack)
102496a hack an instance for process.argv onto Argv so the export can be called to create an instance or used for argv, which is the most common case (@substack)
Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
Contributors
Commits
Contributor
51
2
2
1
1
Building docs
(This document was generated by verb-generate-readme (a verb generator), please don't edit the readme directly. Any changes to the readme must be made in .verb.md.)
To generate the readme and API documentation with verb:
Those wishing to minify ES2015+ (ES6+) should use the npm package uglify-es.
Install
First make sure you have installed the latest version of node.js (You may need to restart your computer after this step).
From NPM for use as a command line app:
From NPM for programmatic use:
Usage
UglifyJS2 can take multiple input files. It's recommended that you pass the input files first, then pass the options. UglifyJS will parse input files in sequence and apply any compression options. The files are parsed in the same global scope, that is, a reference from a file to some variable/function declared in another file will be matched properly.
If you want to read from STDIN instead, pass a single dash instead of input files.
If you wish to pass your options before the input files, separate the two with a double dash to prevent input files being used as option arguments:
The available options are:
Specify --output (-o) to declare the output file. Otherwise the output goes to STDOUT.
Source map options
UglifyJS2 can generate a source map file, which is highly useful for debugging your compressed JavaScript. To get a source map, pass --source-map output.js.map (full path to the file where you want the source map dumped).
Additionally you might need --source-map-root to pass the URL where the original files can be found. In case you are passing full paths to input files to UglifyJS, you can use --prefix (-p) to specify the number of directories to drop from the path prefix when declaring files in the source map.
For example:
The above will compress and mangle file1.js and file2.js, will drop the output in foo.min.js and the source map in foo.min.js.map. The source mapping will refer to http://foo.com/src/js/file1.js and http://foo.com/src/js/file2.js (in fact it will list http://foo.com/src as the source map root, and the original files as js/file1.js and js/file2.js).
Composed source map
When you're compressing JS code that was output by a compiler such as CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd like to map back to the original code (i.e. CoffeeScript). UglifyJS has an option to take an input source map. Assuming you have a mapping from CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → compressed JS by mapping every token in the compiled JS to its original location.
To use this feature you need to pass --in-source-map /path/to/input/source.map or --in-source-map inline if the source map is included inline with the sources. Normally the input source map should also point to the file containing the generated JS, so if that's correct you can omit input files from the command line.
Mangler options
To enable the mangler you need to pass --mangle (-m). The following (comma-separated) options are supported:
toplevel — mangle names declared in the toplevel scope (disabled by default).
eval — mangle names visible in scopes where eval or with are used (disabled by default).
When mangling is enabled but you want to prevent certain names from being mangled, you can declare those names with --reserved (-r) — pass a comma-separated list of names. For example:
to prevent the require, exports and $ names from being changed.
Mangling property names (--mangle-props)
Note: this will probably break your code. Mangling property names is a separate step, different from variable name mangling. Pass --mangle-props. It will mangle all properties that are seen in some object literal, or that are assigned to. For example:
In the above code, foo, bar, baz, moo and boo will be replaced with single characters, while something() will be left as is.
In order for this to be of any use, we should avoid mangling standard JS names. For instance, if your code would contain x.length = 10, then length becomes a candidate for mangling and it will be mangled throughout the code, regardless if it's being used as part of your own objects or accessing an array's length. To avoid that, you can use --reserved-file to pass a filename that should contain the names to be excluded from mangling. This file can be used both for excluding variable names and property names. It could look like this, for example:
--reserved-file can be an array of file names (either a single comma-separated argument, or you can pass multiple --reserved-file arguments) — in this case it will exclude names from all those files.
A default exclusion file is provided in tools/domprops.json which should cover most standard JS and DOM properties defined in various browsers. Pass --reserve-domprops to read that in.
You can also use a regular expression to define which property names should be mangled. For example, --mangle-regex="/^_/" will only mangle property names that start with an underscore.
When you compress multiple files using this option, in order for them to work together in the end we need to ensure somehow that one property gets mangled to the same name in all of them. For this, pass --name-cache filename.json and UglifyJS will maintain these mappings in a file which can then be reused. It should be initially empty. Example:
Now, part1.js and part2.js will be consistent with each other in terms of mangled property names.
Using the name cache is not necessary if you compress all your files in a single call to UglifyJS.
Mangling unquoted names (--mangle-props=unquoted or --mangle-props=2)
Using quoted property name (o["foo"]) reserves the property name (foo) so that it is not mangled throughout the entire script even when used in an unquoted style (o.foo). Example:
Debugging property name mangling
You can also pass --mangle-props-debug in order to mangle property names without completely obscuring them. For example the property o.foo would mangle to o._$foo$_ with this option. This allows property mangling of a large codebase while still being able to debug the code and identify where mangling is breaking things.
You can also pass a custom suffix using --mangle-props-debug=XYZ. This would then mangle o.foo to o._$foo$XYZ_. You can change this each time you compile a script to identify how a property got mangled. One technique is to pass a random number on every compile to simulate mangling changing with different inputs (e.g. as you update the input script with new properties), and to help identify mistakes like writing mangled keys to storage.
Compressor options
You need to pass --compress (-c) to enable the compressor. Optionally you can pass a comma-separated list of options. Options are in the form foo=bar, or just foo (the latter implies a boolean option that you want to set true; it's effectively a shortcut for foo=true).
sequences (default: true) -- join consecutive simple statements using the comma operator. May be set to a positive integer to specify the maximum number of consecutive comma sequences that will be generated. If this option is set to true then the default sequences limit is 200. Set option to false or 0 to disable. The smallest sequences length is 2. A sequences value of 1 is grandfathered to be equivalent to true and as such means 200. On rare occasions the default sequences limit leads to very slow compress times in which case a value of 20 or less is recommended.
properties -- rewrite property access using the dot notation, for example foo["bar"] → foo.bar
unsafe_comps (default: false) -- Reverse < and <= to > and >= to allow improved compression. This might be unsafe when an at least one of two operands is an object with computed values due the use of methods like get, or valueOf. This could cause change in execution order after operands in the comparison are switching. Compression only works if both comparisons and unsafe_comps are both set to true.
unsafe_math (default: false) -- optimize numerical expressions like 2 * x * 3 into 6 * x, which may give imprecise floating point results.
unsafe_proto (default: false) -- optimize expressions like Array.prototype.slice.call(a) into [].slice.call(a)
unsafe_regexp (default: false) -- enable substitutions of variables with RegExp values the same way as if they are constants.
conditionals -- apply optimizations for if-s and conditional expressions
comparisons -- apply certain optimizations to binary nodes, for example: !(a <= b) → a > b (only when unsafe_comps), attempts to negate binary nodes, e.g. a = !b && !c && !d && !e → a=!(b||c||d||e) etc.
evaluate -- attempt to evaluate constant expressions
booleans -- various optimizations for boolean context, for example !!a ? b : c → a ? b : c
loops -- optimizations for do, while and for loops when we can statically determine the condition
unused -- drop unreferenced functions and variables (simple direct variable assignments do not count as references unless set to "keep_assign")
toplevel -- drop unreferenced functions ("funcs") and/or variables ("vars") in the toplevel scope (false by default, true to drop both unreferenced functions and variables)
top_retain -- prevent specific toplevel functions and variables from unused removal (can be array, comma-separated, RegExp or function. Implies toplevel)
hoist_funs -- hoist function declarations
hoist_vars (default: false) -- hoist var declarations (this is false by default because it seems to increase the size of the output in general)
if_return -- optimizations for if/return and if/continue
join_vars -- join consecutive var statements
cascade -- small optimization for sequences, transform x, x into x and x = something(), x into x = something()
collapse_vars -- Collapse single-use var and const definitions when possible.
reduce_vars -- Improve optimization on variables assigned with and used as constant values.
warnings -- display warnings when dropping unreachable code or unused declarations etc.
negate_iife -- negate "Immediately-Called Function Expressions" where the return value is discarded, to avoid the parens that the code generator would insert.
pure_getters -- the default is false. If you pass true for this, UglifyJS will assume that object property access (e.g. foo.bar or foo["bar"]) doesn't have any side effects. Specify "strict" to treat foo.bar as side-effect-free only when foo is certain to not throw, i.e. not null or undefined.
pure_funcs -- default null. You can pass an array of names and UglifyJS will assume that those functions do not produce side effects. DANGER: will not check if the name is redefined in scope. An example case here, for instance var q = Math.floor(a/b). If variable q is not used elsewhere, UglifyJS will drop it, but will still keep the Math.floor(a/b), not knowing what it does. You can pass pure_funcs: [ 'Math.floor' ] to let it know that this function won't produce any side effect, in which case the whole statement would get discarded. The current implementation adds some overhead (compression will be slower).
drop_console -- default false. Pass true to discard calls to console.* functions. If you wish to drop a specific function call such as console.info and/or retain side effects from function arguments after dropping the function call then use pure_funcs instead.
expression -- default false. Pass true to preserve completion values from terminal statements without return, e.g. in bookmarklets.
keep_fargs -- default true. Prevents the compressor from discarding unused function arguments. You need this for code which relies on Function.length.
keep_fnames -- default false. Pass true to prevent the compressor from discarding function names. Useful for code relying on Function.prototype.name. See also: the keep_fnames .
passes -- default 1. Number of times to run compress with a maximum of 3. In some cases more than one pass leads to further compressed code. Keep in mind more passes will take more time.
keep_infinity -- default false. Pass true to prevent Infinity from being compressed into 1/0, which may cause performance issues on Chrome.
side_effects -- default true. Pass false to disable potentially dropping functions marked as "pure". A function call is marked as "pure" if a comment annotation /*@__PURE__*/ or /*#__PURE__*/ immediately precedes the call. For example: /*@__PURE__*/foo();
The unsafe option
It enables some transformations that might break code logic in certain contrived cases, but should be fine for most code. You might want to try it on your own code, it should reduce the minified size. Here's what happens when this flag is on:
new Array(1, 2, 3) or Array(1, 2, 3) → [ 1, 2, 3 ]
new Object() → {}
String(exp) or exp.toString() → "" + exp
new Object/RegExp/Function/Error/Array (...) → we discard the new
typeof foo == "undefined" → foo === void 0
void 0 → undefined (if there is a variable named "undefined" in
scope; we do it because the variable name will be mangled, typically
reduced to a single character)
Conditional compilation
You can use the --define (-d) switch in order to declare global variables that UglifyJS will assume to be constants (unless defined in scope). For example if you pass --define DEBUG=false then, coupled with dead code removal UglifyJS will discard the following from the output:
You can specify nested constants in the form of --define env.DEBUG=false.
UglifyJS will warn about the condition being always false and about dropping unreachable code; for now there is no option to turn off only this specific warning, you can pass warnings=false to turn off all warnings.
Another way of doing that is to declare your globals as constants in a separate file and include it into the build. For example you can have a build/defines.js file with the following:
and build your code like this:
UglifyJS will notice the constants and, since they cannot be altered, it will evaluate references to them to the value itself and drop unreachable code as usual. The build will contain the const declarations if you use them. If you are targeting < ES6 environments which does not support const, using var with reduce_vars (enabled by default) should suffice.
Conditional compilation, API
You can also use conditional compilation via the programmatic API. With the difference that the property name is global_defs and is a compressor property:
Beautifier options
The code generator tries to output shortest code possible by default. In case you want beautified output, pass --beautify (-b). Optionally you can pass additional arguments that control the code output:
beautify (default true) -- whether to actually beautify the output.
Passing -b will set this to true, but you might need to pass -b even
when you want to generate minified code, in order to specify additional
arguments, so you can use -b beautify=false to override it.
indent-level (default 4)
indent-start (default 0) -- prefix all lines by that many spaces
quote-keys (default false) -- pass true to quote all keys in literal
objects
space-colon (default true) -- insert a space after the colon signs
ascii-only (default false) -- escape Unicode characters in strings and
regexps (affects directives with non-ascii characters becoming invalid)
inline-script (default false) -- escape the slash in occurrences of
</script in strings
width (default 80) -- only takes effect when beautification is on, this
specifies an (orientative) line width that the beautifier will try to
obey. It refers to the width of the line text (excluding indentation).
It doesn't work very well currently, but it does make the code generated
by UglifyJS more readable.
max-line-len (default 32000) -- maximum line length (for uglified code)
bracketize (default false) -- always insert brackets in if, for,
do, while or with statements, even if their body is a single
statement.
semicolons (default true) -- separate statements with semicolons. If
you pass false then whenever possible we will use a newline instead of a
semicolon, leading to more readable output of uglified code (size before
gzip could be smaller; size after gzip insignificantly larger).
preamble (default null) -- when passed it must be a string and
it will be prepended to the output literally. The source map will
adjust for this text. Can be used to insert a comment containing
licensing information, for example.
quote_style (default 0) -- preferred quote style for strings (affects
quoted property names and directives as well):
0 -- prefers double quotes, switches to single quotes when there are
keep_quoted_props (default false) -- when turned on, prevents stripping
quotes from property names in object literals.
Keeping copyright notices or other comments
You can pass --comments to retain certain comments in the output. By default it will keep JSDoc-style comments that contain "@preserve", "@license" or "@cc_on" (conditional compilation for IE). You can pass --comments all to keep all the comments, or a valid JavaScript regexp to keep only comments that match this regexp. For example --comments '/foo|bar/' will keep only comments that contain "foo" or "bar".
Note, however, that there might be situations where comments are lost. For example:
Even though it has "@preserve", the comment will be lost because the inner function g (which is the AST node to which the comment is attached to) is discarded by the compressor as not referenced.
The safest comments where to place copyright information (or other info that needs to be kept in the output) are comments attached to toplevel nodes.
Support for the SpiderMonkey AST
UglifyJS2 has its own abstract syntax tree format; for practical reasons we can't easily change to using the SpiderMonkey AST internally. However, UglifyJS now has a converter which can import a SpiderMonkey AST.
For example Acorn is a super-fast parser that produces a SpiderMonkey AST. It has a small CLI utility that parses one file and dumps the AST in JSON on the standard output. To use UglifyJS to mangle and compress that:
The --spidermonkey option tells UglifyJS that all input files are not JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we don't use our own parser in this case, but just transform that AST into our internal AST.
Use Acorn for parsing
More for fun, I added the --acorn option which will use Acorn to do all the parsing. If you pass this option, UglifyJS will require("acorn").
Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but converting the SpiderMonkey tree that Acorn produces takes another 150ms so in total it's a bit more than just using UglifyJS's own parser.
Using UglifyJS to transform SpiderMonkey AST
Now you can use UglifyJS as any other intermediate tool for transforming JavaScript ASTs in SpiderMonkey format.
Assuming installation via NPM, you can load UglifyJS in your application like this:
It exports a lot of names, but I'll discuss here the basics that are needed for parsing, mangling and compressing a piece of code. The sequence is (1) parse, (2) compress, (3) mangle, (4) generate output code.
The simple way
There's a single toplevel function which combines all the steps. If you don't need additional customization, you might want to go with minify. Example:
You can also compress multiple files:
To generate a source map:
To generate a source map with the fromString option, you can also use an object:
Note that the source map is not saved in a file, it's just returned in result.map. The value passed for outSourceMap is only used to set //# sourceMappingURL=out.js.map in result.code. The value of outFileName is only used to set file attribute in source map file.
The file attribute in the source map (see the spec) will use outFileName firstly, if it's falsy, then will be deduced from outSourceMap (by removing '.map').
You can set option sourceMapInline to be true and source map will be appended to code.
You can also specify sourceRoot property to be included in source map:
If you're compressing compiled JavaScript and have a source map for it, you can use the inSourceMap argument:
If your input source map is not in a file, you can pass it in as an object using the inSourceMap argument:
The inSourceMap is only used if you also request outSourceMap (it makes no sense otherwise).
To set the source map url, use the sourceMapUrl option. If you're using the X-SourceMap header instead, you can just set the sourceMapUrl option to false. Defaults to outSourceMap:
Other options:
warnings (default false) — pass true to display compressor warnings.
fromString (default false) — if you pass true then you can pass JavaScript source code, rather than file names.
mangle (default true) — pass false to skip mangling names, or pass an object to specify mangling options (see below).
mangleProperties (default false) — pass an object to specify custom mangle property options.
output (default null) — pass an object if you wish to specify additional . The defaults are optimized for best compression.
compress (default {}) — pass false to skip compressing entirely. Pass an object to specify custom .
parse (default {}) — pass an object if you wish to specify some additional . (not all options available... see below)
mangle
except - pass an array of identifiers that should be excluded from mangling
toplevel — mangle names declared in the toplevel scope (disabled by default).
eval — mangle names visible in scopes where eval or with are used (disabled by default).
keep_fnames -- default false. Pass true to not mangle function names. Useful for code relying on Function.prototype.name. See also: the keep_fnames .
Examples:
mangleProperties options
regex — Pass a RegExp to only mangle certain names (maps to the --mangle-regex CLI arguments option)
ignore_quoted – Only mangle unquoted property names (maps to the --mangle-props 2 CLI arguments option)
debug – Mangle names with the original name still present (maps to the --mangle-props-debug CLI arguments option). Defaults to false. Pass an empty string to enable, or a non-empty string to set the suffix.
We could add more options to UglifyJS.minify — if you need additional functionality please suggest!
The hard way
Following there's more detailed API info, in case the minify function is too simple for your needs.
The parser
options is optional and if present it must be an object. The following properties are available:
strict — disable automatic semicolon insertion and support for trailing
comma in arrays and objects
bare_returns — Allow return outside of functions. (maps to the
--bare-returns CLI arguments option and available to minifyparse
other options object)
filename — the name of the file where this code is coming from
toplevel — a toplevel node (as returned by a previous invocation of
parse)
The last two options are useful when you'd like to minify multiple files and get a single file as the output and a proper source map. Our CLI tool does something like this:
After this, we have in toplevel a big AST containing all our files, with each token having proper information about where it came from.
Scope information
UglifyJS contains a scope analyzer that you need to call manually before compressing or mangling. Basically it augments various nodes in the AST with information about where is a name defined, how many times is a name referenced, if it is a global or not, if a function is using eval or the with statement etc. I will discuss this some place else, for now what's important to know is that you need to call the following before doing anything with the tree:
Compression
Like this:
The options can be missing. Available options are discussed above in “Compressor options”. Defaults should lead to best compression in most scripts.
The compressor is destructive, so don't rely that toplevel remains the original tree.
Mangling
After compression it is a good idea to call again figure_out_scope (since the compressor might drop unused variables / unreachable code and this might change the number of identifiers or their position). Optionally, you can call a trick that helps after Gzip (counting character frequency in non-mangleable words). Example:
Generating output
AST nodes have a print method that takes an output stream. Essentially, to generate code you do this:
or, for a shortcut you can do:
As usual, options is optional. The output stream accepts a lot of options, most of them documented above in section “Beautifier options”. The two which we care about here are source_map and comments.
Keeping comments in the output
In order to keep certain comments in the output you need to pass the comments option. Pass a RegExp (as string starting and closing with / or pass a RegExp object), a boolean or a function. Stringified options all and some can be passed too, where some behaves like it's cli equivalent --comments without passing a value. If you pass a RegExp, only those comments whose body matches the RegExp will be kept. Note that body means without the initial // or /*. If you pass a function, it will be called for every comment in the tree and will receive two arguments: the node that the comment is attached to, and the comment token itself.
The comment token has these properties:
type: "comment1" for single-line comments or "comment2" for multi-line
comments
value: the comment body
pos and endpos: the start/end positions (zero-based indexes) in the
original code where this comment appears
line and col: the line and column where this comment appears in the
original code
file — the file name of the original file
nlb — true if there was a newline before this comment in the original
code, or if this comment contains a newline.
Your function should return true to keep the comment, or a falsy value otherwise.
Generating a source mapping
You need to pass the source_map argument when calling print. It needs to be a SourceMap object (which is a thin wrapper on top of the source-map library).
Example:
The source_map_options (optional) can contain the following properties:
file: the name of the JavaScript output file that this mapping refers to
orig: the "original source map", handy when you compress generated JS
and want to map the minified output back to the original code where it
came from. It can be simply a string in JSON, or a JSON object containing
the original source map.
Support for const
const in uglify-js@2.x has function scope and as such behaves much like var - unlike const in ES2015 (ES6) which has block scope. It is recommended to avoid using const for this reason as it will have undefined behavior when run on an ES2015 compatible browser.
--source-map Specify an output file where to generate source
map.
--source-map-root The path to the original source to be included
in the source map.
--source-map-url The path to the source map to be added in //#
sourceMappingURL. Defaults to the value passed
with --source-map.
--source-map-include-sources Pass this flag if you want to include the
content of source files in the source map as
sourcesContent property.
--source-map-inline Write base64-encoded source map to the end of js output.
--in-source-map Input source map, useful if you're compressing
JS that was generated from some other original
code. Specify "inline" if the source map is included
inline with the sources.
--screw-ie8 Use this flag if you don't wish to support
Internet Explorer 6/7/8.
By default UglifyJS will not try to be IE-proof.
--support-ie8 Use this flag to support Internet Explorer 6/7/8.
Equivalent to setting `screw_ie8: false` in `minify()`
for `compress`, `mangle` and `output` options.
--expr Parse a single expression, rather than a
program (for parsing JSON)
-p, --prefix Skip prefix for original filenames that appear
in source maps. For example -p 3 will drop 3
directories from file names and ensure they are
relative paths. You can also specify -p
relative, which will make UglifyJS figure out
itself the relative paths between original
sources, the source map and the output file.
-o, --output Output file (default STDOUT).
-b, --beautify Beautify output/specify output options.
-m, --mangle Mangle names/pass mangler options.
-r, --reserved Reserved names to exclude from mangling.
-c, --compress Enable compressor/pass compressor options, e.g.
`-c 'if_return=false,pure_funcs=["Math.pow","console.log"]'`
Use `-c` with no argument to enable default compression
options.
-d, --define Global definitions
-e, --enclose Embed everything in a big function, with a
configurable parameter/argument list.
--comments Preserve copyright comments in the output. By
default this works like Google Closure, keeping
JSDoc-style comments that contain "@license" or
"@preserve". You can optionally pass one of the
following arguments to this flag:
- "all" to keep all comments
- a valid JS RegExp like `/foo/` or `/^!/` to
keep only matching comments.
Note that currently not *all* comments can be
kept when compression is on, because of dead
code removal or cascading statements into
sequences.
--preamble Preamble to prepend to the output. You can use
this to insert a comment, for example for
licensing information. This will not be
parsed, but the source map will adjust for its
presence.
--stats Display operations run time on STDERR.
--acorn Use Acorn for parsing.
--spidermonkey Assume input files are SpiderMonkey AST format
(as JSON).
--self Build itself (UglifyJS2) as a library (implies
--wrap=UglifyJS --export-all)
--wrap Embed everything in a big function, making the
“exports” and “global” variables available. You
need to pass an argument to this option to
specify the name that your module will take
when included in, say, a browser.
--export-all Only used when --wrap, this tells UglifyJS to
add code to automatically export all globals.
--lint Display some scope warnings
-v, --verbose Verbose
-V, --version Print version number and exit.
--noerr Don't throw an error for unknown options in -c,
-b or -m.
--bare-returns Allow return outside of functions. Useful when
minifying CommonJS modules and Userscripts that
may be anonymous function wrapped (IIFE) by the
.user.js engine `caller`.
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
--reserved-file File containing reserved names
--reserve-domprops Make (most?) DOM properties reserved for
--mangle-props
--mangle-props Mangle property names (default `0`). Set to
`true` or `1` to mangle all property names. Set
to `unquoted` or `2` to only mangle unquoted
property names. Mode `2` also enables the
`keep_quoted_props` beautifier option to
preserve the quotes around property names and
disables the `properties` compressor option to
prevent rewriting quoted properties with dot
notation. You can override these by setting
them explicitly on the command line.
--mangle-regex Only mangle property names matching the regex
--name-cache File to hold mangled names mappings
--pure-funcs Functions that can be safely removed if their
return value is not used, e.g.
`--pure-funcs Math.floor console.info`
(requires `--compress`)
function f() {
/** @preserve Foo Bar */
function g() {
// this function is never called
}
return something();
}
acorn file.js | uglifyjs --spidermonkey -m -c
function uglify(ast, options, mangle) {
// Conversion from SpiderMonkey AST to internal format
var uAST = UglifyJS.AST_Node.from_mozilla_ast(ast);
// Compression
uAST.figure_out_scope();
uAST = UglifyJS.Compressor(options).compress(uAST);
// Mangling (optional)
if (mangle) {
uAST.figure_out_scope();
uAST.compute_char_frequency();
uAST.mangle_names();
}
// Back-conversion to SpiderMonkey AST
return uAST.to_mozilla_ast();
}
var UglifyJS = require("uglify-js");
var result = UglifyJS.minify("/path/to/file.js");
console.log(result.code); // minified output
// if you need to pass code instead of file name
var result = UglifyJS.minify("var b = function () {};", {fromString: true});
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ]);
console.log(result.code);
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
outSourceMap: "out.js.map"
});
console.log(result.code); // minified output
console.log(result.map);
var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {
outSourceMap: "out.js.map",
outFileName: "out.js",
fromString: true
});
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
outSourceMap: "out.js.map",
sourceRoot: "http://example.com/src"
});
var result = UglifyJS.minify("compiled.js", {
inSourceMap: "compiled.js.map",
outSourceMap: "minified.js.map"
});
// same as before, it returns `code` and `map`
var result = UglifyJS.minify("compiled.js", {
inSourceMap: JSON.parse(my_source_map_string),
outSourceMap: "minified.js.map"
});
var result = UglifyJS.minify([ "file1.js" ], {
outSourceMap: "out.js.map",
sourceMapUrl: "localhost/out.js.map"
});
var toplevel_ast = UglifyJS.parse(code, options);
var toplevel = null;
files.forEach(function(file){
var code = fs.readFileSync(file, "utf8");
toplevel = UglifyJS.parse(code, {
filename: file,
toplevel: toplevel
});
});
toplevel.figure_out_scope()
var compressor = UglifyJS.Compressor(options);
var compressed_ast = compressor.compress(toplevel);
var stream = UglifyJS.OutputStream(options);
compressed_ast.print(stream);
var code = stream.toString(); // this is your minified code
var code = compressed_ast.print_to_string(options);
var source_map = UglifyJS.SourceMap(source_map_options);
var stream = UglifyJS.OutputStream({
...
source_map: source_map
});
compressed_ast.print(stream);
var code = stream.toString();
var map = source_map.toString(); // json output for your source map