新增调试信息

This commit is contained in:
2025-10-27 22:15:25 +08:00
parent ae62457d8c
commit 04642cb2f0
5479 changed files with 683397 additions and 3450 deletions
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/browserify
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+23
View File
@@ -0,0 +1,23 @@
language: node_js
node_js:
- "10"
- "9"
- "8"
- "6"
- "4"
- "iojs"
- "0.12"
- "0.10"
- "0.8"
- "0.6"
before_install:
# Old npm certs are untrusted https://github.com/npm/npm/issues/20191
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.8" ]; then export NPM_CONFIG_STRICT_SSL=false; fi'
- 'nvm install-latest-npm'
install:
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
sudo: false
matrix:
fast_finish: true
allow_failures:
- node_js: "0.6"
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2010 James Halliday
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+27
View File
@@ -0,0 +1,27 @@
environment:
matrix:
- nodejs_version: "10"
- nodejs_version: "9"
- nodejs_version: "8"
- nodejs_version: "6"
- nodejs_version: "4"
- nodejs_version: "0.12"
- nodejs_version: "0.10"
# Install scripts. (runs after repo cloning)
install:
# Get the latest stable version of Node.js or io.js
- ps: Install-Product node $env:nodejs_version
# install modules
- npm install
# Post-install test scripts.
test_script:
# Output useful info for debugging.
- node --version
- npm --version
# run tests
- npm test
# Don't actually build.
build: off
Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+117
View File
@@ -0,0 +1,117 @@
Advanced Options:
--insert-globals, --ig, --fast [default: false]
Skip detection and always insert definitions for process, global,
__filename, and __dirname.
benefit: faster builds
cost: extra bytes
--insert-global-vars, --igv
Comma-separated list of global variables to detect and define.
Default: __filename,__dirname,process,Buffer,global
--detect-globals, --dg [default: true]
Detect the presence of process, global, __filename, and __dirname and define
these values when present.
benefit: npm modules more likely to work
cost: slower builds
--ignore-missing, --im [default: false]
Ignore `require()` statements that don't resolve to anything.
--noparse=FILE
Don't parse FILE at all. This will make bundling much, much faster for giant
libs like jquery or threejs.
--no-builtins
Turn off builtins. This is handy when you want to run a bundle in node which
provides the core builtins.
--no-commondir
Turn off setting a commondir. This is useful if you want to preserve the
original paths that a bundle was generated with.
--no-bundle-external
Turn off bundling of all external modules. This is useful if you only want
to bundle your local files.
--bare
Alias for both --no-builtins, --no-commondir, and sets --insert-global-vars
to just "__filename,__dirname". This is handy if you want to run bundles in
node.
--no-browser-field, --no-bf
Turn off package.json browser field resolution. This is also handy if you
need to run a bundle in node.
--transform-key
Instead of the default package.json#browserify#transform field to list
all transforms to apply when running browserify, a custom field, like, e.g.
package.json#browserify#production or package.json#browserify#staging
can be used, by for example running:
* `browserify index.js --transform-key=production > bundle.js`
* `browserify index.js --transform-key=staging > bundle.js`
--node
Alias for --bare and --no-browser-field.
--full-paths
Turn off converting module ids into numerical indexes. This is useful for
preserving the original paths that a bundle was generated with.
--deps
Instead of standard bundle output, print the dependency array generated by
module-deps.
--no-dedupe
Turn off deduping.
--list
Print each file in the dependency graph. Useful for makefiles.
--extension=EXTENSION
Consider files with specified EXTENSION as modules, this option can used
multiple times.
--global-transform=MODULE, -g MODULE
Use a transform module on all files after any ordinary transforms have run.
--plugin=MODULE, -p MODULE
Register MODULE as a plugin.
--preserve-symlinks
Preserves symlinks when resolving modules.
Passing arguments to transforms and plugins:
For -t, -g, and -p, you may use subarg syntax to pass options to the
transforms or plugin function as the second parameter. For example:
-t [ foo -x 3 --beep ]
will call the `foo` transform for each applicable file by calling:
foo(file, { x: 3, beep: true })
+260
View File
@@ -0,0 +1,260 @@
var browserify = require('../');
var path = require('path');
var spawn = require('child_process').spawn;
var parseShell = require('shell-quote').parse;
var insertGlobals = require('insert-module-globals');
var duplexer = require('duplexer2');
var subarg = require('subarg');
var glob = require('glob');
var Readable = require('readable-stream').Readable;
var xtend = require('xtend');
module.exports = function (args, opts) {
var argv = subarg(args, {
'boolean': [
'deps', 'pack', 'ig', 'dg', 'im', 'd', 'list', 'builtins',
'commondir', 'bare', 'full-paths', 'bundle-external', 'bf',
'node', 'preserve-symlinks'
],
string: [ 's', 'r', 'u', 'x', 't', 'i', 'o', 'e', 'c', 'it' ],
alias: {
ig: [ 'insert-globals', 'fast' ],
dg: [ 'detect-globals', 'detectGlobals', 'dg' ],
bf: [ 'browser-field', 'browserField' ],
im: 'ignore-missing',
it: 'ignore-transform',
igv: 'insert-global-vars',
d: 'debug',
s: 'standalone',
noParse: [ 'noparse' ],
'full-paths': [ 'fullpaths', 'fullPaths' ],
r: 'require',
u: 'exclude',
x: 'external',
t: 'transform',
i: 'ignore',
o: 'outfile',
e: 'entry',
c: 'command',
bare: 'bear'
},
'default': {
ig: false,
im: false,
dg: true,
d: false,
builtins: true,
commondir: true,
'bundle-external': true,
bf: true,
dedupe: true,
node: false
}
});
var entries = argv._.concat(argv.entry)
.filter(Boolean).map(function (entry) {
if (entry === '-') {
var s = process.stdin;
if (typeof s.read === 'function') return s;
// only needed for 0.8, remove at some point later:
var rs = Readable().wrap(s);
s.resume();
return rs;
}
return entry;
});
if (argv.igv) {
var insertGlobalVars = {};
var wantedGlobalVars = argv.igv.split(',');
Object.keys(insertGlobals.vars).forEach(function (x) {
if (wantedGlobalVars.indexOf(x) === -1) {
insertGlobalVars[x] = undefined;
}
});
}
var ignoreTransform = argv['ignore-transform'] || argv.it;
var b = browserify(xtend({
node: argv.node,
bare: argv.bare,
noParse: Array.isArray(argv.noParse) ? argv.noParse : [argv.noParse],
extensions: [].concat(argv.extension).filter(Boolean).map(function (extension) {
if (extension.charAt(0) != '.') {
return '.' + extension;
} else {
return extension
}
}),
ignoreTransform: [].concat(ignoreTransform).filter(Boolean),
entries: entries,
fullPaths: argv['full-paths'],
builtins: argv.builtins === false ? false : undefined,
commondir: argv.commondir === false ? false : undefined,
bundleExternal: argv['bundle-external'],
basedir: argv.basedir,
browserField: argv.browserField,
transformKey: argv['transform-key'] ? ['browserify', argv['transform-key']] : undefined,
dedupe: argv['dedupe'],
preserveSymlinks: argv['preserve-symlinks'],
detectGlobals: argv.detectGlobals,
insertGlobals: argv['insert-globals'] || argv.ig,
insertGlobalVars: insertGlobalVars,
ignoreMissing: argv['ignore-missing'] || argv.im,
debug: argv['debug'] || argv.d,
standalone: argv['standalone'] || argv.s
}, opts));
function error (msg) {
var e = new Error(msg);
process.nextTick(function () { b.emit('error', e) });
}
b.argv = argv;
[].concat(argv.p).concat(argv.plugin).filter(Boolean)
.forEach(function (p) {
var pf = p, pOpts = {};
if (typeof p === 'object') {
pf = p._.shift(), pOpts = p;
}
b.plugin(pf, pOpts);
})
;
[].concat(argv.ignore).filter(Boolean)
.forEach(function (i) {
b._pending ++;
glob(i, function (err, files) {
if (err) return b.emit('error', err);
if (files.length === 0) {
b.ignore(i);
}
else {
files.forEach(function (file) { b.ignore(file) });
}
if (--b._pending === 0) b.emit('_ready');
});
})
;
[].concat(argv.exclude).filter(Boolean)
.forEach(function (u) {
b.exclude(u);
b._pending ++;
glob(u, function (err, files) {
if (err) return b.emit('error', err);
files.forEach(function (file) { b.exclude(file) });
if (--b._pending === 0) b.emit('_ready');
});
})
;
[].concat(argv.require).filter(Boolean)
.forEach(function (r) {
var xs = splitOnColon(r);
b.require(xs[0], { expose: xs.length === 1 ? xs[0] : xs[1] })
})
;
// resolve any external files and add them to the bundle as externals
[].concat(argv.external).filter(Boolean)
.forEach(function (x) {
var xs = splitOnColon(x);
if (xs.length === 2) {
add(xs[0], { expose: xs[1] });
}
else if (/\*/.test(x)) {
b.external(x);
glob(x, function (err, files) {
files.forEach(function (file) {
add(file, {});
});
});
}
else add(x, {});
function add (x, opts) {
if (/^[\/.]/.test(x)) b.external(path.resolve(x), opts)
else b.external(x, opts)
}
})
;
[].concat(argv.transform)
.filter(Boolean)
.forEach(function (t) { addTransform(t) })
;
[].concat(argv.g).concat(argv['global-transform'])
.filter(Boolean)
.forEach(function (t) {
addTransform(t, { global: true });
})
;
function addTransform (t, opts) {
if (typeof t === 'string' || typeof t === 'function') {
b.transform(opts, t);
}
else if (t && typeof t === 'object') {
if (!t._[0] || typeof t._[0] !== 'string') {
return error(
'expected first parameter to be a transform string'
);
}
if (opts) Object.keys(opts).forEach(function (key) {
t[key] = opts[key];
});
b.transform(t, t._.shift());
}
else error('unexpected transform of type ' + typeof t);
}
[].concat(argv.command).filter(Boolean)
.forEach(function (c) {
var cmd = parseShell(c);
b.transform(function (file) {
var env = Object.keys(process.env).reduce(function (acc, key) {
acc[key] = process.env[key];
return acc;
}, {});
env.FILENAME = file;
var ps = spawn(cmd[0], cmd.slice(1), { env: env });
var error = '';
ps.stderr.on('data', function (buf) { error += buf });
ps.on('exit', function (code) {
if (code === 0) return;
console.error([
'error running source transform command: ' + c,
error.split('\n').join('\n '),
''
].join('\n'));
process.exit(1);
});
return duplexer(ps.stdin, ps.stdout);
});
})
;
if (argv.standalone === '') {
error('--standalone requires an export name argument');
return b;
}
return b;
};
function splitOnColon (f) {
var pos = f.lastIndexOf(':');
if (pos == -1) {
return [f]; // No colon
} else {
if ((/[a-zA-Z]:[\\/]/.test(f)) && (pos == 1)){
return [f]; // Windows path and colon is part of drive name
} else {
return [f.substr(0, pos), f.substr(pos + 1)];
}
}
}
Generated Vendored Executable
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env node
var fs = require('fs');
var JSONStream = require('JSONStream');
var through = require('through2');
var mkdirp = require('mkdirp-classic');
var path = require('path');
var b = require('./args')(process.argv.slice(2));
process.stdout.on('error', process.exit);
if ((b.argv._[0] === 'help' && b.argv._[1]) === 'advanced'
|| (b.argv.h || b.argv.help) === 'advanced') {
return fs.createReadStream(__dirname + '/advanced.txt')
.pipe(process.stdout)
.on('close', function () { process.exit(1) })
;
}
if (b.argv._[0] === 'help' || b.argv.h || b.argv.help
|| (process.argv.length <= 2 && process.stdin.isTTY)) {
return fs.createReadStream(__dirname + '/usage.txt')
.pipe(process.stdout)
.on('close', function () { process.exit(1) })
;
}
if (b.argv.version) {
return console.log(require('../package.json').version);
}
b.on('error', errorExit);
if (b.argv.pack) {
process.stdin.pipe(b.pack()).pipe(process.stdout);
process.stdin.resume();
return;
}
if (b.argv.deps) {
var stringify = JSONStream.stringify();
stringify.pipe(process.stdout);
b.pipeline.get('deps').push(through.obj(
function (row, enc, next) { stringify.write(row); next() },
function () { stringify.end() }
));
return b.bundle();
}
if (b.argv.list) {
b.pipeline.get('deps').push(through.obj(
function (row, enc, next) {
console.log(row.file || row.id);
next()
}
));
return b.bundle();
}
var bundle = b.bundle();
bundle.on('error', errorExit);
bundle.on('end', successExit);
var tmpfile;
var outfile = b.argv.o || b.argv.outfile;
if (outfile) {
mkdirp.sync(path.dirname(outfile));
// we'll output to a temp file within same filesystem, then atomically overwrite outfile once successful
tmpfile = outfile + ".tmp-browserify-" + Math.random().toFixed(20).slice(2)
bundle.pipe(fs.createWriteStream(tmpfile));
}
else {
bundle.pipe(process.stdout);
}
function errorExit(err) {
if (tmpfile) fs.unlink(tmpfile, function (err) {
if (err) /* no-op, we're already exiting unhappily… */;
});
if (err.stack) {
console.error(err.stack);
}
else {
console.error(String(err));
}
process.exit(1);
}
function successExit() {
if (tmpfile && outfile) fs.rename(tmpfile, outfile, function (err) {
if (err) errorExit(err);
});
}
+34
View File
@@ -0,0 +1,34 @@
Usage: browserify [entry files] {OPTIONS}
Standard Options:
--outfile, -o Write the browserify bundle to this file.
If unspecified, browserify prints to stdout.
--require, -r A module name or file to bundle.require()
Optionally use a colon separator to set the target.
--entry, -e An entry point of your app
--ignore, -i Replace a file with an empty stub. Files can be globs.
--exclude, -u Omit a file from the output bundle. Files can be globs.
--external, -x Reference a file from another bundle. Files can be globs.
--transform, -t Use a transform module on top-level files.
--command, -c Use a transform command on top-level files.
--standalone -s Generate a UMD bundle for the supplied export name.
This bundle works with other module systems and sets the name
given as a window global if no module system is found.
--debug -d Enable source maps that allow you to debug your files
separately.
--help, -h Show this message
For advanced options, type `browserify --help advanced`.
Specify a parameter.
File diff suppressed because it is too large Load Diff
+78
View File
@@ -0,0 +1,78 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at (any one or all of these):
* substack@gmail.com
All complaints will be reviewed and investigated and will result in a response
that is deemed necessary and appropriate to the circumstances. The project team
is obligated to maintain confidentiality with regard to the reporter of an
incident. Further details of specific enforcement policies may be posted
separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
+1
View File
@@ -0,0 +1 @@
module.exports = function (n) { return n * 3 };
+5
View File
@@ -0,0 +1,5 @@
var bar = require('./bar');
module.exports = function (n) {
return n * bar(n);
};
+2
View File
@@ -0,0 +1,2 @@
var foo = require('./foo');
console.log(foo(5));
+4
View File
@@ -0,0 +1,4 @@
var browserify = require('browserify');
var b = browserify();
b.add('./browser/main.js');
b.bundle().pipe(process.stdout);
+2
View File
@@ -0,0 +1,2 @@
var robot = require('./robot');
console.log(robot('beep'));
+2
View File
@@ -0,0 +1,2 @@
var robot = require('./robot');
console.log(robot('boop'));
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
browserify -r ./robot.js > static/common.js
browserify -x ./robot.js beep.js > static/beep.js
browserify -x ./robot.js boop.js > static/boop.js
+1
View File
@@ -0,0 +1 @@
module.exports = function (s) { return s.toUpperCase() + '!' };
@@ -0,0 +1,2 @@
<script src="common.js"></script>
<script src="beep.js"></script>
@@ -0,0 +1,2 @@
<script src="common.js"></script>
<script src="boop.js"></script>
+13
View File
@@ -0,0 +1,13 @@
var browserify = require('../..'),
path = require('path'),
fs = require('fs'),
bundlePath = path.join(__dirname, 'js', 'build', 'bundle.js');
browserify()
.require(require.resolve('./js/main.js'), {
entry: true,
debug: true
})
.bundle()
.on('error', function (err) { console.error(err); })
.pipe(fs.createWriteStream(bundlePath));
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
../../bin/cmd.js --debug -e ./js/main.js > js/build/bundle.js
echo bundle was generated with source maps, you can now open index.html
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title></title>
<script type="text/javascript" src="./js/build/bundle.js"></script>
</head>
<body>
<p>Open your dev tools ;)</p>
</body>
</html>
@@ -0,0 +1 @@
!.gitignore
+28
View File
@@ -0,0 +1,28 @@
;(function(e,t,n,r){function i(r){if(!n[r]){if(!t[r]){if(e)return e(r);throw new Error("Cannot find module '"+r+"'")}var s=n[r]={exports:{}};t[r][0](function(e){var n=t[r][1][e];return i(n?n:e)},s,s.exports)}return n[r].exports}for(var s=0;s<r.length;s++)i(r[s]);return i})(typeof require!=="undefined"&&require,{1:[function(require,module,exports){
console.log('main line 1');
var foo = require('./foo.js');
foo();
},{"./foo.js":2}],2:[function(require,module,exports){
console.log('foo line 1');
var bar = require('./wunder/bar');
module.exports = function foo() {
console.log('hello from foo line 5');
bar();
};
},{"./wunder/bar":3}],3:[function(require,module,exports){
console.log('bar line 1');
'use strict';
// this is a meaningless comment to add some lines
module.exports = function bar() {
console.log('hello from bar line 7');
};
},{}]},{},[1])
//@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlcyI6WyIvVXNlcnMvdGhsb3JlbnovZGV2L2pzL3Byb2plY3RzL2ZvcmtzL25vZGUtYnJvd3NlcmlmeS9leGFtcGxlL3NvdXJjZV9tYXBzL2pzL21haW4uanMiLCIvVXNlcnMvdGhsb3JlbnovZGV2L2pzL3Byb2plY3RzL2ZvcmtzL25vZGUtYnJvd3NlcmlmeS9leGFtcGxlL3NvdXJjZV9tYXBzL2pzL2Zvby5qcyIsIi9Vc2Vycy90aGxvcmVuei9kZXYvanMvcHJvamVjdHMvZm9ya3Mvbm9kZS1icm93c2VyaWZ5L2V4YW1wbGUvc291cmNlX21hcHMvanMvd3VuZGVyL2Jhci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiJmaWxlOi8vbG9jYWxob3N0Iiwic291cmNlQ29udGVudCI6WyJjb25zb2xlLmxvZygnbWFpbiBsaW5lIDEnKTtcbnZhciBmb28gPSByZXF1aXJlKCcuL2Zvby5qcycpO1xuXG5mb28oKTtcbiIsImNvbnNvbGUubG9nKCdmb28gbGluZSAxJyk7XG52YXIgYmFyID0gcmVxdWlyZSgnLi93dW5kZXIvYmFyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZm9vKCkge1xuICBjb25zb2xlLmxvZygnaGVsbG8gZnJvbSBmb28gbGluZSA1Jyk7XG4gIGJhcigpO1xufTtcbiIsImNvbnNvbGUubG9nKCdiYXIgbGluZSAxJyk7XG4ndXNlIHN0cmljdCc7XG5cbi8vIHRoaXMgaXMgYSBtZWFuaW5nbGVzcyBjb21tZW50IHRvIGFkZCBzb21lIGxpbmVzXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYmFyKCkge1xuICBjb25zb2xlLmxvZygnaGVsbG8gZnJvbSBiYXIgbGluZSA3Jyk7XG59O1xuIl19
;
+7
View File
@@ -0,0 +1,7 @@
console.log('foo line 1');
var bar = require('./wunder/bar');
module.exports = function foo() {
console.log('hello from foo line 5');
bar();
};
+4
View File
@@ -0,0 +1,4 @@
console.log('main line 1');
var foo = require('./foo.js');
foo();
+8
View File
@@ -0,0 +1,8 @@
console.log('bar line 1');
'use strict';
// this is a meaningless comment to add some lines
module.exports = function bar() {
console.log('hello from bar line 7');
};
+875
View File
@@ -0,0 +1,875 @@
var path = require('path');
var mdeps = require('module-deps');
var depsSort = require('deps-sort');
var bpack = require('browser-pack');
var insertGlobals = require('insert-module-globals');
var syntaxError = require('syntax-error');
var builtins = require('./lib/builtins.js');
var splicer = require('labeled-stream-splicer');
var through = require('through2');
var concat = require('concat-stream');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
var xtend = require('xtend');
var isArray = Array.isArray;
var defined = require('defined');
var has = require('has');
var sanitize = require('htmlescape').sanitize;
var shasum = require('shasum-object');
var bresolve = require('browser-resolve');
var resolve = require('resolve');
var readonly = require('read-only-stream');
module.exports = Browserify;
inherits(Browserify, EventEmitter);
var fs = require('fs');
var path = require('path');
var cachedPathRelative = require('cached-path-relative');
var paths = {
empty: path.join(__dirname, 'lib/_empty.js')
};
function Browserify (files, opts) {
var self = this;
if (!(this instanceof Browserify)) return new Browserify(files, opts);
if (!opts) opts = {};
if (typeof files === 'string' || isArray(files) || isStream(files)) {
opts = xtend(opts, { entries: [].concat(opts.entries || [], files) });
}
else opts = xtend(files, opts);
if (opts.node) {
opts.bare = true;
opts.browserField = false;
}
if (opts.bare) {
opts.builtins = false;
opts.commondir = false;
if (opts.insertGlobalVars === undefined) {
opts.insertGlobalVars = {}
Object.keys(insertGlobals.vars).forEach(function (name) {
if (name !== '__dirname' && name !== '__filename') {
opts.insertGlobalVars[name] = undefined;
}
})
}
}
self._options = opts;
if (opts.noparse) opts.noParse = opts.noparse;
if (opts.basedir !== undefined && typeof opts.basedir !== 'string') {
throw new Error('opts.basedir must be either undefined or a string.');
}
opts.dedupe = opts.dedupe === false ? false : true;
self._external = [];
self._exclude = [];
self._ignore = [];
self._expose = {};
self._hashes = {};
self._pending = 0;
self._transformOrder = 0;
self._transformPending = 0;
self._transforms = [];
self._entryOrder = 0;
self._ticked = false;
var browserField = opts.browserField
self._bresolve = browserField === false
? function (id, opts, cb) {
if (!opts.basedir) opts.basedir = path.dirname(opts.filename)
resolve(id, opts, cb)
}
: typeof browserField === 'string'
? function (id, opts, cb) {
opts.browser = browserField
bresolve(id, opts, cb)
}
: bresolve
;
self._syntaxCache = {};
var ignoreTransform = [].concat(opts.ignoreTransform).filter(Boolean);
self._filterTransform = function (tr) {
if (isArray(tr)) {
return ignoreTransform.indexOf(tr[0]) === -1;
}
return ignoreTransform.indexOf(tr) === -1;
};
self.pipeline = self._createPipeline(opts);
[].concat(opts.transform).filter(Boolean).filter(self._filterTransform)
.forEach(function (tr) {
self.transform(tr);
});
[].concat(opts.entries).filter(Boolean).forEach(function (file) {
self.add(file, { basedir: opts.basedir });
});
[].concat(opts.require).filter(Boolean).forEach(function (file) {
self.require(file, { basedir: opts.basedir });
});
[].concat(opts.plugin).filter(Boolean).forEach(function (p) {
self.plugin(p, { basedir: opts.basedir });
});
}
Browserify.prototype.require = function (file, opts) {
var self = this;
if (isArray(file)) {
file.forEach(function (x) {
if (typeof x === 'object') {
self.require(x.file, xtend(opts, x));
}
else self.require(x, opts);
});
return this;
}
if (!opts) opts = {};
var basedir = defined(opts.basedir, self._options.basedir, process.cwd());
var expose = opts.expose;
if (file === expose && /^[\.]/.test(expose)) {
expose = '/' + relativePath(basedir, expose);
}
if (expose === undefined && this._options.exposeAll) {
expose = true;
}
if (expose === true) {
expose = '/' + relativePath(basedir, file);
}
if (isStream(file)) {
self._pending ++;
var order = self._entryOrder ++;
file.pipe(concat(function (buf) {
var filename = opts.file || file.file || path.join(
basedir,
'_stream_' + order + '.js'
);
var id = file.id || expose || filename;
if (expose || opts.entry === false) {
self._expose[id] = filename;
}
if (!opts.entry && self._options.exports === undefined) {
self._bpack.hasExports = true;
}
var rec = {
source: buf.toString('utf8'),
entry: defined(opts.entry, false),
file: filename,
id: id
};
if (rec.entry) rec.order = order;
if (rec.transform === false) rec.transform = false;
self.pipeline.write(rec);
if (-- self._pending === 0) self.emit('_ready');
}));
return this;
}
var row;
if (typeof file === 'object') {
row = xtend(file, opts);
}
else if (!opts.entry && isExternalModule(file)) {
// external module or builtin
row = xtend(opts, { id: expose || file, file: file });
}
else {
row = xtend(opts, { file: path.resolve(basedir, file) });
}
if (!row.id) {
row.id = expose || row.file;
}
if (expose || !row.entry) {
// Make this available to mdeps so that it can assign the value when it
// resolves the pathname.
row.expose = row.id;
}
if (opts.external) return self.external(file, opts);
if (row.entry === undefined) row.entry = false;
if (!row.entry && self._options.exports === undefined) {
self._bpack.hasExports = true;
}
if (row.entry) row.order = self._entryOrder ++;
if (opts.transform === false) row.transform = false;
self.pipeline.write(row);
return self;
};
Browserify.prototype.add = function (file, opts) {
var self = this;
if (!opts) opts = {};
if (isArray(file)) {
file.forEach(function (x) { self.add(x, opts) });
return this;
}
return this.require(file, xtend({ entry: true, expose: false }, opts));
};
Browserify.prototype.external = function (file, opts) {
var self = this;
if (isArray(file)) {
file.forEach(function (f) {
if (typeof f === 'object') {
self.external(f, xtend(opts, f));
}
else self.external(f, opts)
});
return this;
}
if (file && typeof file === 'object' && typeof file.bundle === 'function') {
var b = file;
self._pending ++;
var bdeps = {};
var blabels = {};
b.on('label', function (prev, id) {
self._external.push(id);
if (prev !== id) {
blabels[prev] = id;
self._external.push(prev);
}
});
b.pipeline.get('deps').push(through.obj(function (row, enc, next) {
bdeps = xtend(bdeps, row.deps);
this.push(row);
next();
}));
self.on('dep', function (row) {
Object.keys(row.deps).forEach(function (key) {
var prev = bdeps[key];
if (prev) {
var id = blabels[prev];
if (id) {
row.indexDeps[key] = id;
}
}
});
});
b.pipeline.get('label').once('end', function () {
if (-- self._pending === 0) self.emit('_ready');
});
return this;
}
if (!opts) opts = {};
var basedir = defined(opts.basedir, process.cwd());
this._external.push(file);
this._external.push('/' + relativePath(basedir, file));
return this;
};
Browserify.prototype.exclude = function (file, opts) {
if (!opts) opts = {};
if (isArray(file)) {
var self = this;
file.forEach(function(file) {
self.exclude(file, opts);
});
return this;
}
var basedir = defined(opts.basedir, process.cwd());
this._exclude.push(file);
this._exclude.push('/' + relativePath(basedir, file));
return this;
};
Browserify.prototype.ignore = function (file, opts) {
if (!opts) opts = {};
if (isArray(file)) {
var self = this;
file.forEach(function(file) {
self.ignore(file, opts);
});
return this;
}
var basedir = defined(opts.basedir, process.cwd());
// Handle relative paths
if (file[0] === '.') {
this._ignore.push(path.resolve(basedir, file));
}
else {
this._ignore.push(file);
}
return this;
};
Browserify.prototype.transform = function (tr, opts) {
var self = this;
if (typeof opts === 'function' || typeof opts === 'string') {
tr = [ opts, tr ];
}
if (isArray(tr)) {
opts = tr[1];
tr = tr[0];
}
//if the bundler is ignoring this transform
if (typeof tr === 'string' && !self._filterTransform(tr)) {
return this;
}
function resolved () {
self._transforms[order] = rec;
-- self._pending;
if (-- self._transformPending === 0) {
self._transforms.forEach(function (transform) {
self.pipeline.write(transform);
});
if (self._pending === 0) {
self.emit('_ready');
}
}
}
if (!opts) opts = {};
opts._flags = '_flags' in opts ? opts._flags : self._options;
var basedir = defined(opts.basedir, this._options.basedir, process.cwd());
var order = self._transformOrder ++;
self._pending ++;
self._transformPending ++;
var rec = {
transform: tr,
options: opts,
global: opts.global
};
if (typeof tr === 'string') {
var topts = {
basedir: basedir,
paths: (self._options.paths || []).map(function (p) {
return path.resolve(basedir, p);
})
};
resolve(tr, topts, function (err, res) {
if (err) return self.emit('error', err);
rec.transform = res;
resolved();
});
}
else process.nextTick(resolved);
return this;
};
Browserify.prototype.plugin = function (p, opts) {
if (isArray(p)) {
opts = p[1];
p = p[0];
}
if (!opts) opts = {};
var basedir = defined(opts.basedir, this._options.basedir, process.cwd());
if (typeof p === 'function') {
p(this, opts);
}
else {
var pfile = resolve.sync(String(p), { basedir: basedir })
var f = require(pfile);
if (typeof f !== 'function') {
throw new Error('plugin ' + p + ' should export a function');
}
f(this, opts);
}
return this;
};
Browserify.prototype._createPipeline = function (opts) {
var self = this;
if (!opts) opts = {};
this._mdeps = this._createDeps(opts);
this._mdeps.on('file', function (file, id) {
pipeline.emit('file', file, id);
self.emit('file', file, id);
});
this._mdeps.on('package', function (pkg) {
pipeline.emit('package', pkg);
self.emit('package', pkg);
});
this._mdeps.on('transform', function (tr, file) {
pipeline.emit('transform', tr, file);
self.emit('transform', tr, file);
});
var dopts = {
index: !opts.fullPaths && !opts.exposeAll,
dedupe: opts.dedupe,
expose: this._expose
};
this._bpack = bpack(xtend(opts, { raw: true }));
var pipeline = splicer.obj([
'record', [ this._recorder() ],
'deps', [ this._mdeps ],
'json', [ this._json() ],
'unbom', [ this._unbom() ],
'unshebang', [ this._unshebang() ],
'syntax', [ this._syntax() ],
'sort', [ depsSort(dopts) ],
'dedupe', [ this._dedupe() ],
'label', [ this._label(opts) ],
'emit-deps', [ this._emitDeps() ],
'debug', [ this._debug(opts) ],
'pack', [ this._bpack ],
'wrap', []
]);
if (opts.exposeAll) {
var basedir = defined(opts.basedir, process.cwd());
pipeline.get('deps').push(through.obj(function (row, enc, next) {
if (self._external.indexOf(row.id) >= 0) return next();
if (self._external.indexOf(row.file) >= 0) return next();
if (isAbsolutePath(row.id)) {
row.id = '/' + relativePath(basedir, row.file);
}
Object.keys(row.deps || {}).forEach(function (key) {
row.deps[key] = '/' + relativePath(basedir, row.deps[key]);
});
this.push(row);
next();
}));
}
return pipeline;
};
Browserify.prototype._createDeps = function (opts) {
var self = this;
var mopts = xtend(opts);
var basedir = defined(opts.basedir, process.cwd());
// Let mdeps populate these values since it will be resolving file paths
// anyway.
mopts.expose = this._expose;
mopts.extensions = [ '.js', '.json' ].concat(mopts.extensions || []);
self._extensions = mopts.extensions;
mopts.transform = [];
mopts.transformKey = defined(opts.transformKey, [ 'browserify', 'transform' ]);
mopts.postFilter = function (id, file, pkg) {
if (opts.postFilter && !opts.postFilter(id, file, pkg)) return false;
if (self._external.indexOf(file) >= 0) return false;
if (self._exclude.indexOf(file) >= 0) return false;
//filter transforms on module dependencies
if (pkg && pkg.browserify && pkg.browserify.transform) {
//In edge cases it may be a string
pkg.browserify.transform = [].concat(pkg.browserify.transform)
.filter(Boolean)
.filter(self._filterTransform);
}
return true;
};
mopts.filter = function (id) {
if (opts.filter && !opts.filter(id)) return false;
if (self._external.indexOf(id) >= 0) return false;
if (self._exclude.indexOf(id) >= 0) return false;
if (opts.bundleExternal === false && isExternalModule(id)) {
return false;
}
return true;
};
mopts.resolve = function (id, parent, cb) {
if (self._ignore.indexOf(id) >= 0) return cb(null, paths.empty, {});
self._bresolve(id, parent, function (err, file, pkg) {
if (file && self._ignore.indexOf(file) >= 0) {
return cb(null, paths.empty, {});
}
if (file && self._ignore.length) {
var nm = file.replace(/\\/g, '/').split('/node_modules/')[1];
if (nm) {
nm = nm.split('/')[0];
if (self._ignore.indexOf(nm) >= 0) {
return cb(null, paths.empty, {});
}
}
}
if (file) {
var ex = '/' + relativePath(basedir, file);
if (self._external.indexOf(ex) >= 0) {
return cb(null, ex);
}
if (self._exclude.indexOf(ex) >= 0) {
return cb(null, ex);
}
if (self._ignore.indexOf(ex) >= 0) {
return cb(null, paths.empty, {});
}
}
if (err) cb(err, file, pkg)
else if (file) {
if (opts.preserveSymlinks && parent.id !== self._mdeps.top.id) {
return cb(err, path.resolve(file), pkg, file)
}
fs.realpath(file, function (err, res) {
cb(err, res, pkg, file);
});
} else cb(err, null, pkg)
});
};
if (opts.builtins === false) {
mopts.modules = {};
self._exclude.push.apply(self._exclude, Object.keys(builtins));
}
else if (opts.builtins && isArray(opts.builtins)) {
mopts.modules = {};
opts.builtins.forEach(function (key) {
mopts.modules[key] = builtins[key];
});
}
else if (opts.builtins && typeof opts.builtins === 'object') {
mopts.modules = opts.builtins;
}
else mopts.modules = xtend(builtins);
Object.keys(builtins).forEach(function (key) {
if (!has(mopts.modules, key)) self._exclude.push(key);
});
mopts.globalTransform = [];
if (!this._bundled) {
this.once('bundle', function () {
self.pipeline.write({
transform: globalTr,
global: true,
options: {}
});
});
}
var no = [].concat(opts.noParse).filter(Boolean);
var absno = no.filter(function(x) {
return typeof x === 'string';
}).map(function (x) {
return path.resolve(basedir, x);
});
function globalTr (file) {
if (opts.detectGlobals === false) return through();
if (opts.noParse === true) return through();
if (no.indexOf(file) >= 0) return through();
if (absno.indexOf(file) >= 0) return through();
var parts = file.replace(/\\/g, '/').split('/node_modules/');
for (var i = 0; i < no.length; i++) {
if (typeof no[i] === 'function' && no[i](file)) {
return through();
}
else if (no[i] === parts[parts.length-1].split('/')[0]) {
return through();
}
else if (no[i] === parts[parts.length-1]) {
return through();
}
}
if (opts.commondir === false && opts.builtins === false) {
opts.insertGlobalVars = xtend({
__dirname: function(file, basedir) {
var dir = path.dirname(path.relative(basedir, file));
return 'require("path").join(__dirname,' + dir.split(path.sep).map(JSON.stringify).join(',') + ')';
},
__filename: function(file, basedir) {
var filename = path.relative(basedir, file);
return 'require("path").join(__dirname,' + filename.split(path.sep).map(JSON.stringify).join(',') + ')';
}
}, opts.insertGlobalVars);
}
var vars = xtend({
process: function () { return "require('_process')" },
}, opts.insertGlobalVars);
if (opts.bundleExternal === false) {
vars.process = undefined;
vars.buffer = undefined;
}
return insertGlobals(file, xtend(opts, {
debug: opts.debug,
always: opts.insertGlobals,
basedir: opts.commondir === false && isArray(opts.builtins)
? '/'
: opts.basedir || process.cwd()
,
vars: vars
}));
}
return mdeps(mopts);
};
Browserify.prototype._recorder = function (opts) {
var self = this;
var ended = false;
this._recorded = [];
if (!this._ticked) {
process.nextTick(function () {
self._ticked = true;
self._recorded.forEach(function (row) {
stream.push(row);
});
if (ended) stream.push(null);
});
}
var stream = through.obj(write, end);
return stream;
function write (row, enc, next) {
self._recorded.push(row);
if (self._ticked) this.push(row);
next();
}
function end () {
ended = true;
if (self._ticked) this.push(null);
}
};
Browserify.prototype._json = function () {
return through.obj(function (row, enc, next) {
if (/\.json$/.test(row.file)) {
var sanitizedString = sanitize(row.source);
try {
// check json validity
JSON.parse(sanitizedString);
row.source = 'module.exports=' + sanitizedString;
} catch (err) {
err.message = 'While parsing ' + (row.file || row.id) + ': ' + err.message
this.emit('error', err);
return;
}
}
this.push(row);
next();
});
};
Browserify.prototype._unbom = function () {
return through.obj(function (row, enc, next) {
if (/^\ufeff/.test(row.source)) {
row.source = row.source.replace(/^\ufeff/, '');
}
this.push(row);
next();
});
};
Browserify.prototype._unshebang = function () {
return through.obj(function (row, enc, next) {
if (/^#!/.test(row.source)) {
row.source = row.source.replace(/^#![^\n]*\n/, '');
}
this.push(row);
next();
});
};
Browserify.prototype._syntax = function () {
var self = this;
return through.obj(function (row, enc, next) {
var h = shasum(row.source);
if (typeof self._syntaxCache[h] === 'undefined') {
var err = syntaxError(row.source, row.file || row.id);
if (err) return this.emit('error', err);
self._syntaxCache[h] = true;
}
this.push(row);
next();
});
};
Browserify.prototype._dedupe = function () {
return through.obj(function (row, enc, next) {
if (!row.dedupeIndex && row.dedupe) {
row.source = 'arguments[4]['
+ JSON.stringify(row.dedupe)
+ '][0].apply(exports,arguments)'
;
row.nomap = true;
}
else if (row.dedupeIndex) {
row.source = 'arguments[4]['
+ JSON.stringify(row.dedupeIndex)
+ '][0].apply(exports,arguments)'
;
row.nomap = true;
}
if (row.dedupeIndex && row.indexDeps) {
row.indexDeps.dup = row.dedupeIndex;
}
this.push(row);
next();
});
};
Browserify.prototype._label = function (opts) {
var self = this;
var basedir = defined(opts.basedir, process.cwd());
return through.obj(function (row, enc, next) {
var prev = row.id;
if (self._external.indexOf(row.id) >= 0) return next();
if (self._external.indexOf('/' + relativePath(basedir, row.id)) >= 0) {
return next();
}
if (self._external.indexOf(row.file) >= 0) return next();
if (row.index) row.id = row.index;
self.emit('label', prev, row.id);
if (row.indexDeps) row.deps = row.indexDeps || {};
Object.keys(row.deps).forEach(function (key) {
if (self._expose[key]) {
row.deps[key] = key;
return;
}
var afile = path.resolve(path.dirname(row.file), key);
var rfile = '/' + relativePath(basedir, afile);
if (self._external.indexOf(rfile) >= 0) {
row.deps[key] = rfile;
}
if (self._external.indexOf(afile) >= 0) {
row.deps[key] = rfile;
}
if (self._external.indexOf(key) >= 0) {
row.deps[key] = key;
return;
}
for (var i = 0; i < self._extensions.length; i++) {
var ex = self._extensions[i];
if (self._external.indexOf(rfile + ex) >= 0) {
row.deps[key] = rfile + ex;
break;
}
}
});
if (row.entry || row.expose) {
self._bpack.standaloneModule = row.id;
}
this.push(row);
next();
});
};
Browserify.prototype._emitDeps = function () {
var self = this;
return through.obj(function (row, enc, next) {
self.emit('dep', row);
this.push(row);
next();
})
};
Browserify.prototype._debug = function (opts) {
var basedir = defined(opts.basedir, process.cwd());
return through.obj(function (row, enc, next) {
if (opts.debug) {
row.sourceRoot = 'file://localhost';
row.sourceFile = relativePath(basedir, row.file);
}
this.push(row);
next();
});
};
Browserify.prototype.reset = function (opts) {
if (!opts) opts = {};
var hadExports = this._bpack.hasExports;
this.pipeline = this._createPipeline(xtend(opts, this._options));
this._bpack.hasExports = hadExports;
this._entryOrder = 0;
this._bundled = false;
this.emit('reset');
};
Browserify.prototype.bundle = function (cb) {
var self = this;
if (cb && typeof cb === 'object') {
throw new Error(
'bundle() no longer accepts option arguments.\n'
+ 'Move all option arguments to the browserify() constructor.'
);
}
if (this._bundled) {
var recorded = this._recorded;
this.reset();
recorded.forEach(function (x) {
self.pipeline.write(x);
});
}
var output = readonly(this.pipeline);
if (cb) {
output.on('error', cb);
output.pipe(concat(function (body) {
cb(null, body);
}));
}
function ready () {
self.emit('bundle', output);
self.pipeline.end();
}
if (this._pending === 0) ready();
else this.once('_ready', ready);
this._bundled = true;
return output;
};
function isStream (s) { return s && typeof s.pipe === 'function' }
function isAbsolutePath (file) {
var regexp = process.platform === 'win32' ?
/^\w:/ :
/^\//;
return regexp.test(file);
}
function isExternalModule (file) {
var regexp = process.platform === 'win32' ?
/^(\.|\w:)/ :
/^[\/.]/;
return !regexp.test(file);
}
function relativePath (from, to) {
// Replace \ with / for OS-independent behavior
return cachedPathRelative(from, to).replace(/\\/g, '/');
}
View File
+41
View File
@@ -0,0 +1,41 @@
exports.assert = require.resolve('assert/');
exports.buffer = require.resolve('buffer/');
exports.child_process = require.resolve('./_empty.js');
exports.cluster = require.resolve('./_empty.js');
exports.console = require.resolve('console-browserify');
exports.constants = require.resolve('constants-browserify');
exports.crypto = require.resolve('crypto-browserify');
exports.dgram = require.resolve('./_empty.js');
exports.dns = require.resolve('./_empty.js');
exports.domain = require.resolve('domain-browser');
exports.events = require.resolve('events/');
exports.fs = require.resolve('./_empty.js');
exports.http = require.resolve('stream-http');
exports.https = require.resolve('https-browserify');
exports.http2 = require.resolve('./_empty.js');
exports.inspector = require.resolve('./_empty.js');
exports.module = require.resolve('./_empty.js');
exports.net = require.resolve('./_empty.js');
exports.os = require.resolve('os-browserify/browser.js');
exports.path = require.resolve('path-browserify');
exports.perf_hooks = require.resolve('./_empty.js')
exports.punycode = require.resolve('punycode/');
exports.querystring = require.resolve('querystring-es3/');
exports.readline = require.resolve('./_empty.js');
exports.repl = require.resolve('./_empty.js');
exports.stream = require.resolve('stream-browserify');
exports._stream_duplex = require.resolve('readable-stream/duplex.js');
exports._stream_passthrough = require.resolve('readable-stream/passthrough.js');
exports._stream_readable = require.resolve('readable-stream/readable.js');
exports._stream_transform = require.resolve('readable-stream/transform.js');
exports._stream_writable = require.resolve('readable-stream/writable.js');
exports.string_decoder = require.resolve('string_decoder/');
exports.sys = require.resolve('util/util.js');
exports.timers = require.resolve('timers-browserify');
exports.tls = require.resolve('./_empty.js');
exports.tty = require.resolve('tty-browserify');
exports.url = require.resolve('url/');
exports.util = require.resolve('util/util.js');
exports.vm = require.resolve('vm-browserify');
exports.zlib = require.resolve('browserify-zlib');
exports._process = require.resolve('process/browser');
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+129
View File
@@ -0,0 +1,129 @@
# brace-expansion
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
as known from sh/bash, in JavaScript.
[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
## Example
```js
var expand = require('brace-expansion');
expand('file-{a,b,c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('-v{,,}')
// => ['-v', '-v', '-v']
expand('file{0..2}.jpg')
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
expand('file-{a..c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('file{2..0}.jpg')
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
expand('file{0..4..2}.jpg')
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
expand('file-{a..e..2}.jpg')
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
expand('file{00..10..5}.jpg')
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
expand('{{A..C},{a..c}}')
// => ['A', 'B', 'C', 'a', 'b', 'c']
expand('ppp{,config,oe{,conf}}')
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
```
## API
```js
var expand = require('brace-expansion');
```
### var expanded = expand(str)
Return an array of all possible and valid expansions of `str`. If none are
found, `[str]` is returned.
Valid expansions are:
```js
/^(.*,)+(.+)?$/
// {a,b,...}
```
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
A numeric sequence from `x` to `y` inclusive, with optional increment.
If `x` or `y` start with a leading `0`, all the numbers will be padded
to have equal length. Negative numbers and backwards iteration work too.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
`x` and `y` must be exactly one character, and if given, `incr` must be a
number.
For compatibility reasons, the string `${` is not eligible for brace expansion.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install brace-expansion
```
## Contributors
- [Julian Gruber](https://github.com/juliangruber)
- [Isaac Z. Schlueter](https://github.com/isaacs)
## Sponsors
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+201
View File
@@ -0,0 +1,201 @@
var concatMap = require('concat-map');
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str) {
if (!str)
return [];
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.substr(0, 2) === '{}') {
str = '\\{\\}' + str.substr(2);
}
return expand(escapeBraces(str), true).map(unescapeBraces);
}
function identity(e) {
return e;
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
if (!m || /\$$/.test(m.pre)) return [str];
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,.*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], false).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post, false)
: [''];
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, false)
: [''];
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.abs(numeric(n[2]))
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = concatMap(n, function(el) { return expand(el, false) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
return expansions;
}
@@ -0,0 +1,47 @@
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
"version": "1.1.11",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"
},
"homepage": "https://github.com/juliangruber/brace-expansion",
"main": "index.js",
"scripts": {
"test": "tape test/*.js",
"gentest": "bash test/generate.sh",
"bench": "matcha test/perf/bench.js"
},
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
},
"devDependencies": {
"matcha": "^0.7.0",
"tape": "^4.6.0"
},
"keywords": [],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
}
}
+21
View File
@@ -0,0 +1,21 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
## Glob Logo
Glob's logo created by Tanya Brassie <http://tanyabrassie.com/>, licensed
under a Creative Commons Attribution-ShareAlike 4.0 International License
https://creativecommons.org/licenses/by-sa/4.0/
+378
View File
@@ -0,0 +1,378 @@
# Glob
Match files using the patterns the shell uses, like stars and stuff.
[![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Build Status](https://ci.appveyor.com/api/projects/status/kd7f3yftf7unxlsx?svg=true)](https://ci.appveyor.com/project/isaacs/node-glob) [![Coverage Status](https://coveralls.io/repos/isaacs/node-glob/badge.svg?branch=master&service=github)](https://coveralls.io/github/isaacs/node-glob?branch=master)
This is a glob implementation in JavaScript. It uses the `minimatch`
library to do its matching.
![a fun cartoon logo made of glob characters](logo/glob.png)
## Usage
Install with npm
```
npm i glob
```
```javascript
var glob = require("glob")
// options is optional
glob("**/*.js", options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
})
```
## Glob Primer
"Globs" are the patterns you type when you do stuff like `ls *.js` on
the command line, or put `build/*` in a `.gitignore` file.
Before parsing the path part patterns, braced sections are expanded
into a set. Braced sections start with `{` and end with `}`, with any
number of comma-delimited sections within. Braced sections may contain
slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`.
The following characters have special magic meaning when used in a
path portion:
* `*` Matches 0 or more characters in a single path portion
* `?` Matches 1 character
* `[...]` Matches a range of characters, similar to a RegExp range.
If the first character of the range is `!` or `^` then it matches
any character not in the range.
* `!(pattern|pattern|pattern)` Matches anything that does not match
any of the patterns provided.
* `?(pattern|pattern|pattern)` Matches zero or one occurrence of the
patterns provided.
* `+(pattern|pattern|pattern)` Matches one or more occurrences of the
patterns provided.
* `*(a|b|c)` Matches zero or more occurrences of the patterns provided
* `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns
provided
* `**` If a "globstar" is alone in a path portion, then it matches
zero or more directories and subdirectories searching for matches.
It does not crawl symlinked directories.
### Dots
If a file or directory path portion has a `.` as the first character,
then it will not match any glob pattern unless that pattern's
corresponding path part also has a `.` as its first character.
For example, the pattern `a/.*/c` would match the file at `a/.b/c`.
However the pattern `a/*/c` would not, because `*` does not start with
a dot character.
You can make glob treat dots as normal characters by setting
`dot:true` in the options.
### Basename Matching
If you set `matchBase:true` in the options, and the pattern has no
slashes in it, then it will seek for any file anywhere in the tree
with a matching basename. For example, `*.js` would match
`test/simple/basic.js`.
### Empty Sets
If no matching files are found, then an empty array is returned. This
differs from the shell, where the pattern itself is returned. For
example:
$ echo a*s*d*f
a*s*d*f
To get the bash-style behavior, set the `nonull:true` in the options.
### See Also:
* `man sh`
* `man bash` (Search for "Pattern Matching")
* `man 3 fnmatch`
* `man 5 gitignore`
* [minimatch documentation](https://github.com/isaacs/minimatch)
## glob.hasMagic(pattern, [options])
Returns `true` if there are any special characters in the pattern, and
`false` otherwise.
Note that the options affect the results. If `noext:true` is set in
the options object, then `+(a|b)` will not be considered a magic
pattern. If the pattern has a brace expansion, like `a/{b/c,x/y}`
then that is considered magical, unless `nobrace:true` is set in the
options.
## glob(pattern, [options], cb)
* `pattern` `{String}` Pattern to be matched
* `options` `{Object}`
* `cb` `{Function}`
* `err` `{Error | null}`
* `matches` `{Array<String>}` filenames found matching the pattern
Perform an asynchronous glob search.
## glob.sync(pattern, [options])
* `pattern` `{String}` Pattern to be matched
* `options` `{Object}`
* return: `{Array<String>}` filenames found matching the pattern
Perform a synchronous glob search.
## Class: glob.Glob
Create a Glob object by instantiating the `glob.Glob` class.
```javascript
var Glob = require("glob").Glob
var mg = new Glob(pattern, options, cb)
```
It's an EventEmitter, and starts walking the filesystem to find matches
immediately.
### new glob.Glob(pattern, [options], [cb])
* `pattern` `{String}` pattern to search for
* `options` `{Object}`
* `cb` `{Function}` Called when an error occurs, or matches are found
* `err` `{Error | null}`
* `matches` `{Array<String>}` filenames found matching the pattern
Note that if the `sync` flag is set in the options, then matches will
be immediately available on the `g.found` member.
### Properties
* `minimatch` The minimatch object that the glob uses.
* `options` The options object passed in.
* `aborted` Boolean which is set to true when calling `abort()`. There
is no way at this time to continue a glob search after aborting, but
you can re-use the statCache to avoid having to duplicate syscalls.
* `cache` Convenience object. Each field has the following possible
values:
* `false` - Path does not exist
* `true` - Path exists
* `'FILE'` - Path exists, and is not a directory
* `'DIR'` - Path exists, and is a directory
* `[file, entries, ...]` - Path exists, is a directory, and the
array value is the results of `fs.readdir`
* `statCache` Cache of `fs.stat` results, to prevent statting the same
path multiple times.
* `symlinks` A record of which paths are symbolic links, which is
relevant in resolving `**` patterns.
* `realpathCache` An optional object which is passed to `fs.realpath`
to minimize unnecessary syscalls. It is stored on the instantiated
Glob object, and may be re-used.
### Events
* `end` When the matching is finished, this is emitted with all the
matches found. If the `nonull` option is set, and no match was found,
then the `matches` list contains the original pattern. The matches
are sorted, unless the `nosort` flag is set.
* `match` Every time a match is found, this is emitted with the specific
thing that matched. It is not deduplicated or resolved to a realpath.
* `error` Emitted when an unexpected error is encountered, or whenever
any fs error occurs if `options.strict` is set.
* `abort` When `abort()` is called, this event is raised.
### Methods
* `pause` Temporarily stop the search
* `resume` Resume the search
* `abort` Stop the search forever
### Options
All the options that can be passed to Minimatch can also be passed to
Glob to change pattern matching behavior. Also, some have been added,
or have glob-specific ramifications.
All options are false by default, unless otherwise noted.
All options are added to the Glob object, as well.
If you are running many `glob` operations, you can pass a Glob object
as the `options` argument to a subsequent operation to shortcut some
`stat` and `readdir` calls. At the very least, you may pass in shared
`symlinks`, `statCache`, `realpathCache`, and `cache` options, so that
parallel glob operations will be sped up by sharing information about
the filesystem.
* `cwd` The current working directory in which to search. Defaults
to `process.cwd()`.
* `root` The place where patterns starting with `/` will be mounted
onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
systems, and `C:\` or some such on Windows.)
* `dot` Include `.dot` files in normal matches and `globstar` matches.
Note that an explicit dot in a portion of the pattern will always
match dot files.
* `nomount` By default, a pattern starting with a forward-slash will be
"mounted" onto the root setting, so that a valid filesystem path is
returned. Set this flag to disable that behavior.
* `mark` Add a `/` character to directory matches. Note that this
requires additional stat calls.
* `nosort` Don't sort the results.
* `stat` Set to true to stat *all* results. This reduces performance
somewhat, and is completely unnecessary, unless `readdir` is presumed
to be an untrustworthy indicator of file existence.
* `silent` When an unusual error is encountered when attempting to
read a directory, a warning will be printed to stderr. Set the
`silent` option to true to suppress these warnings.
* `strict` When an unusual error is encountered when attempting to
read a directory, the process will just continue on in search of
other matches. Set the `strict` option to raise an error in these
cases.
* `cache` See `cache` property above. Pass in a previously generated
cache object to save some fs calls.
* `statCache` A cache of results of filesystem information, to prevent
unnecessary stat calls. While it should not normally be necessary
to set this, you may pass the statCache from one glob() call to the
options object of another, if you know that the filesystem will not
change between calls. (See "Race Conditions" below.)
* `symlinks` A cache of known symbolic links. You may pass in a
previously generated `symlinks` object to save `lstat` calls when
resolving `**` matches.
* `sync` DEPRECATED: use `glob.sync(pattern, opts)` instead.
* `nounique` In some cases, brace-expanded patterns can result in the
same file showing up multiple times in the result set. By default,
this implementation prevents duplicates in the result set. Set this
flag to disable that behavior.
* `nonull` Set to never return an empty set, instead returning a set
containing the pattern itself. This is the default in glob(3).
* `debug` Set to enable debug logging in minimatch and glob.
* `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets.
* `noglobstar` Do not match `**` against multiple filenames. (Ie,
treat it as a normal `*` instead.)
* `noext` Do not match `+(a|b)` "extglob" patterns.
* `nocase` Perform a case-insensitive match. Note: on
case-insensitive filesystems, non-magic patterns will match by
default, since `stat` and `readdir` will not raise errors.
* `matchBase` Perform a basename-only match if the pattern does not
contain any slash characters. That is, `*.js` would be treated as
equivalent to `**/*.js`, matching all js files in all directories.
* `nodir` Do not match directories, only files. (Note: to match
*only* directories, simply put a `/` at the end of the pattern.)
* `ignore` Add a pattern or an array of glob patterns to exclude matches.
Note: `ignore` patterns are *always* in `dot:true` mode, regardless
of any other settings.
* `follow` Follow symlinked directories when expanding `**` patterns.
Note that this can result in a lot of duplicate references in the
presence of cyclic links.
* `realpath` Set to true to call `fs.realpath` on all of the results.
In the case of a symlink that cannot be resolved, the full absolute
path to the matched entry is returned (though it will usually be a
broken symlink)
* `absolute` Set to true to always receive absolute paths for matched
files. Unlike `realpath`, this also affects the values returned in
the `match` event.
* `fs` File-system object with Node's `fs` API. By default, the built-in
`fs` module will be used. Set to a volume provided by a library like
`memfs` to avoid using the "real" file-system.
## Comparisons to other fnmatch/glob implementations
While strict compliance with the existing standards is a worthwhile
goal, some discrepancies exist between node-glob and other
implementations, and are intentional.
The double-star character `**` is supported by default, unless the
`noglobstar` flag is set. This is supported in the manner of bsdglob
and bash 4.3, where `**` only has special significance if it is the only
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
`a/**b` will not.
Note that symlinked directories are not crawled as part of a `**`,
though their contents may match against subsequent portions of the
pattern. This prevents infinite loops and duplicates and the like.
If an escaped pattern has no matches, and the `nonull` flag is set,
then glob returns the pattern as-provided, rather than
interpreting the character escapes. For example,
`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
that it does not resolve escaped pattern characters.
If brace expansion is not disabled, then it is performed before any
other interpretation of the glob pattern. Thus, a pattern like
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
checked for validity. Since those two are valid, matching proceeds.
### Comments and Negation
Previously, this module let you mark a pattern as a "comment" if it
started with a `#` character, or a "negated" pattern if it started
with a `!` character.
These options were deprecated in version 5, and removed in version 6.
To specify things that should not match, use the `ignore` option.
## Windows
**Please only use forward-slashes in glob expressions.**
Though windows uses either `/` or `\` as its path separator, only `/`
characters are used by this glob implementation. You must use
forward-slashes **only** in glob expressions. Back-slashes will always
be interpreted as escape characters, not path separators.
Results from absolute patterns such as `/foo/*` are mounted onto the
root setting using `path.join`. On windows, this will by default result
in `/foo/*` matching `C:\foo\bar.txt`.
## Race Conditions
Glob searching, by its very nature, is susceptible to race conditions,
since it relies on directory walking and such.
As a result, it is possible that a file that exists when glob looks for
it may have been deleted or modified by the time it returns the result.
As part of its internal implementation, this program caches all stat
and readdir calls that it makes, in order to cut down on system
overhead. However, this also makes it even more susceptible to races,
especially if the cache or statCache objects are reused between glob
calls.
Users are thus advised not to use a glob result as a guarantee of
filesystem state in the face of rapid changes. For the vast majority
of operations, this is never a problem.
## Glob Logo
Glob's logo was created by [Tanya Brassie](http://tanyabrassie.com/). Logo files can be found [here](https://github.com/isaacs/node-glob/tree/master/logo).
The logo is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/).
## Contributing
Any change to behavior (including bugfixes) must come with a test.
Patches that fail tests or reduce performance will be rejected.
```
# to run tests
npm test
# to re-generate test fixtures
npm run test-regen
# to benchmark against bash/zsh
npm run bench
# to profile javascript
npm run prof
```
![](oh-my-glob.gif)
+238
View File
@@ -0,0 +1,238 @@
exports.setopts = setopts
exports.ownProp = ownProp
exports.makeAbs = makeAbs
exports.finish = finish
exports.mark = mark
exports.isIgnored = isIgnored
exports.childrenIgnored = childrenIgnored
function ownProp (obj, field) {
return Object.prototype.hasOwnProperty.call(obj, field)
}
var fs = require("fs")
var path = require("path")
var minimatch = require("minimatch")
var isAbsolute = require("path-is-absolute")
var Minimatch = minimatch.Minimatch
function alphasort (a, b) {
return a.localeCompare(b, 'en')
}
function setupIgnores (self, options) {
self.ignore = options.ignore || []
if (!Array.isArray(self.ignore))
self.ignore = [self.ignore]
if (self.ignore.length) {
self.ignore = self.ignore.map(ignoreMap)
}
}
// ignore patterns are always in dot:true mode.
function ignoreMap (pattern) {
var gmatcher = null
if (pattern.slice(-3) === '/**') {
var gpattern = pattern.replace(/(\/\*\*)+$/, '')
gmatcher = new Minimatch(gpattern, { dot: true })
}
return {
matcher: new Minimatch(pattern, { dot: true }),
gmatcher: gmatcher
}
}
function setopts (self, pattern, options) {
if (!options)
options = {}
// base-matching: just use globstar for that.
if (options.matchBase && -1 === pattern.indexOf("/")) {
if (options.noglobstar) {
throw new Error("base matching requires globstar")
}
pattern = "**/" + pattern
}
self.silent = !!options.silent
self.pattern = pattern
self.strict = options.strict !== false
self.realpath = !!options.realpath
self.realpathCache = options.realpathCache || Object.create(null)
self.follow = !!options.follow
self.dot = !!options.dot
self.mark = !!options.mark
self.nodir = !!options.nodir
if (self.nodir)
self.mark = true
self.sync = !!options.sync
self.nounique = !!options.nounique
self.nonull = !!options.nonull
self.nosort = !!options.nosort
self.nocase = !!options.nocase
self.stat = !!options.stat
self.noprocess = !!options.noprocess
self.absolute = !!options.absolute
self.fs = options.fs || fs
self.maxLength = options.maxLength || Infinity
self.cache = options.cache || Object.create(null)
self.statCache = options.statCache || Object.create(null)
self.symlinks = options.symlinks || Object.create(null)
setupIgnores(self, options)
self.changedCwd = false
var cwd = process.cwd()
if (!ownProp(options, "cwd"))
self.cwd = cwd
else {
self.cwd = path.resolve(options.cwd)
self.changedCwd = self.cwd !== cwd
}
self.root = options.root || path.resolve(self.cwd, "/")
self.root = path.resolve(self.root)
if (process.platform === "win32")
self.root = self.root.replace(/\\/g, "/")
// TODO: is an absolute `cwd` supposed to be resolved against `root`?
// e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
if (process.platform === "win32")
self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
self.nomount = !!options.nomount
// disable comments and negation in Minimatch.
// Note that they are not supported in Glob itself anyway.
options.nonegate = true
options.nocomment = true
// always treat \ in patterns as escapes, not path separators
options.allowWindowsEscape = false
self.minimatch = new Minimatch(pattern, options)
self.options = self.minimatch.options
}
function finish (self) {
var nou = self.nounique
var all = nou ? [] : Object.create(null)
for (var i = 0, l = self.matches.length; i < l; i ++) {
var matches = self.matches[i]
if (!matches || Object.keys(matches).length === 0) {
if (self.nonull) {
// do like the shell, and spit out the literal glob
var literal = self.minimatch.globSet[i]
if (nou)
all.push(literal)
else
all[literal] = true
}
} else {
// had matches
var m = Object.keys(matches)
if (nou)
all.push.apply(all, m)
else
m.forEach(function (m) {
all[m] = true
})
}
}
if (!nou)
all = Object.keys(all)
if (!self.nosort)
all = all.sort(alphasort)
// at *some* point we statted all of these
if (self.mark) {
for (var i = 0; i < all.length; i++) {
all[i] = self._mark(all[i])
}
if (self.nodir) {
all = all.filter(function (e) {
var notDir = !(/\/$/.test(e))
var c = self.cache[e] || self.cache[makeAbs(self, e)]
if (notDir && c)
notDir = c !== 'DIR' && !Array.isArray(c)
return notDir
})
}
}
if (self.ignore.length)
all = all.filter(function(m) {
return !isIgnored(self, m)
})
self.found = all
}
function mark (self, p) {
var abs = makeAbs(self, p)
var c = self.cache[abs]
var m = p
if (c) {
var isDir = c === 'DIR' || Array.isArray(c)
var slash = p.slice(-1) === '/'
if (isDir && !slash)
m += '/'
else if (!isDir && slash)
m = m.slice(0, -1)
if (m !== p) {
var mabs = makeAbs(self, m)
self.statCache[mabs] = self.statCache[abs]
self.cache[mabs] = self.cache[abs]
}
}
return m
}
// lotta situps...
function makeAbs (self, f) {
var abs = f
if (f.charAt(0) === '/') {
abs = path.join(self.root, f)
} else if (isAbsolute(f) || f === '') {
abs = f
} else if (self.changedCwd) {
abs = path.resolve(self.cwd, f)
} else {
abs = path.resolve(f)
}
if (process.platform === 'win32')
abs = abs.replace(/\\/g, '/')
return abs
}
// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
function isIgnored (self, path) {
if (!self.ignore.length)
return false
return self.ignore.some(function(item) {
return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
})
}
function childrenIgnored (self, path) {
if (!self.ignore.length)
return false
return self.ignore.some(function(item) {
return !!(item.gmatcher && item.gmatcher.match(path))
})
}
+790
View File
@@ -0,0 +1,790 @@
// Approach:
//
// 1. Get the minimatch set
// 2. For each pattern in the set, PROCESS(pattern, false)
// 3. Store matches per-set, then uniq them
//
// PROCESS(pattern, inGlobStar)
// Get the first [n] items from pattern that are all strings
// Join these together. This is PREFIX.
// If there is no more remaining, then stat(PREFIX) and
// add to matches if it succeeds. END.
//
// If inGlobStar and PREFIX is symlink and points to dir
// set ENTRIES = []
// else readdir(PREFIX) as ENTRIES
// If fail, END
//
// with ENTRIES
// If pattern[n] is GLOBSTAR
// // handle the case where the globstar match is empty
// // by pruning it out, and testing the resulting pattern
// PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
// // handle other cases.
// for ENTRY in ENTRIES (not dotfiles)
// // attach globstar + tail onto the entry
// // Mark that this entry is a globstar match
// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
//
// else // not globstar
// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
// Test ENTRY against pattern[n]
// If fails, continue
// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
//
// Caveat:
// Cache all stats and readdirs results to minimize syscall. Since all
// we ever care about is existence and directory-ness, we can just keep
// `true` for files, and [children,...] for directories, or `false` for
// things that don't exist.
module.exports = glob
var rp = require('fs.realpath')
var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var inherits = require('inherits')
var EE = require('events').EventEmitter
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var globSync = require('./sync.js')
var common = require('./common.js')
var setopts = common.setopts
var ownProp = common.ownProp
var inflight = require('inflight')
var util = require('util')
var childrenIgnored = common.childrenIgnored
var isIgnored = common.isIgnored
var once = require('once')
function glob (pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {}
if (!options) options = {}
if (options.sync) {
if (cb)
throw new TypeError('callback provided to sync glob')
return globSync(pattern, options)
}
return new Glob(pattern, options, cb)
}
glob.sync = globSync
var GlobSync = glob.GlobSync = globSync.GlobSync
// old api surface
glob.glob = glob
function extend (origin, add) {
if (add === null || typeof add !== 'object') {
return origin
}
var keys = Object.keys(add)
var i = keys.length
while (i--) {
origin[keys[i]] = add[keys[i]]
}
return origin
}
glob.hasMagic = function (pattern, options_) {
var options = extend({}, options_)
options.noprocess = true
var g = new Glob(pattern, options)
var set = g.minimatch.set
if (!pattern)
return false
if (set.length > 1)
return true
for (var j = 0; j < set[0].length; j++) {
if (typeof set[0][j] !== 'string')
return true
}
return false
}
glob.Glob = Glob
inherits(Glob, EE)
function Glob (pattern, options, cb) {
if (typeof options === 'function') {
cb = options
options = null
}
if (options && options.sync) {
if (cb)
throw new TypeError('callback provided to sync glob')
return new GlobSync(pattern, options)
}
if (!(this instanceof Glob))
return new Glob(pattern, options, cb)
setopts(this, pattern, options)
this._didRealPath = false
// process each pattern in the minimatch set
var n = this.minimatch.set.length
// The matches are stored as {<filename>: true,...} so that
// duplicates are automagically pruned.
// Later, we do an Object.keys() on these.
// Keep them as a list so we can fill in when nonull is set.
this.matches = new Array(n)
if (typeof cb === 'function') {
cb = once(cb)
this.on('error', cb)
this.on('end', function (matches) {
cb(null, matches)
})
}
var self = this
this._processing = 0
this._emitQueue = []
this._processQueue = []
this.paused = false
if (this.noprocess)
return this
if (n === 0)
return done()
var sync = true
for (var i = 0; i < n; i ++) {
this._process(this.minimatch.set[i], i, false, done)
}
sync = false
function done () {
--self._processing
if (self._processing <= 0) {
if (sync) {
process.nextTick(function () {
self._finish()
})
} else {
self._finish()
}
}
}
}
Glob.prototype._finish = function () {
assert(this instanceof Glob)
if (this.aborted)
return
if (this.realpath && !this._didRealpath)
return this._realpath()
common.finish(this)
this.emit('end', this.found)
}
Glob.prototype._realpath = function () {
if (this._didRealpath)
return
this._didRealpath = true
var n = this.matches.length
if (n === 0)
return this._finish()
var self = this
for (var i = 0; i < this.matches.length; i++)
this._realpathSet(i, next)
function next () {
if (--n === 0)
self._finish()
}
}
Glob.prototype._realpathSet = function (index, cb) {
var matchset = this.matches[index]
if (!matchset)
return cb()
var found = Object.keys(matchset)
var self = this
var n = found.length
if (n === 0)
return cb()
var set = this.matches[index] = Object.create(null)
found.forEach(function (p, i) {
// If there's a problem with the stat, then it means that
// one or more of the links in the realpath couldn't be
// resolved. just return the abs value in that case.
p = self._makeAbs(p)
rp.realpath(p, self.realpathCache, function (er, real) {
if (!er)
set[real] = true
else if (er.syscall === 'stat')
set[p] = true
else
self.emit('error', er) // srsly wtf right here
if (--n === 0) {
self.matches[index] = set
cb()
}
})
})
}
Glob.prototype._mark = function (p) {
return common.mark(this, p)
}
Glob.prototype._makeAbs = function (f) {
return common.makeAbs(this, f)
}
Glob.prototype.abort = function () {
this.aborted = true
this.emit('abort')
}
Glob.prototype.pause = function () {
if (!this.paused) {
this.paused = true
this.emit('pause')
}
}
Glob.prototype.resume = function () {
if (this.paused) {
this.emit('resume')
this.paused = false
if (this._emitQueue.length) {
var eq = this._emitQueue.slice(0)
this._emitQueue.length = 0
for (var i = 0; i < eq.length; i ++) {
var e = eq[i]
this._emitMatch(e[0], e[1])
}
}
if (this._processQueue.length) {
var pq = this._processQueue.slice(0)
this._processQueue.length = 0
for (var i = 0; i < pq.length; i ++) {
var p = pq[i]
this._processing--
this._process(p[0], p[1], p[2], p[3])
}
}
}
}
Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
assert(this instanceof Glob)
assert(typeof cb === 'function')
if (this.aborted)
return
this._processing++
if (this.paused) {
this._processQueue.push([pattern, index, inGlobStar, cb])
return
}
//console.error('PROCESS %d', this._processing, pattern)
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === 'string') {
n ++
}
// now n is the index of the first one that is *not* a string.
// see if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
this._processSimple(pattern.join('/'), index, cb)
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's 'absolute' like /foo/bar,
// or 'relative' like '../baz'
prefix = pattern.slice(0, n).join('/')
break
}
var remain = pattern.slice(n)
// get the list of entries.
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) ||
isAbsolute(pattern.map(function (p) {
return typeof p === 'string' ? p : '[*]'
}).join('/'))) {
if (!prefix || !isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
read = prefix
var abs = this._makeAbs(read)
//if ignored, skip _processing
if (childrenIgnored(this, read))
return cb()
var isGlobStar = remain[0] === minimatch.GLOBSTAR
if (isGlobStar)
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
else
this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
}
Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
var self = this
this._readdir(abs, inGlobStar, function (er, entries) {
return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
})
}
Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
// if the abs isn't a dir, then nothing can match!
if (!entries)
return cb()
// It will only match dot entries if it starts with a dot, or if
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
var pn = remain[0]
var negate = !!this.minimatch.negate
var rawGlob = pn._glob
var dotOk = this.dot || rawGlob.charAt(0) === '.'
var matchedEntries = []
for (var i = 0; i < entries.length; i++) {
var e = entries[i]
if (e.charAt(0) !== '.' || dotOk) {
var m
if (negate && !prefix) {
m = !e.match(pn)
} else {
m = e.match(pn)
}
if (m)
matchedEntries.push(e)
}
}
//console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
var len = matchedEntries.length
// If there are no matched entries, then nothing matches.
if (len === 0)
return cb()
// if this is the last remaining pattern bit, then no need for
// an additional stat *unless* the user has specified mark or
// stat explicitly. We know they exist, since readdir returned
// them.
if (remain.length === 1 && !this.mark && !this.stat) {
if (!this.matches[index])
this.matches[index] = Object.create(null)
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
if (prefix) {
if (prefix !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
if (e.charAt(0) === '/' && !this.nomount) {
e = path.join(this.root, e)
}
this._emitMatch(index, e)
}
// This was the last one, and no stats were needed
return cb()
}
// now test all matched entries as stand-ins for that part
// of the pattern.
remain.shift()
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
var newPattern
if (prefix) {
if (prefix !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
this._process([e].concat(remain), index, inGlobStar, cb)
}
cb()
}
Glob.prototype._emitMatch = function (index, e) {
if (this.aborted)
return
if (isIgnored(this, e))
return
if (this.paused) {
this._emitQueue.push([index, e])
return
}
var abs = isAbsolute(e) ? e : this._makeAbs(e)
if (this.mark)
e = this._mark(e)
if (this.absolute)
e = abs
if (this.matches[index][e])
return
if (this.nodir) {
var c = this.cache[abs]
if (c === 'DIR' || Array.isArray(c))
return
}
this.matches[index][e] = true
var st = this.statCache[abs]
if (st)
this.emit('stat', e, st)
this.emit('match', e)
}
Glob.prototype._readdirInGlobStar = function (abs, cb) {
if (this.aborted)
return
// follow all symlinked directories forever
// just proceed as if this is a non-globstar situation
if (this.follow)
return this._readdir(abs, false, cb)
var lstatkey = 'lstat\0' + abs
var self = this
var lstatcb = inflight(lstatkey, lstatcb_)
if (lstatcb)
self.fs.lstat(abs, lstatcb)
function lstatcb_ (er, lstat) {
if (er && er.code === 'ENOENT')
return cb()
var isSym = lstat && lstat.isSymbolicLink()
self.symlinks[abs] = isSym
// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && lstat && !lstat.isDirectory()) {
self.cache[abs] = 'FILE'
cb()
} else
self._readdir(abs, false, cb)
}
}
Glob.prototype._readdir = function (abs, inGlobStar, cb) {
if (this.aborted)
return
cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
if (!cb)
return
//console.error('RD %j %j', +inGlobStar, abs)
if (inGlobStar && !ownProp(this.symlinks, abs))
return this._readdirInGlobStar(abs, cb)
if (ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (!c || c === 'FILE')
return cb()
if (Array.isArray(c))
return cb(null, c)
}
var self = this
self.fs.readdir(abs, readdirCb(this, abs, cb))
}
function readdirCb (self, abs, cb) {
return function (er, entries) {
if (er)
self._readdirError(abs, er, cb)
else
self._readdirEntries(abs, entries, cb)
}
}
Glob.prototype._readdirEntries = function (abs, entries, cb) {
if (this.aborted)
return
// if we haven't asked to stat everything, then just
// assume that everything in there exists, so we can avoid
// having to stat it a second time.
if (!this.mark && !this.stat) {
for (var i = 0; i < entries.length; i ++) {
var e = entries[i]
if (abs === '/')
e = abs + e
else
e = abs + '/' + e
this.cache[e] = true
}
}
this.cache[abs] = entries
return cb(null, entries)
}
Glob.prototype._readdirError = function (f, er, cb) {
if (this.aborted)
return
// handle errors, and cache the information
switch (er.code) {
case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
case 'ENOTDIR': // totally normal. means it *does* exist.
var abs = this._makeAbs(f)
this.cache[abs] = 'FILE'
if (abs === this.cwdAbs) {
var error = new Error(er.code + ' invalid cwd ' + this.cwd)
error.path = this.cwd
error.code = er.code
this.emit('error', error)
this.abort()
}
break
case 'ENOENT': // not terribly unusual
case 'ELOOP':
case 'ENAMETOOLONG':
case 'UNKNOWN':
this.cache[this._makeAbs(f)] = false
break
default: // some unusual error. Treat as failure.
this.cache[this._makeAbs(f)] = false
if (this.strict) {
this.emit('error', er)
// If the error is handled, then we abort
// if not, we threw out of here
this.abort()
}
if (!this.silent)
console.error('glob error', er)
break
}
return cb()
}
Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
var self = this
this._readdir(abs, inGlobStar, function (er, entries) {
self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
})
}
Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
//console.error('pgs2', prefix, remain[0], entries)
// no entries means not a dir, so it can never have matches
// foo.txt/** doesn't match foo.txt
if (!entries)
return cb()
// test without the globstar, and with every child both below
// and replacing the globstar.
var remainWithoutGlobStar = remain.slice(1)
var gspref = prefix ? [ prefix ] : []
var noGlobStar = gspref.concat(remainWithoutGlobStar)
// the noGlobStar pattern exits the inGlobStar state
this._process(noGlobStar, index, false, cb)
var isSym = this.symlinks[abs]
var len = entries.length
// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
return cb()
for (var i = 0; i < len; i++) {
var e = entries[i]
if (e.charAt(0) === '.' && !this.dot)
continue
// these two cases enter the inGlobStar state
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
this._process(instead, index, true, cb)
var below = gspref.concat(entries[i], remain)
this._process(below, index, true, cb)
}
cb()
}
Glob.prototype._processSimple = function (prefix, index, cb) {
// XXX review this. Shouldn't it be doing the mounting etc
// before doing stat? kinda weird?
var self = this
this._stat(prefix, function (er, exists) {
self._processSimple2(prefix, index, er, exists, cb)
})
}
Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
//console.error('ps2', prefix, exists)
if (!this.matches[index])
this.matches[index] = Object.create(null)
// If it doesn't exist, then just mark the lack of results
if (!exists)
return cb()
if (prefix && isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}
if (process.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')
// Mark this as a match
this._emitMatch(index, prefix)
cb()
}
// Returns either 'DIR', 'FILE', or false
Glob.prototype._stat = function (f, cb) {
var abs = this._makeAbs(f)
var needDir = f.slice(-1) === '/'
if (f.length > this.maxLength)
return cb()
if (!this.stat && ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (Array.isArray(c))
c = 'DIR'
// It exists, but maybe not how we need it
if (!needDir || c === 'DIR')
return cb(null, c)
if (needDir && c === 'FILE')
return cb()
// otherwise we have to stat, because maybe c=true
// if we know it exists, but not what it is.
}
var exists
var stat = this.statCache[abs]
if (stat !== undefined) {
if (stat === false)
return cb(null, stat)
else {
var type = stat.isDirectory() ? 'DIR' : 'FILE'
if (needDir && type === 'FILE')
return cb()
else
return cb(null, type, stat)
}
}
var self = this
var statcb = inflight('stat\0' + abs, lstatcb_)
if (statcb)
self.fs.lstat(abs, statcb)
function lstatcb_ (er, lstat) {
if (lstat && lstat.isSymbolicLink()) {
// If it's a symlink, then treat it as the target, unless
// the target does not exist, then treat it as a file.
return self.fs.stat(abs, function (er, stat) {
if (er)
self._stat2(f, abs, null, lstat, cb)
else
self._stat2(f, abs, er, stat, cb)
})
} else {
self._stat2(f, abs, er, lstat, cb)
}
}
}
Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
this.statCache[abs] = false
return cb()
}
var needDir = f.slice(-1) === '/'
this.statCache[abs] = stat
if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
return cb(null, false, stat)
var c = true
if (stat)
c = stat.isDirectory() ? 'DIR' : 'FILE'
this.cache[abs] = this.cache[abs] || c
if (needDir && c === 'FILE')
return cb()
return cb(null, c, stat)
}
+55
View File
@@ -0,0 +1,55 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"name": "glob",
"description": "a little globber",
"version": "7.2.3",
"publishConfig": {
"tag": "v7-legacy"
},
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-glob.git"
},
"main": "glob.js",
"files": [
"glob.js",
"sync.js",
"common.js"
],
"engines": {
"node": "*"
},
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"devDependencies": {
"memfs": "^3.2.0",
"mkdirp": "0",
"rimraf": "^2.2.8",
"tap": "^15.0.6",
"tick": "0.0.6"
},
"tap": {
"before": "test/00-setup.js",
"after": "test/zz-cleanup.js",
"jobs": 1
},
"scripts": {
"prepublish": "npm run benchclean",
"profclean": "rm -f v8.log profile.txt",
"test": "tap",
"test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js",
"bench": "bash benchmark.sh",
"prof": "bash prof.sh && cat profile.txt",
"benchclean": "node benchclean.js"
},
"license": "ISC",
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
}
+486
View File
@@ -0,0 +1,486 @@
module.exports = globSync
globSync.GlobSync = GlobSync
var rp = require('fs.realpath')
var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var Glob = require('./glob.js').Glob
var util = require('util')
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var common = require('./common.js')
var setopts = common.setopts
var ownProp = common.ownProp
var childrenIgnored = common.childrenIgnored
var isIgnored = common.isIgnored
function globSync (pattern, options) {
if (typeof options === 'function' || arguments.length === 3)
throw new TypeError('callback provided to sync glob\n'+
'See: https://github.com/isaacs/node-glob/issues/167')
return new GlobSync(pattern, options).found
}
function GlobSync (pattern, options) {
if (!pattern)
throw new Error('must provide pattern')
if (typeof options === 'function' || arguments.length === 3)
throw new TypeError('callback provided to sync glob\n'+
'See: https://github.com/isaacs/node-glob/issues/167')
if (!(this instanceof GlobSync))
return new GlobSync(pattern, options)
setopts(this, pattern, options)
if (this.noprocess)
return this
var n = this.minimatch.set.length
this.matches = new Array(n)
for (var i = 0; i < n; i ++) {
this._process(this.minimatch.set[i], i, false)
}
this._finish()
}
GlobSync.prototype._finish = function () {
assert.ok(this instanceof GlobSync)
if (this.realpath) {
var self = this
this.matches.forEach(function (matchset, index) {
var set = self.matches[index] = Object.create(null)
for (var p in matchset) {
try {
p = self._makeAbs(p)
var real = rp.realpathSync(p, self.realpathCache)
set[real] = true
} catch (er) {
if (er.syscall === 'stat')
set[self._makeAbs(p)] = true
else
throw er
}
}
})
}
common.finish(this)
}
GlobSync.prototype._process = function (pattern, index, inGlobStar) {
assert.ok(this instanceof GlobSync)
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === 'string') {
n ++
}
// now n is the index of the first one that is *not* a string.
// See if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
this._processSimple(pattern.join('/'), index)
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's 'absolute' like /foo/bar,
// or 'relative' like '../baz'
prefix = pattern.slice(0, n).join('/')
break
}
var remain = pattern.slice(n)
// get the list of entries.
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) ||
isAbsolute(pattern.map(function (p) {
return typeof p === 'string' ? p : '[*]'
}).join('/'))) {
if (!prefix || !isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
read = prefix
var abs = this._makeAbs(read)
//if ignored, skip processing
if (childrenIgnored(this, read))
return
var isGlobStar = remain[0] === minimatch.GLOBSTAR
if (isGlobStar)
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
else
this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
}
GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
var entries = this._readdir(abs, inGlobStar)
// if the abs isn't a dir, then nothing can match!
if (!entries)
return
// It will only match dot entries if it starts with a dot, or if
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
var pn = remain[0]
var negate = !!this.minimatch.negate
var rawGlob = pn._glob
var dotOk = this.dot || rawGlob.charAt(0) === '.'
var matchedEntries = []
for (var i = 0; i < entries.length; i++) {
var e = entries[i]
if (e.charAt(0) !== '.' || dotOk) {
var m
if (negate && !prefix) {
m = !e.match(pn)
} else {
m = e.match(pn)
}
if (m)
matchedEntries.push(e)
}
}
var len = matchedEntries.length
// If there are no matched entries, then nothing matches.
if (len === 0)
return
// if this is the last remaining pattern bit, then no need for
// an additional stat *unless* the user has specified mark or
// stat explicitly. We know they exist, since readdir returned
// them.
if (remain.length === 1 && !this.mark && !this.stat) {
if (!this.matches[index])
this.matches[index] = Object.create(null)
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
if (prefix) {
if (prefix.slice(-1) !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
if (e.charAt(0) === '/' && !this.nomount) {
e = path.join(this.root, e)
}
this._emitMatch(index, e)
}
// This was the last one, and no stats were needed
return
}
// now test all matched entries as stand-ins for that part
// of the pattern.
remain.shift()
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
var newPattern
if (prefix)
newPattern = [prefix, e]
else
newPattern = [e]
this._process(newPattern.concat(remain), index, inGlobStar)
}
}
GlobSync.prototype._emitMatch = function (index, e) {
if (isIgnored(this, e))
return
var abs = this._makeAbs(e)
if (this.mark)
e = this._mark(e)
if (this.absolute) {
e = abs
}
if (this.matches[index][e])
return
if (this.nodir) {
var c = this.cache[abs]
if (c === 'DIR' || Array.isArray(c))
return
}
this.matches[index][e] = true
if (this.stat)
this._stat(e)
}
GlobSync.prototype._readdirInGlobStar = function (abs) {
// follow all symlinked directories forever
// just proceed as if this is a non-globstar situation
if (this.follow)
return this._readdir(abs, false)
var entries
var lstat
var stat
try {
lstat = this.fs.lstatSync(abs)
} catch (er) {
if (er.code === 'ENOENT') {
// lstat failed, doesn't exist
return null
}
}
var isSym = lstat && lstat.isSymbolicLink()
this.symlinks[abs] = isSym
// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && lstat && !lstat.isDirectory())
this.cache[abs] = 'FILE'
else
entries = this._readdir(abs, false)
return entries
}
GlobSync.prototype._readdir = function (abs, inGlobStar) {
var entries
if (inGlobStar && !ownProp(this.symlinks, abs))
return this._readdirInGlobStar(abs)
if (ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (!c || c === 'FILE')
return null
if (Array.isArray(c))
return c
}
try {
return this._readdirEntries(abs, this.fs.readdirSync(abs))
} catch (er) {
this._readdirError(abs, er)
return null
}
}
GlobSync.prototype._readdirEntries = function (abs, entries) {
// if we haven't asked to stat everything, then just
// assume that everything in there exists, so we can avoid
// having to stat it a second time.
if (!this.mark && !this.stat) {
for (var i = 0; i < entries.length; i ++) {
var e = entries[i]
if (abs === '/')
e = abs + e
else
e = abs + '/' + e
this.cache[e] = true
}
}
this.cache[abs] = entries
// mark and cache dir-ness
return entries
}
GlobSync.prototype._readdirError = function (f, er) {
// handle errors, and cache the information
switch (er.code) {
case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
case 'ENOTDIR': // totally normal. means it *does* exist.
var abs = this._makeAbs(f)
this.cache[abs] = 'FILE'
if (abs === this.cwdAbs) {
var error = new Error(er.code + ' invalid cwd ' + this.cwd)
error.path = this.cwd
error.code = er.code
throw error
}
break
case 'ENOENT': // not terribly unusual
case 'ELOOP':
case 'ENAMETOOLONG':
case 'UNKNOWN':
this.cache[this._makeAbs(f)] = false
break
default: // some unusual error. Treat as failure.
this.cache[this._makeAbs(f)] = false
if (this.strict)
throw er
if (!this.silent)
console.error('glob error', er)
break
}
}
GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
var entries = this._readdir(abs, inGlobStar)
// no entries means not a dir, so it can never have matches
// foo.txt/** doesn't match foo.txt
if (!entries)
return
// test without the globstar, and with every child both below
// and replacing the globstar.
var remainWithoutGlobStar = remain.slice(1)
var gspref = prefix ? [ prefix ] : []
var noGlobStar = gspref.concat(remainWithoutGlobStar)
// the noGlobStar pattern exits the inGlobStar state
this._process(noGlobStar, index, false)
var len = entries.length
var isSym = this.symlinks[abs]
// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
return
for (var i = 0; i < len; i++) {
var e = entries[i]
if (e.charAt(0) === '.' && !this.dot)
continue
// these two cases enter the inGlobStar state
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
this._process(instead, index, true)
var below = gspref.concat(entries[i], remain)
this._process(below, index, true)
}
}
GlobSync.prototype._processSimple = function (prefix, index) {
// XXX review this. Shouldn't it be doing the mounting etc
// before doing stat? kinda weird?
var exists = this._stat(prefix)
if (!this.matches[index])
this.matches[index] = Object.create(null)
// If it doesn't exist, then just mark the lack of results
if (!exists)
return
if (prefix && isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}
if (process.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')
// Mark this as a match
this._emitMatch(index, prefix)
}
// Returns either 'DIR', 'FILE', or false
GlobSync.prototype._stat = function (f) {
var abs = this._makeAbs(f)
var needDir = f.slice(-1) === '/'
if (f.length > this.maxLength)
return false
if (!this.stat && ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (Array.isArray(c))
c = 'DIR'
// It exists, but maybe not how we need it
if (!needDir || c === 'DIR')
return c
if (needDir && c === 'FILE')
return false
// otherwise we have to stat, because maybe c=true
// if we know it exists, but not what it is.
}
var exists
var stat = this.statCache[abs]
if (!stat) {
var lstat
try {
lstat = this.fs.lstatSync(abs)
} catch (er) {
if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
this.statCache[abs] = false
return false
}
}
if (lstat && lstat.isSymbolicLink()) {
try {
stat = this.fs.statSync(abs)
} catch (er) {
stat = lstat
}
} else {
stat = lstat
}
}
this.statCache[abs] = stat
var c = true
if (stat)
c = stat.isDirectory() ? 'DIR' : 'FILE'
this.cache[abs] = this.cache[abs] || c
if (needDir && c === 'FILE')
return false
return c
}
GlobSync.prototype._mark = function (p) {
return common.mark(this, p)
}
GlobSync.prototype._makeAbs = function (f) {
return common.makeAbs(this, f)
}
+15
View File
@@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+230
View File
@@ -0,0 +1,230 @@
# minimatch
A minimal matching utility.
[![Build Status](https://travis-ci.org/isaacs/minimatch.svg?branch=master)](http://travis-ci.org/isaacs/minimatch)
This is the matching library used internally by npm.
It works by converting glob expressions into JavaScript `RegExp`
objects.
## Usage
```javascript
var minimatch = require("minimatch")
minimatch("bar.foo", "*.foo") // true!
minimatch("bar.foo", "*.bar") // false!
minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
```
## Features
Supports these glob features:
* Brace Expansion
* Extended glob matching
* "Globstar" `**` matching
See:
* `man sh`
* `man bash`
* `man 3 fnmatch`
* `man 5 gitignore`
## Minimatch Class
Create a minimatch object by instantiating the `minimatch.Minimatch` class.
```javascript
var Minimatch = require("minimatch").Minimatch
var mm = new Minimatch(pattern, options)
```
### Properties
* `pattern` The original pattern the minimatch object represents.
* `options` The options supplied to the constructor.
* `set` A 2-dimensional array of regexp or string expressions.
Each row in the
array corresponds to a brace-expanded pattern. Each item in the row
corresponds to a single path-part. For example, the pattern
`{a,b/c}/d` would expand to a set of patterns like:
[ [ a, d ]
, [ b, c, d ] ]
If a portion of the pattern doesn't have any "magic" in it
(that is, it's something like `"foo"` rather than `fo*o?`), then it
will be left as a string rather than converted to a regular
expression.
* `regexp` Created by the `makeRe` method. A single regular expression
expressing the entire pattern. This is useful in cases where you wish
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
* `negate` True if the pattern is negated.
* `comment` True if the pattern is a comment.
* `empty` True if the pattern is `""`.
### Methods
* `makeRe` Generate the `regexp` member if necessary, and return it.
Will return `false` if the pattern is invalid.
* `match(fname)` Return true if the filename matches the pattern, or
false otherwise.
* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
filename, and match it against a single row in the `regExpSet`. This
method is mainly for internal use, but is exposed so that it can be
used by a glob-walker that needs to avoid excessive filesystem calls.
All other methods are internal, and will be called as necessary.
### minimatch(path, pattern, options)
Main export. Tests a path against the pattern using the options.
```javascript
var isJS = minimatch(file, "*.js", { matchBase: true })
```
### minimatch.filter(pattern, options)
Returns a function that tests its
supplied argument, suitable for use with `Array.filter`. Example:
```javascript
var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
```
### minimatch.match(list, pattern, options)
Match against the list of
files, in the style of fnmatch or glob. If nothing is matched, and
options.nonull is set, then return a list containing the pattern itself.
```javascript
var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
```
### minimatch.makeRe(pattern, options)
Make a regular expression object from the pattern.
## Options
All options are `false` by default.
### debug
Dump a ton of stuff to stderr.
### nobrace
Do not expand `{a,b}` and `{1..3}` brace sets.
### noglobstar
Disable `**` matching against multiple folder names.
### dot
Allow patterns to match filenames starting with a period, even if
the pattern does not explicitly have a period in that spot.
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
is set.
### noext
Disable "extglob" style patterns like `+(a|b)`.
### nocase
Perform a case-insensitive match.
### nonull
When a match is not found by `minimatch.match`, return a list containing
the pattern itself if this option is set. When not set, an empty list
is returned if there are no matches.
### matchBase
If set, then patterns without slashes will be matched
against the basename of the path if it contains slashes. For example,
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
### nocomment
Suppress the behavior of treating `#` at the start of a pattern as a
comment.
### nonegate
Suppress the behavior of treating a leading `!` character as negation.
### flipNegate
Returns from negate expressions the same as if they were not negated.
(Ie, true on a hit, false on a miss.)
### partial
Compare a partial path to a pattern. As long as the parts of the path that
are present are not contradicted by the pattern, it will be treated as a
match. This is useful in applications where you're walking through a
folder structure, and don't yet have the full path, but want to ensure that
you do not walk down paths that can never be a match.
For example,
```js
minimatch('/a/b', '/a/*/c/d', { partial: true }) // true, might be /a/b/c/d
minimatch('/a/b', '/**/d', { partial: true }) // true, might be /a/b/.../d
minimatch('/x/y/z', '/a/**/z', { partial: true }) // false, because x !== a
```
### allowWindowsEscape
Windows path separator `\` is by default converted to `/`, which
prohibits the usage of `\` as a escape character. This flag skips that
behavior and allows using the escape character.
## Comparisons to other fnmatch/glob implementations
While strict compliance with the existing standards is a worthwhile
goal, some discrepancies exist between minimatch and other
implementations, and are intentional.
If the pattern starts with a `!` character, then it is negated. Set the
`nonegate` flag to suppress this behavior, and treat leading `!`
characters normally. This is perhaps relevant if you wish to start the
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
characters at the start of a pattern will negate the pattern multiple
times.
If a pattern starts with `#`, then it is treated as a comment, and
will not match anything. Use `\#` to match a literal `#` at the
start of a line, or set the `nocomment` flag to suppress this behavior.
The double-star character `**` is supported by default, unless the
`noglobstar` flag is set. This is supported in the manner of bsdglob
and bash 4.1, where `**` only has special significance if it is the only
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
`a/**b` will not.
If an escaped pattern has no matches, and the `nonull` flag is set,
then minimatch.match returns the pattern as-provided, rather than
interpreting the character escapes. For example,
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
that it does not resolve escaped pattern characters.
If brace expansion is not disabled, then it is performed before any
other interpretation of the glob pattern. Thus, a pattern like
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
checked for validity. Since those two are valid, matching proceeds.
+947
View File
@@ -0,0 +1,947 @@
module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = (function () { try { return require('path') } catch (e) {}}()) || {
sep: '/'
}
minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = require('brace-expansion')
var plTypes = {
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
'?': { open: '(?:', close: ')?' },
'+': { open: '(?:', close: ')+' },
'*': { open: '(?:', close: ')*' },
'@': { open: '(?:', close: ')' }
}
// any single thing other than /
// don't need to escape / when using new RegExp()
var qmark = '[^/]'
// * => any number of characters
var star = qmark + '*?'
// ** when dots are allowed. Anything goes, except .. and .
// not (^ or / followed by one or two dots followed by $ or /),
// followed by anything, any number of times.
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
// not a ^ or / followed by a dot,
// followed by anything, any number of times.
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
// characters that need to be escaped in RegExp.
var reSpecials = charSet('().*{}+?[]^$\\!')
// "abc" -> { a:true, b:true, c:true }
function charSet (s) {
return s.split('').reduce(function (set, c) {
set[c] = true
return set
}, {})
}
// normalizes slashes.
var slashSplit = /\/+/
minimatch.filter = filter
function filter (pattern, options) {
options = options || {}
return function (p, i, list) {
return minimatch(p, pattern, options)
}
}
function ext (a, b) {
b = b || {}
var t = {}
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
return minimatch
}
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
m.Minimatch.defaults = function defaults (options) {
return orig.defaults(ext(def, options)).Minimatch
}
m.filter = function filter (pattern, options) {
return orig.filter(pattern, ext(def, options))
}
m.defaults = function defaults (options) {
return orig.defaults(ext(def, options))
}
m.makeRe = function makeRe (pattern, options) {
return orig.makeRe(pattern, ext(def, options))
}
m.braceExpand = function braceExpand (pattern, options) {
return orig.braceExpand(pattern, ext(def, options))
}
m.match = function (list, pattern, options) {
return orig.match(list, pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
assertValidPattern(pattern)
if (!options) options = {}
// shortcut: comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
return false
}
return new Minimatch(pattern, options).match(p)
}
function Minimatch (pattern, options) {
if (!(this instanceof Minimatch)) {
return new Minimatch(pattern, options)
}
assertValidPattern(pattern)
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
this.options = options
this.set = []
this.pattern = pattern
this.regexp = null
this.negate = false
this.comment = false
this.empty = false
this.partial = !!options.partial
// make the set of regexps etc.
this.make()
}
Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
var pattern = this.pattern
var options = this.options
// empty patterns and comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
this.comment = true
return
}
if (!pattern) {
this.empty = true
return
}
// step 1: figure out negation, etc.
this.parseNegate()
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
this.debug(this.pattern, set)
// step 3: now we have a set, so turn each one into a series of path-portion
// matching patterns.
// These will be regexps, except in the case of "**", which is
// set to the GLOBSTAR object for globstar behavior,
// and will not contain any / characters
set = this.globParts = set.map(function (s) {
return s.split(slashSplit)
})
this.debug(this.pattern, set)
// glob --> regexps
set = set.map(function (s, si, set) {
return s.map(this.parse, this)
}, this)
this.debug(this.pattern, set)
// filter out everything that didn't compile properly.
set = set.filter(function (s) {
return s.indexOf(false) === -1
})
this.debug(this.pattern, set)
this.set = set
}
Minimatch.prototype.parseNegate = parseNegate
function parseNegate () {
var pattern = this.pattern
var negate = false
var options = this.options
var negateOffset = 0
if (options.nonegate) return
for (var i = 0, l = pattern.length
; i < l && pattern.charAt(i) === '!'
; i++) {
negate = !negate
negateOffset++
}
if (negateOffset) this.pattern = pattern.substr(negateOffset)
this.negate = negate
}
// Brace expansion:
// a{b,c}d -> abd acd
// a{b,}c -> abc ac
// a{0..3}d -> a0d a1d a2d a3d
// a{b,c{d,e}f}g -> abg acdfg acefg
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
//
// Invalid sets are not expanded.
// a{2..}b -> a{2..}b
// a{b}c -> a{b}c
minimatch.braceExpand = function (pattern, options) {
return braceExpand(pattern, options)
}
Minimatch.prototype.braceExpand = braceExpand
function braceExpand (pattern, options) {
if (!options) {
if (this instanceof Minimatch) {
options = this.options
} else {
options = {}
}
}
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
assertValidPattern(pattern)
// Thanks to Yeting Li <https://github.com/yetingli> for
// improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand.
return [pattern]
}
return expand(pattern)
}
var MAX_PATTERN_LENGTH = 1024 * 64
var assertValidPattern = function (pattern) {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern')
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long')
}
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
// pattern, split on '/', and then turned into a regular expression.
// A regexp is made at the end which joins each array with an
// escaped /, and another full one which joins each regexp with |.
//
// Following the lead of Bash 4.1, note that "**" only has special meaning
// when it is the *only* thing in a path portion. Otherwise, any series
// of * is equivalent to a single *. Globstar behavior is enabled by
// default, and can be disabled by setting options.noglobstar.
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
assertValidPattern(pattern)
var options = this.options
// shortcuts
if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return ''
var re = ''
var hasMagic = !!options.nocase
var escaping = false
// ? => one single character
var patternListStack = []
var negativeLists = []
var stateChar
var inClass = false
var reClassStart = -1
var classStart = -1
// . and .. never match anything that doesn't start with .,
// even when options.dot is set.
var patternStart = pattern.charAt(0) === '.' ? '' // anything
// not (start or / followed by . or .. followed by / or end)
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
: '(?!\\.)'
var self = this
function clearStateChar () {
if (stateChar) {
// we had some state-tracking character
// that wasn't consumed by this pass.
switch (stateChar) {
case '*':
re += star
hasMagic = true
break
case '?':
re += qmark
hasMagic = true
break
default:
re += '\\' + stateChar
break
}
self.debug('clearStateChar %j %j', stateChar, re)
stateChar = false
}
}
for (var i = 0, len = pattern.length, c
; (i < len) && (c = pattern.charAt(i))
; i++) {
this.debug('%s\t%s %s %j', pattern, i, re, c)
// skip over any that are escaped.
if (escaping && reSpecials[c]) {
re += '\\' + c
escaping = false
continue
}
switch (c) {
/* istanbul ignore next */
case '/': {
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
}
case '\\':
clearStateChar()
escaping = true
continue
// the various stateChar values
// for the "extglob" stuff.
case '?':
case '*':
case '+':
case '@':
case '!':
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
// all of those are literals inside a class, except that
// the glob [!a] means [^a] in regexp
if (inClass) {
this.debug(' in class')
if (c === '!' && i === classStart + 1) c = '^'
re += c
continue
}
// if we already have a stateChar, then it means
// that there was something like ** or +? in there.
// Handle the stateChar, then proceed with this one.
self.debug('call clearStateChar %j', stateChar)
clearStateChar()
stateChar = c
// if extglob is disabled, then +(asdf|foo) isn't a thing.
// just clear the statechar *now*, rather than even diving into
// the patternList stuff.
if (options.noext) clearStateChar()
continue
case '(':
if (inClass) {
re += '('
continue
}
if (!stateChar) {
re += '\\('
continue
}
patternListStack.push({
type: stateChar,
start: i - 1,
reStart: re.length,
open: plTypes[stateChar].open,
close: plTypes[stateChar].close
})
// negation is (?:(?!js)[^/]*)
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
this.debug('plType %j %j', stateChar, re)
stateChar = false
continue
case ')':
if (inClass || !patternListStack.length) {
re += '\\)'
continue
}
clearStateChar()
hasMagic = true
var pl = patternListStack.pop()
// negation is (?:(?!js)[^/]*)
// The others are (?:<pattern>)<type>
re += pl.close
if (pl.type === '!') {
negativeLists.push(pl)
}
pl.reEnd = re.length
continue
case '|':
if (inClass || !patternListStack.length || escaping) {
re += '\\|'
escaping = false
continue
}
clearStateChar()
re += '|'
continue
// these are mostly the same in regexp and glob
case '[':
// swallow any state-tracking char before the [
clearStateChar()
if (inClass) {
re += '\\' + c
continue
}
inClass = true
classStart = i
reClassStart = re.length
re += c
continue
case ']':
// a right bracket shall lose its special
// meaning and represent itself in
// a bracket expression if it occurs
// first in the list. -- POSIX.2 2.8.3.2
if (i === classStart + 1 || !inClass) {
re += '\\' + c
escaping = false
continue
}
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// finish up the class.
hasMagic = true
inClass = false
re += c
continue
default:
// swallow any state char that wasn't consumed
clearStateChar()
if (escaping) {
// no need
escaping = false
} else if (reSpecials[c]
&& !(c === '^' && inClass)) {
re += '\\'
}
re += c
} // switch
} // for
// handle the case where we left a class open.
// "[abc" is valid, equivalent to "\[abc"
if (inClass) {
// split where the last [ was, and escape it
// this is a huge pita. We now have to re-walk
// the contents of the would-be class to re-translate
// any characters that were passed through as-is
cs = pattern.substr(classStart + 1)
sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0]
hasMagic = hasMagic || sp[1]
}
// handle the case where we had a +( thing at the *end*
// of the pattern.
// each pattern list stack adds 3 chars, and we need to go through
// and escape any | chars that were passed through as-is for the regexp.
// Go through and escape them, taking care not to double-escape any
// | chars that were already escaped.
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
var tail = re.slice(pl.reStart + pl.open.length)
this.debug('setting tail', re, pl)
// maybe some even number of \, then maybe 1 \, followed by a |
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
if (!$2) {
// the | isn't already escaped, so escape it.
$2 = '\\'
}
// need to escape all those slashes *again*, without escaping the
// one that we need for escaping the | character. As it works out,
// escaping an even number of slashes can be done by simply repeating
// it exactly after itself. That's why this trick works.
//
// I am sorry that you have to see this.
return $1 + $1 + $2 + '|'
})
this.debug('tail=%j\n %s', tail, tail, pl, re)
var t = pl.type === '*' ? star
: pl.type === '?' ? qmark
: '\\' + pl.type
hasMagic = true
re = re.slice(0, pl.reStart) + t + '\\(' + tail
}
// handle trailing things that only matter at the very end.
clearStateChar()
if (escaping) {
// trailing \\
re += '\\\\'
}
// only need to apply the nodot start if the re starts with
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '[': case '.': case '(': addPatternStart = true
}
// Hack to work around lack of negative lookbehind in JS
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
// like 'a.xyz.yz' doesn't match. So, the first negative
// lookahead, has to look ALL the way ahead, to the end of
// the pattern.
for (var n = negativeLists.length - 1; n > -1; n--) {
var nl = negativeLists[n]
var nlBefore = re.slice(0, nl.reStart)
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
var nlAfter = re.slice(nl.reEnd)
nlLast += nlAfter
// Handle nested stuff like *(*.js|!(*.json)), where open parens
// mean that we should *not* include the ) in the bit that is considered
// "after" the negated section.
var openParensBefore = nlBefore.split('(').length - 1
var cleanAfter = nlAfter
for (i = 0; i < openParensBefore; i++) {
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
}
nlAfter = cleanAfter
var dollar = ''
if (nlAfter === '' && isSub !== SUBPARSE) {
dollar = '$'
}
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
re = newRe
}
// if the re is not "" at this point, then we need to make sure
// it doesn't match against an empty path part.
// Otherwise a/* will match a/, which it should not.
if (re !== '' && hasMagic) {
re = '(?=.)' + re
}
if (addPatternStart) {
re = patternStart + re
}
// parsing just a piece of a larger pattern.
if (isSub === SUBPARSE) {
return [re, hasMagic]
}
// skip the regexp for non-magical patterns
// unescape anything in it, though, so that it'll be
// an exact match against a file etc.
if (!hasMagic) {
return globUnescape(pattern)
}
var flags = options.nocase ? 'i' : ''
try {
var regExp = new RegExp('^' + re + '$', flags)
} catch (er) /* istanbul ignore next - should be impossible */ {
// If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line
// mode, but it's not a /m regex.
return new RegExp('$.')
}
regExp._glob = pattern
regExp._src = re
return regExp
}
minimatch.makeRe = function (pattern, options) {
return new Minimatch(pattern, options || {}).makeRe()
}
Minimatch.prototype.makeRe = makeRe
function makeRe () {
if (this.regexp || this.regexp === false) return this.regexp
// at this point, this.set is a 2d array of partial
// pattern strings, or "**".
//
// It's better to use .match(). This function shouldn't
// be used, really, but it's pretty convenient sometimes,
// when you just want to work with a regex.
var set = this.set
if (!set.length) {
this.regexp = false
return this.regexp
}
var options = this.options
var twoStar = options.noglobstar ? star
: options.dot ? twoStarDot
: twoStarNoDot
var flags = options.nocase ? 'i' : ''
var re = set.map(function (pattern) {
return pattern.map(function (p) {
return (p === GLOBSTAR) ? twoStar
: (typeof p === 'string') ? regExpEscape(p)
: p._src
}).join('\\\/')
}).join('|')
// must match entire pattern
// ending in a * or ** will make it less strict.
re = '^(?:' + re + ')$'
// can match anything, as long as it's not this.
if (this.negate) re = '^(?!' + re + ').*$'
try {
this.regexp = new RegExp(re, flags)
} catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false
}
return this.regexp
}
minimatch.match = function (list, pattern, options) {
options = options || {}
var mm = new Minimatch(pattern, options)
list = list.filter(function (f) {
return mm.match(f)
})
if (mm.options.nonull && !list.length) {
list.push(pattern)
}
return list
}
Minimatch.prototype.match = function match (f, partial) {
if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
if (this.comment) return false
if (this.empty) return f === ''
if (f === '/' && partial) return true
var options = this.options
// windows: need to use /, not \
if (path.sep !== '/') {
f = f.split(path.sep).join('/')
}
// treat the test path as a set of pathparts.
f = f.split(slashSplit)
this.debug(this.pattern, 'split', f)
// just ONE of the pattern sets in this.set needs to match
// in order for it to be valid. If negating, then just one
// match means that we have failed.
// Either way, return on the first hit.
var set = this.set
this.debug(this.pattern, 'set', set)
// Find the basename of the path by looking for the last non-empty segment
var filename
var i
for (i = f.length - 1; i >= 0; i--) {
filename = f[i]
if (filename) break
}
for (i = 0; i < set.length; i++) {
var pattern = set[i]
var file = f
if (options.matchBase && pattern.length === 1) {
file = [filename]
}
var hit = this.matchOne(file, pattern, partial)
if (hit) {
if (options.flipNegate) return true
return !this.negate
}
}
// didn't get any hits. this is success if it's a negative
// pattern, failure otherwise.
if (options.flipNegate) return false
return this.negate
}
// set partial to true to test if, for example,
// "/a/b" matches the start of "/*/b/*/d"
// Partial means, if you run out of file before you run
// out of pattern, then that's fine, as long as all
// the parts match.
Minimatch.prototype.matchOne = function (file, pattern, partial) {
var options = this.options
this.debug('matchOne',
{ 'this': this, file: file, pattern: pattern })
this.debug('matchOne', file.length, pattern.length)
for (var fi = 0,
pi = 0,
fl = file.length,
pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++) {
this.debug('matchOne loop')
var p = pattern[pi]
var f = file[fi]
this.debug(pattern, p, f)
// should be impossible.
// some invalid regexp stuff in the set.
/* istanbul ignore if */
if (p === false) return false
if (p === GLOBSTAR) {
this.debug('GLOBSTAR', [pattern, p, f])
// "**"
// a/**/b/**/c would match the following:
// a/b/x/y/z/c
// a/x/y/z/b/c
// a/b/x/b/x/c
// a/b/c
// To do this, take the rest of the pattern after
// the **, and see if it would match the file remainder.
// If so, return success.
// If not, the ** "swallows" a segment, and try again.
// This is recursively awful.
//
// a/**/b/**/c matching a/b/x/y/z/c
// - a matches a
// - doublestar
// - matchOne(b/x/y/z/c, b/**/c)
// - b matches b
// - doublestar
// - matchOne(x/y/z/c, c) -> no
// - matchOne(y/z/c, c) -> no
// - matchOne(z/c, c) -> no
// - matchOne(c, c) yes, hit
var fr = fi
var pr = pi + 1
if (pr === pl) {
this.debug('** at the end')
// a ** at the end will just swallow the rest.
// We have found a match.
// however, it will not swallow /.x, unless
// options.dot is set.
// . and .. are *never* matched by **, for explosively
// exponential reasons.
for (; fi < fl; fi++) {
if (file[fi] === '.' || file[fi] === '..' ||
(!options.dot && file[fi].charAt(0) === '.')) return false
}
return true
}
// ok, let's see if we can swallow whatever we can.
while (fr < fl) {
var swallowee = file[fr]
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
// XXX remove this slice. Just pass the start index.
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
this.debug('globstar found match!', fr, fl, swallowee)
// found a match.
return true
} else {
// can't swallow "." or ".." ever.
// can only swallow ".foo" when explicitly asked.
if (swallowee === '.' || swallowee === '..' ||
(!options.dot && swallowee.charAt(0) === '.')) {
this.debug('dot detected!', file, fr, pattern, pr)
break
}
// ** swallows a segment, and continue.
this.debug('globstar swallow a segment, and continue')
fr++
}
}
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
/* istanbul ignore if */
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
if (fr === fl) return true
}
return false
}
// something other than **
// non-magic patterns just have to match exactly
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
hit = f === p
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
this.debug('pattern match', p, f, hit)
}
if (!hit) return false
}
// Note: ending in / means that we'll get a final ""
// at the end of the pattern. This can only match a
// corresponding "" at the end of the file.
// If the file ends in /, then it can only match a
// a pattern that ends in /, unless the pattern just
// doesn't have any more for it. But, a/b/ should *not*
// match "a/b/*", even though "" matches against the
// [^/]*? pattern, except in partial mode, where it might
// simply not be reached yet.
// However, a/b/ should still satisfy a/*
// now either we fell off the end of the pattern, or we're done.
if (fi === fl && pi === pl) {
// ran out of pattern and filename at the same time.
// an exact hit!
return true
} else if (fi === fl) {
// ran out of file, but still had pattern left.
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
return (fi === fl - 1) && (file[fi] === '')
}
// should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?')
}
// replace stuff like \* with *
function globUnescape (s) {
return s.replace(/\\(.)/g, '$1')
}
function regExpEscape (s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
+33
View File
@@ -0,0 +1,33 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
"name": "minimatch",
"description": "a glob matcher in javascript",
"version": "3.1.2",
"publishConfig": {
"tag": "v3-legacy"
},
"repository": {
"type": "git",
"url": "git://github.com/isaacs/minimatch.git"
},
"main": "minimatch.js",
"scripts": {
"test": "tap",
"preversion": "npm test",
"postversion": "npm publish",
"postpublish": "git push origin --all; git push origin --tags"
},
"engines": {
"node": "*"
},
"dependencies": {
"brace-expansion": "^1.1.7"
},
"devDependencies": {
"tap": "^15.1.6"
},
"license": "ISC",
"files": [
"minimatch.js"
]
}
+99
View File
@@ -0,0 +1,99 @@
{
"name": "browserify",
"version": "17.0.0",
"description": "browser-side require() the node way",
"main": "index.js",
"bin": {
"browserify": "bin/cmd.js"
},
"repository": {
"type": "git",
"url": "http://github.com/browserify/browserify.git"
},
"engines": {
"node": ">= 0.8"
},
"keywords": [
"browser",
"require",
"commonjs",
"commonj-esque",
"bundle",
"npm",
"javascript"
],
"dependencies": {
"JSONStream": "^1.0.3",
"assert": "^1.4.0",
"browser-pack": "^6.0.1",
"browser-resolve": "^2.0.0",
"browserify-zlib": "~0.2.0",
"buffer": "~5.2.1",
"cached-path-relative": "^1.0.0",
"concat-stream": "^1.6.0",
"console-browserify": "^1.1.0",
"constants-browserify": "~1.0.0",
"crypto-browserify": "^3.0.0",
"defined": "^1.0.0",
"deps-sort": "^2.0.1",
"domain-browser": "^1.2.0",
"duplexer2": "~0.1.2",
"events": "^3.0.0",
"glob": "^7.1.0",
"has": "^1.0.0",
"htmlescape": "^1.1.0",
"https-browserify": "^1.0.0",
"inherits": "~2.0.1",
"insert-module-globals": "^7.2.1",
"labeled-stream-splicer": "^2.0.0",
"mkdirp-classic": "^0.5.2",
"module-deps": "^6.2.3",
"os-browserify": "~0.3.0",
"parents": "^1.0.1",
"path-browserify": "^1.0.0",
"process": "~0.11.0",
"punycode": "^1.3.2",
"querystring-es3": "~0.2.0",
"read-only-stream": "^2.0.0",
"readable-stream": "^2.0.2",
"resolve": "^1.1.4",
"shasum-object": "^1.0.0",
"shell-quote": "^1.6.1",
"stream-browserify": "^3.0.0",
"stream-http": "^3.0.0",
"string_decoder": "^1.1.1",
"subarg": "^1.0.0",
"syntax-error": "^1.1.1",
"through2": "^2.0.0",
"timers-browserify": "^1.0.1",
"tty-browserify": "0.0.1",
"url": "~0.11.0",
"util": "~0.12.0",
"vm-browserify": "^1.0.0",
"xtend": "^4.0.0"
},
"devDependencies": {
"backbone": "~0.9.2",
"browser-unpack": "^1.1.1",
"coffee-script": "~1.10.0",
"coffeeify": "~1.1.0",
"has-object-spread": "^1.0.0",
"has-template-literals": "^1.0.0",
"isstream": "^0.1.2",
"make-generator-function": "^1.1.0",
"semver": "^5.5.0",
"seq": "0.3.5",
"tap": "^10.7.2",
"temp": "=0.8.3",
"through": "^2.3.4"
},
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"scripts": {
"test": "tap test/*.js"
},
"license": "MIT"
}
+831
View File
@@ -0,0 +1,831 @@
# browserify
`require('modules')` in the browser
Use a [node](http://nodejs.org)-style `require()` to organize your browser code
and load modules installed by [npm](https://www.npmjs.com).
browserify will recursively analyze all the `require()` calls in your app in
order to build a bundle you can serve up to the browser in a single `<script>`
tag.
[![build status](https://img.shields.io/travis/browserify/browserify/master.svg)](https://travis-ci.org/browserify/browserify)
![browserify!](./assets/logo.png)
# getting started
If you're new to browserify, check out the
[browserify handbook](https://github.com/browserify/browserify-handbook)
and the resources on [browserify.org](http://browserify.org/).
# example
Whip up a file, `main.js` with some `require()`s in it. You can use relative
paths like `'./foo.js'` and `'../lib/bar.js'` or module paths like `'gamma'`
that will search `node_modules/` using
[node's module lookup algorithm](https://github.com/browserify/resolve).
``` js
var foo = require('./foo.js');
var bar = require('../lib/bar.js');
var gamma = require('gamma');
var elem = document.getElementById('result');
var x = foo(100) + bar('baz');
elem.textContent = gamma(x);
```
Export functionality by assigning onto `module.exports` or `exports`:
``` js
module.exports = function (n) { return n * 111 }
```
Now just use the `browserify` command to build a bundle starting at `main.js`:
```
$ browserify main.js > bundle.js
```
All of the modules that `main.js` needs are included in the `bundle.js` from a
recursive walk of the `require()` graph using
[required](https://github.com/defunctzombie/node-required).
To use this bundle, just toss a `<script src="bundle.js"></script>` into your
html!
# install
With [npm](https://www.npmjs.com/) do:
```
npm install -g browserify
```
# usage
```
Usage: browserify [entry files] {OPTIONS}
Standard Options:
--outfile, -o Write the browserify bundle to this file.
If unspecified, browserify prints to stdout.
--require, -r A module name or file to bundle.require()
Optionally use a colon separator to set the target.
--entry, -e An entry point of your app
--ignore, -i Replace a file with an empty stub. Files can be globs.
--exclude, -u Omit a file from the output bundle. Files can be globs.
--external, -x Reference a file from another bundle. Files can be globs.
--transform, -t Use a transform module on top-level files.
--command, -c Use a transform command on top-level files.
--standalone -s Generate a UMD bundle for the supplied export name.
This bundle works with other module systems and sets the name
given as a window global if no module system is found.
--debug -d Enable source maps that allow you to debug your files
separately.
--help, -h Show this message
For advanced options, type `browserify --help advanced`.
Specify a parameter.
```
```
Advanced Options:
--insert-globals, --ig, --fast [default: false]
Skip detection and always insert definitions for process, global,
__filename, and __dirname.
benefit: faster builds
cost: extra bytes
--insert-global-vars, --igv
Comma-separated list of global variables to detect and define.
Default: __filename,__dirname,process,Buffer,global
--detect-globals, --dg [default: true]
Detect the presence of process, global, __filename, and __dirname and define
these values when present.
benefit: npm modules more likely to work
cost: slower builds
--ignore-missing, --im [default: false]
Ignore `require()` statements that don't resolve to anything.
--noparse=FILE
Don't parse FILE at all. This will make bundling much, much faster for giant
libs like jquery or threejs.
--no-builtins
Turn off builtins. This is handy when you want to run a bundle in node which
provides the core builtins.
--no-commondir
Turn off setting a commondir. This is useful if you want to preserve the
original paths that a bundle was generated with.
--no-bundle-external
Turn off bundling of all external modules. This is useful if you only want
to bundle your local files.
--bare
Alias for both --no-builtins, --no-commondir, and sets --insert-global-vars
to just "__filename,__dirname". This is handy if you want to run bundles in
node.
--no-browser-field, --no-bf
Turn off package.json browser field resolution. This is also handy if you
need to run a bundle in node.
--transform-key
Instead of the default package.json#browserify#transform field to list
all transforms to apply when running browserify, a custom field, like, e.g.
package.json#browserify#production or package.json#browserify#staging
can be used, by for example running:
* `browserify index.js --transform-key=production > bundle.js`
* `browserify index.js --transform-key=staging > bundle.js`
--node
Alias for --bare and --no-browser-field.
--full-paths
Turn off converting module ids into numerical indexes. This is useful for
preserving the original paths that a bundle was generated with.
--deps
Instead of standard bundle output, print the dependency array generated by
module-deps.
--no-dedupe
Turn off deduping.
--list
Print each file in the dependency graph. Useful for makefiles.
--extension=EXTENSION
Consider files with specified EXTENSION as modules, this option can used
multiple times.
--global-transform=MODULE, -g MODULE
Use a transform module on all files after any ordinary transforms have run.
--ignore-transform=MODULE, -it MODULE
Do not run certain transformations, even if specified elsewhere.
--plugin=MODULE, -p MODULE
Register MODULE as a plugin.
Passing arguments to transforms and plugins:
For -t, -g, and -p, you may use subarg syntax to pass options to the
transforms or plugin function as the second parameter. For example:
-t [ foo -x 3 --beep ]
will call the `foo` transform for each applicable file by calling:
foo(file, { x: 3, beep: true })
```
# compatibility
Many [npm](https://www.npmjs.com/) modules that don't do IO will just work after being
browserified. Others take more work.
Many node built-in modules have been wrapped to work in the browser, but only
when you explicitly `require()` or use their functionality.
When you `require()` any of these modules, you will get a browser-specific shim:
* [assert](https://www.npmjs.com/package/assert)
* [buffer](https://www.npmjs.com/package/buffer)
* [console](https://www.npmjs.com/package/console-browserify)
* [constants](https://www.npmjs.com/package/constants-browserify)
* [crypto](https://www.npmjs.com/package/crypto-browserify)
* [domain](https://www.npmjs.com/package/domain-browser)
* [events](https://www.npmjs.com/package/events)
* [http](https://www.npmjs.com/package/stream-http)
* [https](https://www.npmjs.com/package/https-browserify)
* [os](https://www.npmjs.com/package/os-browserify)
* [path](https://www.npmjs.com/package/path-browserify)
* [punycode](https://www.npmjs.com/package/punycode)
* [querystring](https://www.npmjs.com/package/querystring-es3)
* [stream](https://www.npmjs.com/package/stream-browserify)
* [string_decoder](https://www.npmjs.com/package/string_decoder)
* [timers](https://www.npmjs.com/package/timers-browserify)
* [tty](https://www.npmjs.com/package/tty-browserify)
* [url](https://www.npmjs.com/package/url)
* [util](https://www.npmjs.com/package/util)
* [vm](https://www.npmjs.com/package/vm-browserify)
* [zlib](https://www.npmjs.com/package/browserify-zlib)
Additionally, if you use any of these variables, they
[will be defined](https://github.com/browserify/insert-module-globals)
in the bundled output in a browser-appropriate way:
* [process](https://www.npmjs.com/package/process)
* [Buffer](https://www.npmjs.com/package/buffer)
* global - top-level scope object (window)
* __filename - file path of the currently executing file
* __dirname - directory path of the currently executing file
# more examples
## external requires
You can just as easily create a bundle that will export a `require()` function so
you can `require()` modules from another script tag. Here we'll create a
`bundle.js` with the [through](https://www.npmjs.com/package/through)
and [duplexer](https://www.npmjs.com/package/duplexer) modules.
```
$ browserify -r through -r duplexer -r ./my-file.js:my-module > bundle.js
```
Then in your page you can do:
``` html
<script src="bundle.js"></script>
<script>
var through = require('through');
var duplexer = require('duplexer');
var myModule = require('my-module');
/* ... */
</script>
```
## external source maps
If you prefer the source maps be saved to a separate `.js.map` source map file, you may use
[exorcist](https://github.com/thlorenz/exorcist) in order to achieve that. It's as simple as:
```
$ browserify main.js --debug | exorcist bundle.js.map > bundle.js
```
Learn about additional options [here](https://github.com/thlorenz/exorcist#usage).
## multiple bundles
If browserify finds a `require`d function already defined in the page scope, it
will fall back to that function if it didn't find any matches in its own set of
bundled modules.
In this way, you can use browserify to split up bundles among multiple pages to
get the benefit of caching for shared, infrequently-changing modules, while
still being able to use `require()`. Just use a combination of `--external` and
`--require` to factor out common dependencies.
For example, if a website with 2 pages, `beep.js`:
``` js
var robot = require('./robot.js');
console.log(robot('beep'));
```
and `boop.js`:
``` js
var robot = require('./robot.js');
console.log(robot('boop'));
```
both depend on `robot.js`:
``` js
module.exports = function (s) { return s.toUpperCase() + '!' };
```
```
$ browserify -r ./robot.js > static/common.js
$ browserify -x ./robot.js beep.js > static/beep.js
$ browserify -x ./robot.js boop.js > static/boop.js
```
Then on the beep page you can have:
``` html
<script src="common.js"></script>
<script src="beep.js"></script>
```
while the boop page can have:
``` html
<script src="common.js"></script>
<script src="boop.js"></script>
```
This approach using `-r` and `-x` works fine for a small number of split assets,
but there are plugins for automatically factoring out components which are
described in the
[partitioning section of the browserify handbook](https://github.com/browserify/browserify-handbook#partitioning).
## api example
You can use the API directly too:
``` js
var browserify = require('browserify');
var b = browserify();
b.add('./browser/main.js');
b.bundle().pipe(process.stdout);
```
# methods
``` js
var browserify = require('browserify')
```
## `browserify([files] [, opts])`
Returns a new browserify instance.
<dl>
<dt>
files
</dt>
<dd>
String, file object, or array of those types (they may be mixed) specifying entry file(s).
</dd>
<dt>
opts
</dt>
<dd>
Object.
</dd>
</dl>
`files` and `opts` are both optional, but must be in the order shown if both are
passed.
Entry files may be passed in `files` and / or `opts.entries`.
External requires may be specified in `opts.require`, accepting the same formats
that the `files` argument does.
If an entry file is a stream, its contents will be used. You should pass
`opts.basedir` when using streaming files so that relative requires can be
resolved.
`opts.entries` has the same definition as `files`.
`opts.noParse` is an array which will skip all require() and global parsing for
each file in the array. Use this for giant libs like jquery or threejs that
don't have any requires or node-style globals but take forever to parse.
`opts.transform` is an array of transform functions or modules names which will
transform the source code before the parsing.
`opts.ignoreTransform` is an array of transformations that will not be run,
even if specified elsewhere.
`opts.plugin` is an array of plugin functions or module names to use. See the
plugins section below for details.
`opts.extensions` is an array of optional extra extensions for the module lookup
machinery to use when the extension has not been specified.
By default browserify considers only `.js` and `.json` files in such cases.
`opts.basedir` is the directory that browserify starts bundling from for
filenames that start with `.`.
`opts.paths` is an array of directories that browserify searches when looking
for modules which are not referenced using relative path. Can be absolute or
relative to `basedir`. Equivalent of setting `NODE_PATH` environmental variable
when calling `browserify` command.
`opts.commondir` sets the algorithm used to parse out the common paths. Use
`false` to turn this off, otherwise it uses the
[commondir](https://www.npmjs.com/package/commondir) module.
`opts.fullPaths` disables converting module ids into numerical indexes. This is
useful for preserving the original paths that a bundle was generated with.
`opts.builtins` sets the list of built-ins to use, which by default is set in
`lib/builtins.js` in this distribution.
`opts.bundleExternal` boolean option to set if external modules should be
bundled. Defaults to true.
When `opts.browserField` is false, the package.json browser field will be
ignored. When `opts.browserField` is set to a `string`, then a custom field name
can be used instead of the default `"browser"` field.
When `opts.insertGlobals` is true, always insert `process`, `global`,
`__filename`, and `__dirname` without analyzing the AST for faster builds but
larger output bundles. Default false.
When `opts.detectGlobals` is true, scan all files for `process`, `global`,
`__filename`, and `__dirname`, defining as necessary. With this option npm
modules are more likely to work but bundling takes longer. Default true.
When `opts.ignoreMissing` is true, ignore `require()` statements that don't
resolve to anything.
When `opts.debug` is true, add a source map inline to the end of the bundle.
This makes debugging easier because you can see all the original files if
you are in a modern enough browser.
When `opts.standalone` is a non-empty string, a standalone module is created
with that name and a [umd](https://github.com/forbeslindesay/umd) wrapper.
You can use namespaces in the standalone global export using a `.` in the string
name as a separator, for example `'A.B.C'`. The global export will be [sanitized
and camel cased](https://github.com/ForbesLindesay/umd#name-casing-and-characters).
Note that in standalone mode the `require()` calls from the original source will
still be around, which may trip up AMD loaders scanning for `require()` calls.
You can remove these calls with
[derequire](https://www.npmjs.com/package/derequire):
```
$ npm install -g derequire
$ browserify main.js --standalone Foo | derequire > bundle.js
```
`opts.insertGlobalVars` will be passed to
[insert-module-globals](https://www.npmjs.com/package/insert-module-globals)
as the `opts.vars` parameter.
`opts.externalRequireName` defaults to `'require'` in `expose` mode but you can
use another name.
`opts.bare` creates a bundle that does not include Node builtins, and does not
replace global Node variables except for `__dirname` and `__filename`.
`opts.node` creates a bundle that runs in Node and does not use the browser
versions of dependencies. Same as passing `{ bare: true, browserField: false }`.
Note that if files do not contain javascript source code then you also need to
specify a corresponding transform for them.
All other options are forwarded along to
[module-deps](https://www.npmjs.com/package/module-deps)
and [browser-pack](https://www.npmjs.com/package/browser-pack) directly.
## b.add(file, opts)
Add an entry file from `file` that will be executed when the bundle loads.
If `file` is an array, each item in `file` will be added as an entry file.
## b.require(file, opts)
Make `file` available from outside the bundle with `require(file)`.
The `file` param is anything that can be resolved by `require.resolve()`,
including files from `node_modules`. Like with `require.resolve()`, you must
prefix `file` with `./` to require a local file (not in `node_modules`).
`file` can also be a stream, but you should also use `opts.basedir` so that
relative requires will be resolvable.
If `file` is an array, each item in `file` will be required.
In `file` array form, you can use a string or object for each item. Object items
should have a `file` property and the rest of the parameters will be used for
the `opts`.
Use the `expose` property of opts to specify a custom dependency name.
`require('./vendor/angular/angular.js', {expose: 'angular'})` enables `require('angular')`
## b.bundle(cb)
Bundle the files and their dependencies into a single javascript file.
Return a readable stream with the javascript file contents or
optionally specify a `cb(err, buf)` to get the buffered results.
## b.external(file)
Prevent `file` from being loaded into the current bundle, instead referencing
from another bundle.
If `file` is an array, each item in `file` will be externalized.
If `file` is another bundle, that bundle's contents will be read and excluded
from the current bundle as the bundle in `file` gets bundled.
## b.ignore(file)
Prevent the module name or file at `file` from showing up in the output bundle.
If `file` is an array, each item in `file` will be ignored.
Instead you will get a file with `module.exports = {}`.
## b.exclude(file)
Prevent the module name or file at `file` from showing up in the output bundle.
If `file` is an array, each item in `file` will be excluded.
If your code tries to `require()` that file it will throw unless you've provided
another mechanism for loading it.
## b.transform(tr, opts={})
Transform source code before parsing it for `require()` calls with the transform
function or module name `tr`.
If `tr` is a function, it will be called with `tr(file)` and it should return a
[through-stream](https://github.com/substack/stream-handbook#through)
that takes the raw file contents and produces the transformed source.
If `tr` is a string, it should be a module name or file path of a
[transform module](https://github.com/browserify/module-deps#transforms)
with a signature of:
``` js
var through = require('through');
module.exports = function (file) { return through() };
```
You don't need to necessarily use the
[through](https://www.npmjs.com/package/through) module.
Browserify is compatible with the newer, more verbose
[Transform streams](http://nodejs.org/api/stream.html#stream_class_stream_transform_1)
built into Node v0.10.
Here's how you might compile coffee script on the fly using `.transform()`:
``` js
var coffee = require('coffee-script');
var through = require('through');
b.transform(function (file) {
var data = '';
return through(write, end);
function write (buf) { data += buf }
function end () {
this.queue(coffee.compile(data));
this.queue(null);
}
});
```
Note that on the command-line with the `-c` flag you can just do:
```
$ browserify -c 'coffee -sc' main.coffee > bundle.js
```
Or better still, use the [coffeeify](https://github.com/jnordberg/coffeeify)
module:
```
$ npm install coffeeify
$ browserify -t coffeeify main.coffee > bundle.js
```
If `opts.global` is `true`, the transform will operate on ALL files, despite
whether they exist up a level in a `node_modules/` directory. Use global
transforms cautiously and sparingly, since most of the time an ordinary
transform will suffice. You can also not configure global transforms in a
`package.json` like you can with ordinary transforms.
Global transforms always run after any ordinary transforms have run.
Transforms may obtain options from the command-line with
[subarg](https://www.npmjs.com/package/subarg) syntax:
```
$ browserify -t [ foo --bar=555 ] main.js
```
or from the api:
```
b.transform('foo', { bar: 555 })
```
In both cases, these options are provided as the second argument to the
transform function:
```
module.exports = function (file, opts) { /* opts.bar === 555 */ }
```
Options sent to the browserify constructor are also provided under
`opts._flags`. These browserify options are sometimes required if your transform
needs to do something different when browserify is run in debug mode, for
example.
## b.plugin(plugin, opts)
Register a `plugin` with `opts`. Plugins can be a string module name or a
function the same as transforms.
`plugin(b, opts)` is called with the browserify instance `b`.
For more information, consult the plugins section below.
## b.pipeline
There is an internal
[labeled-stream-splicer](https://www.npmjs.com/package/labeled-stream-splicer)
pipeline with these labels:
* `'record'` - save inputs to play back later on subsequent `bundle()` calls
* `'deps'` - [module-deps](https://www.npmjs.com/package/module-deps)
* `'json'` - adds `module.exports=` to the beginning of json files
* `'unbom'` - remove byte-order markers
* `'unshebang'` - remove #! labels on the first line
* `'syntax'` - check for syntax errors
* `'sort'` - sort the dependencies for deterministic bundles
* `'dedupe'` - remove duplicate source contents
* `'label'` - apply integer labels to files
* `'emit-deps'` - emit `'dep'` event
* `'debug'` - apply source maps
* `'pack'` - [browser-pack](https://www.npmjs.com/package/browser-pack)
* `'wrap'` - apply final wrapping, `require=` and a newline and semicolon
You can call `b.pipeline.get()` with a label name to get a handle on a stream pipeline
that you can `push()`, `unshift()`, or `splice()` to insert your own transform
streams.
## b.reset(opts)
Reset the pipeline back to a normal state. This function is called automatically
when `bundle()` is called multiple times.
This function triggers a 'reset' event.
# package.json
browserify uses the `package.json` in its module resolution algorithm, just like
node. If there is a `"main"` field, browserify will start resolving the package
at that point. If there is no `"main"` field, browserify will look for an
`"index.js"` file in the module root directory. Here are some more
sophisticated things you can do in the package.json:
## browser field
There is a special "[browser](https://github.com/defunctzombie/package-browser-field-spec)" field you can
set in your package.json on a per-module basis to override file resolution for
browser-specific versions of files.
For example, if you want to have a browser-specific module entry point for your
`"main"` field you can just set the `"browser"` field to a string:
``` json
"browser": "./browser.js"
```
or you can have overrides on a per-file basis:
``` json
"browser": {
"fs": "level-fs",
"./lib/ops.js": "./browser/opts.js"
}
```
Note that the browser field only applies to files in the local module, and like
transforms, it doesn't apply into `node_modules` directories.
## browserify.transform
You can specify source transforms in the package.json in the
`browserify.transform` field. There is more information about how source
transforms work in package.json on the
[module-deps readme](https://github.com/browserify/module-deps#transforms).
For example, if your module requires [brfs](https://www.npmjs.com/package/brfs), you
can add
``` json
"browserify": { "transform": [ "brfs" ] }
```
to your package.json. Now when somebody `require()`s your module, brfs will
automatically be applied to the files in your module without explicit
intervention by the person using your module. Make sure to add transforms to
your package.json dependencies field.
# events
## b.on('file', function (file, id, parent) {})
## b.pipeline.on('file', function (file, id, parent) {})
When a file is resolved for the bundle, the bundle emits a `'file'` event with
the full `file` path, the `id` string passed to `require()`, and the `parent`
object used by
[browser-resolve](https://github.com/defunctzombie/node-browser-resolve).
You could use the `file` event to implement a file watcher to regenerate bundles
when files change.
## b.on('package', function (pkg) {})
## b.pipeline.on('package', function (pkg) {})
When a package file is read, this event fires with the contents. The package
directory is available at `pkg.__dirname`.
## b.on('bundle', function (bundle) {})
When `.bundle()` is called, this event fires with the `bundle` output stream.
## b.on('reset', function () {})
When the `.reset()` method is called or implicitly called by another call to
`.bundle()`, this event fires.
## b.on('transform', function (tr, file) {})
## b.pipeline.on('transform', function (tr, file) {})
When a transform is applied to a file, the `'transform'` event fires on the
bundle stream with the transform stream `tr` and the `file` that the transform
is being applied to.
# plugins
For some more advanced use-cases, a transform is not sufficiently extensible.
Plugins are modules that take the bundle instance as their first parameter and
an option hash as their second.
Plugins can be used to do perform some fancy features that transforms can't do.
For example, [factor-bundle](https://www.npmjs.com/package/factor-bundle) is a
plugin that can factor out common dependencies from multiple entry-points into a
common bundle. Use plugins with `-p` and pass options to plugins with
[subarg](https://www.npmjs.com/package/subarg) syntax:
```
browserify x.js y.js -p [ factor-bundle -o bundle/x.js -o bundle/y.js ] \
> bundle/common.js
```
For a list of plugins, consult the
[browserify-plugin tag](https://www.npmjs.com/browse/keyword/browserify-plugin)
on npm.
# list of source transforms
There is a [wiki page that lists the known browserify
transforms](https://github.com/browserify/browserify/wiki/list-of-transforms).
If you write a transform, make sure to add your transform to that wiki page and
add a package.json keyword of `browserify-transform` so that
[people can browse for all the browserify
transforms](https://www.npmjs.com/browse/keyword/browserify-transform) on npmjs.org.
# third-party tools
There is a [wiki page that lists the known browserify
tools](https://github.com/browserify/browserify/wiki/browserify-tools).
If you write a tool, make sure to add it to that wiki page and
add a package.json keyword of `browserify-tool` so that
[people can browse for all the browserify
tools](https://www.npmjs.com/browse/keyword/browserify-tool) on npmjs.org.
# changelog
Releases are documented in
[changelog.markdown](changelog.markdown) and on the
[browserify twitter feed](https://twitter.com/browserify).
# license
[MIT](./LICENSE)
![browserify!](./assets/browserify.png)
+10
View File
@@ -0,0 +1,10 @@
# Security Policy
## Supported Versions
Only the latest major version is supported at any given time.
## Reporting a Vulnerability
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
+72
View File
@@ -0,0 +1,72 @@
var test = require('tap').test;
var fromArgs = require('../bin/args.js');
var path = require('path');
var vm = require('vm');
test('bundle from an arguments array', function (t) {
t.plan(2);
var b = fromArgs([ __dirname + '/entry/two.js', '-s', 'XYZ' ]);
b.bundle(function (err, src) {
t.ifError(err);
var c = { window: {} };
vm.runInNewContext(src, c);
t.equal(c.window.XYZ, 2);
});
});
test('external flag for node modules', function(t) {
t.plan(2);
var b = fromArgs([ __dirname + '/external_args/main.js', '-x', 'backbone' ]);
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, {t: t});
});
});
test('bundle from an arguments with --insert-global-vars', function (t) {
t.plan(4);
var b = fromArgs([
__dirname + '/global/filename.js',
'--insert-global-vars=__filename,__dirname',
'--basedir', __dirname
]);
b.require(__dirname + '/global/filename.js', { expose: 'x' });
b.bundle(function (err, src) {
t.ifError(err, 'b.bundle()');
var c = {}, x;
vm.runInNewContext(src, c);
t.doesNotThrow(function() {
x = c.require('x');
}, 'x = c.require(\'x\')');
t.equal(x && x.filename, '/global/filename.js', 'x.filename');
t.equal(x && x.dirname, '/global', 'x.dirname');
})
});
test('numeric module names', function(t) {
t.plan(1);
var b = fromArgs([ '-x', '1337' ]);
b.bundle(function (err, src) {
t.ifError(err);
});
});
test('entry expose', function (t) {
t.plan(3)
var b = fromArgs([
path.join(__dirname, '/entry_expose/main.js'),
'--require', path.join(__dirname, '/entry_expose/main.js') + ':x',
]);
b.bundle(function (err, src) {
t.ifError(err);
var c = { console: { log: log } };
function log (msg) { t.equal(msg, 'wow') }
vm.runInNewContext(src, c);
t.equal(c.require('x'), 555);
})
});
+74
View File
@@ -0,0 +1,74 @@
var browserify = require('../');
var vm = require('vm');
var test = require('tap').test;
test('array add', function (t) {
var expected = [ 'ONE', 'TWO', 'THREE' ];
t.plan(expected.length);
var b = browserify();
var files = [
__dirname + '/array/one.js',
__dirname + '/array/two.js',
__dirname + '/array/three.js'
];
b.add(files);
b.bundle(function (err, src) {
vm.runInNewContext(src, { console: { log: log } });
function log (msg) {
t.equal(msg, expected.shift());
}
});
});
test('array require', function (t) {
t.plan(3);
var b = browserify();
var files = [ 'defined', 'subarg' ];
b.require(files);
b.bundle(function (err, src) {
var c = {};
vm.runInNewContext(src, c);
t.equal(c.require('defined')(undefined, true), true);
t.equal(c.require('defined')(undefined, false), false);
t.deepEqual(c.require('subarg')(['-x', '3']), { x: 3, _: [] });
});
});
test('array require opts', function (t) {
t.plan(3);
var b = browserify();
var files = [
{ file: require.resolve('defined'), expose: 'abc' },
{ file: require.resolve('subarg'), expose: 'def' }
];
b.require(files);
b.bundle(function (err, src) {
var c = {};
vm.runInNewContext(src, c);
t.equal(c.require('abc')(undefined, true), true);
t.equal(c.require('abc')(undefined, false), false);
t.deepEqual(c.require('def')(['-x', '3']), { x: 3, _: [] });
});
});
test('array external', function (t) {
t.plan(2);
var b = browserify(__dirname + '/external/main.js');
b.external(['util','freelist']);
b.bundle(function (err, src) {
if (err) return t.fail(err);
vm.runInNewContext(
'function require (x) {'
+ 'if (x==="freelist") return function (n) { return n + 1000 }'
+ '}'
+ src,
{ t: t }
);
});
});
+1
View File
@@ -0,0 +1 @@
console.log('ONE');
+1
View File
@@ -0,0 +1 @@
console.log('THREE');
+1
View File
@@ -0,0 +1 @@
console.log('TWO');
+24
View File
@@ -0,0 +1,24 @@
var browserify = require('../');
var fs = require('fs');
var vm = require('vm');
var test = require('tap').test;
var src = fs.readFileSync(__dirname + '/async/src.js','utf8');
var canAsync = true;
try { Function(src) } catch (err) { canAsync = false }
if (!canAsync) console.error('# async/await unsupported in this environment')
else test('async/await', function (t) {
t.plan(2);
var b = browserify(__dirname + '/async/src.js');
b.bundle(function (err, src) {
t.error(err)
var c = {
console: { log: log },
setTimeout: setTimeout,
clearTimeout: clearTimeout
}
vm.runInNewContext(src, c);
function log (msg) { t.equal(msg, 60) }
});
});
+8
View File
@@ -0,0 +1,8 @@
function f (x) { return new Promise(resolve => {
process.nextTick(() => { resolve(x) }) }) }
async function add (x) {
return x + await f(20) + await f(30)
}
add(10).then(v => { console.log(v) })
+23
View File
@@ -0,0 +1,23 @@
var browserify = require('../');
var vm = require('vm');
var backbone = require('backbone');
var test = require('tap').test;
test('backbone', function (t) {
t.plan(3);
var b = browserify();
b.require('backbone');
b.bundle(function (err, buf) {
t.ok(Buffer.isBuffer(buf));
var src = buf.toString('utf8');
t.ok(src.length > 0);
var c = { console: console };
vm.runInNewContext(src, c);
t.deepEqual(
Object.keys(backbone).sort(),
Object.keys(c.require('backbone')).sort()
);
t.end();
});
});
+173
View File
@@ -0,0 +1,173 @@
var test = require('tap').test;
var spawn = require('child_process').spawn;
var browserify = require('../');
var path = require('path');
var concat = require('concat-stream');
var vm = require('vm');
var fs = require('fs');
var through = require('through2');
var temp = require('temp');
temp.track();
var tmpdir = temp.mkdirSync({prefix: 'browserify-test'});
test('bare', function (t) {
t.plan(4);
var cwd = process.cwd();
process.chdir(__dirname);
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
'-', '--bare'
]);
ps.stdout.pipe(concat(function (body) {
vm.runInNewContext(body, {
Buffer: function (s) { return s.toLowerCase() },
console: {
log: function (msg) { t.equal(msg, 'abc') }
}
});
vm.runInNewContext(body, {
Buffer: Buffer,
console: {
log: function (msg) {
t.ok(Buffer.isBuffer(msg));
t.equal(msg.toString('utf8'), 'ABC')
}
}
});
}));
ps.stdin.end('console.log(Buffer("ABC"))');
ps.on('exit', function (code) {
t.equal(code, 0);
});
});
test('bare api', function (t) {
t.plan(3);
var input = through();
var b = browserify(input, { bare: true });
b.bundle().pipe(concat(function (body) {
vm.runInNewContext(body, {
Buffer: function (s) { return s.toLowerCase() },
console: {
log: function (msg) { t.equal(msg, 'abc') }
}
});
vm.runInNewContext(body, {
Buffer: Buffer,
console: {
log: function (msg) {
t.ok(Buffer.isBuffer(msg));
t.equal(msg.toString('utf8'), 'ABC')
}
}
});
}));
input.end('console.log(Buffer("ABC"))');
});
test('bare inserts __filename,__dirname but not process,global,Buffer', function (t) {
t.plan(2);
var file = path.resolve(__dirname, 'bare/main.js');
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
file,
'--bare'
]);
ps.stdout.pipe(concat(function (body) {
vm.runInNewContext(body, {
require: require,
__dirname: process.cwd(),
console: {
log: function (msg) {
t.same(msg, [
path.join(__dirname, 'bare'),
path.join(__dirname, 'bare/main.js'),
'undefined',
'undefined',
'undefined'
]);
}
}
});
}));
ps.stdin.end();
ps.on('exit', function (code) {
t.equal(code, 0);
});
});
test('bare inserts dynamic __filename,__dirname', function (t) {
t.plan(2);
var file = path.join(tmpdir, 'dirname-filename.js');
fs.writeFileSync(
file,
fs.readFileSync(path.resolve(__dirname, 'bare/dirname-filename.js'))
);
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
file,
'--bare'
]);
ps.stdout.pipe(concat(function (body) {
vm.runInNewContext(body, {
require: require,
__dirname: process.cwd(),
console: {
log: function (msg) {
t.same(msg, [
path.dirname(file),
file
]);
}
}
});
}));
ps.stdin.end();
ps.on('exit', function (code) {
t.equal(code, 0);
});
});
test('bare inserts dynamic __filename,__dirname with basedir', function (t) {
t.plan(2);
var file = 'dirname-filename.js';
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
file,
'--bare',
'--basedir=' + path.join(__dirname, 'bare')
]);
ps.stdout.pipe(concat(function (body) {
vm.runInNewContext(body, {
require: require,
__dirname: process.cwd(),
console: {
log: function (msg) {
t.same(msg, [
__dirname,
path.join(__dirname, file)
]);
}
}
});
}));
ps.stdin.end();
ps.on('exit', function (code) {
t.equal(code, 0);
});
});
+4
View File
@@ -0,0 +1,4 @@
console.log([
__dirname,
__filename
]);
+7
View File
@@ -0,0 +1,7 @@
console.log([
__dirname,
__filename,
typeof process,
typeof global,
typeof Buffer
]);
+37
View File
@@ -0,0 +1,37 @@
var test = require('tap').test;
var spawn = require('child_process').spawn;
var path = require('path');
var concat = require('concat-stream');
var vm = require('vm');
test('bare shebang', function (t) {
t.plan(4);
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
'-', '--bare'
]);
ps.stderr.pipe(process.stderr);
ps.stdout.pipe(concat(function (body) {
vm.runInNewContext(body, {
Buffer: function (s) { return s.toLowerCase() },
console: {
log: function (msg) { t.equal(msg, 'woo') }
}
});
vm.runInNewContext(body, {
Buffer: Buffer,
console: {
log: function (msg) {
t.ok(Buffer.isBuffer(msg));
t.equal(msg.toString('utf8'), 'WOO')
}
}
});
}));
ps.stdin.end('#!/usr/bin/env node\nconsole.log(Buffer("WOO"))');
ps.on('exit', function (code) {
t.equal(code, 0);
});
});
+31
View File
@@ -0,0 +1,31 @@
var test = require('tap').test;
var spawn = require('child_process').spawn;
var path = require('path');
var vm = require('vm');
test('bin', function (t) {
t.plan(3);
var cwd = process.cwd();
process.chdir(__dirname);
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
'entry/main.js'
]);
var src = '';
var err = '';
ps.stdout.on('data', function (buf) { src += buf });
ps.stderr.on('data', function (buf) { err += buf });
ps.on('exit', function (code) {
t.equal(code, 0);
t.equal(err, '');
var allDone = false;
var c = { done : function () { allDone = true } };
vm.runInNewContext(src, c);
t.ok(allDone);
});
});
+31
View File
@@ -0,0 +1,31 @@
var test = require('tap').test;
var spawn = require('child_process').spawn;
var path = require('path');
var vm = require('vm');
test('bin --entry', function (t) {
t.plan(3);
var cwd = process.cwd();
process.chdir(__dirname);
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
'--entry', 'entry/main.js'
]);
var src = '';
var err = '';
ps.stdout.on('data', function (buf) { src += buf });
ps.stderr.on('data', function (buf) { err += buf });
ps.on('exit', function (code) {
t.equal(code, 0);
t.equal(err, '');
var allDone = false;
var c = { done : function () { allDone = true } };
vm.runInNewContext(src, c);
t.ok(allDone);
});
});
+27
View File
@@ -0,0 +1,27 @@
var browserify = require('../');
var spawn = require('child_process').spawn;
var test = require('tap').test;
var path = require('path')
var semver = require('semver');
// TODO this should be fixable I guess
var flaky = process.platform === 'win32' && semver.satisfies(process.version, 'v0.10.x');
test('function transform', { skip: flaky }, function (t) {
t.plan(3);
var ps = spawn(process.execPath, [
path.resolve(__dirname, '../bin/cmd.js'),
'-t', './tr.js', './main.js'
], {cwd: path.resolve(__dirname, 'bin_tr_error')});
var src = '';
var err = '';
ps.stdout.on('data', function (buf) { src += buf });
ps.stderr.on('data', function (buf) { err += buf });
ps.on('exit', function (code) {
t.notEqual(code, 0);
var errorFile = path.resolve(__dirname, 'bin_tr_error', 'tr.js');
t.notEqual(err.indexOf('there was error'), -1, 'Error should contain error message')
t.notEqual(err.indexOf(errorFile), -1, 'Error should contain stack trace')
});
});
+1
View File
@@ -0,0 +1 @@
t.equal(XXX * 5, 555);
+12
View File
@@ -0,0 +1,12 @@
var through = require('through2');
module.exports = function (file, opts) {
var data = '';
return through(write, end);
function write (buf, enc, next) { data += buf; next() }
function end () {
this.emit('error', new Error('there was error'))
this.push(null);
}
};
+19
View File
@@ -0,0 +1,19 @@
var browserify = require('../');
var vm = require('vm');
var test = require('tap').test;
test('byte order marker', function (t) {
t.plan(2);
var b = browserify(__dirname + '/bom/hello.js');
b.bundle(function (err, src) {
if (err) t.fail(err);
var c = {
console: { log: function (msg) {
t.equal(msg, 'hello');
} }
};
vm.runInNewContext(src, c);
t.notOk(/\ufeff/.test(src.toString('utf8')));
});
});
+1
View File
@@ -0,0 +1 @@
console.log('hello')
+13
View File
@@ -0,0 +1,13 @@
var test = require('tap').test;
var vm = require('vm');
var browserify = require('../');
test('browser field file no ext', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_file/xyz');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (msg) { t.equal(msg, 'cool beans') }
});
});
+5
View File
@@ -0,0 +1,5 @@
{
"browser": {
"./xyz": "wow.js"
}
}
+1
View File
@@ -0,0 +1 @@
console.log('cool beans');
+124
View File
@@ -0,0 +1,124 @@
var browserify = require('../');
var vm = require('vm');
var test = require('tap').test;
test('browser field resolve (a)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/a/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.equal(x, 555) }
});
});
test('browser field resolve (b)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/b/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.equal(x, 444) }
});
});
test('browser field resolve (c)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/c/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.equal(x, 333) }
});
});
test('browser field resolve (d)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/d/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.equal(x, 222) }
});
});
test('browser field resolve (e)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/e/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.equal(x, 111) }
});
});
test('browser field resolve (f)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/f/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.equal(x, 999) }
});
});
test('browser field resolve (g)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/g/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.deepEqual(x, {}) }
});
});
test('browser field resolve (h)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/h/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.deepEqual(x, {}) }
});
});
test('browser field resolve (i)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/i/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.deepEqual(x, 5000) }
});
});
test('browser field resolve (j)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/j/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.deepEqual(x, 5000) }
});
});
test('browser field resolve (k)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/k/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.deepEqual(x, 3000) }
});
});
test('browser field resolve (l)', function (t) {
t.plan(2);
var b = browserify(__dirname + '/browser_field_resolve/l/main.js');
b.bundle(function (err, src) {
t.ifError(err);
vm.runInNewContext(src, { console: { log: log } });
function log (x) { t.deepEqual(x, 3000) }
});
});
+1
View File
@@ -0,0 +1 @@
console.log(require('zzz'))
@@ -0,0 +1,5 @@
{
"browser": {
"zzz": "aaa"
}
}
+1
View File
@@ -0,0 +1 @@
console.log(require('zzz'))
@@ -0,0 +1,5 @@
{
"browser": {
"zzz": "./x"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 444
+1
View File
@@ -0,0 +1 @@
console.log(require('./z.js'))
@@ -0,0 +1,5 @@
{
"browser": {
"./z": "./x"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 333
+1
View File
@@ -0,0 +1 @@
console.log(require('./z.js'))
@@ -0,0 +1,5 @@
{
"browser": {
"./z.js": "./x.js"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 222
+1
View File
@@ -0,0 +1 @@
console.log(require('./z.js'))
@@ -0,0 +1,5 @@
{
"browser": {
"./z": "./x.js"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 111
+1
View File
@@ -0,0 +1 @@
console.log(require('aaa/what.js'))
@@ -0,0 +1,5 @@
{
"browser": {
"aaa/what": "./x.js"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 999
+2
View File
@@ -0,0 +1,2 @@
try { var x = require('./x') } catch (err) {}
console.log(x)
@@ -0,0 +1,5 @@
{
"browser": {
"./x.js": false
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 1000
+2
View File
@@ -0,0 +1,2 @@
try { var x = require('./x.js') } catch (err) {}
console.log(x)
@@ -0,0 +1,5 @@
{
"browser": {
"./x": false
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 1000
@@ -0,0 +1 @@
module.exports = 5000
+2
View File
@@ -0,0 +1,2 @@
var x = require('./x.js')
console.log(x)
@@ -0,0 +1,5 @@
{
"browser": {
"./x": "./browser"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = 1000

Some files were not shown because too many files have changed in this diff Show More