Skip to content

Commit

Permalink
Added node_modules and source map support.
Browse files Browse the repository at this point in the history
  • Loading branch information
RReverser committed Jan 23, 2014
1 parent 9c498c8 commit 5180493
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 18 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Features
* Minimal destination overhead (almost as small as concatenated file).
* Ability to export `module.exports` from top module as single property / identifier (useful for building libs).
* Resolves all the paths on build stage to static number identifiers (so saves space and execution time used for storing and resolving string paths, but should be used only for projects with static `require('./some/module')` calls and would fail on others (same restriction applicable for [r.js (Simplified CommonJS wrapper)](http://requirejs.org/docs/whyamd.html#sugar) and most projects already match this).
* Supports modules installed as `npm` dependencies in `node_modules` hierarchy.
* Does not corrupt `require('systemModule')` calls, transforms only local ones.

Console usage
Expand All @@ -23,6 +24,7 @@ Command-line options:
-V, --version output the version number
-i, --input <file> input file (required)
-o, --output <file> output file (defaults to <input>.out.js)
-m, --map <file> file to store source map to (optional, defaults to <output>.map)
-e, --exports <id> top module exports destination (optional)
```

Expand All @@ -35,6 +37,7 @@ var cjs = require('pure-cjs');
cjs.transform({
input: 'superLib/topModule.js' /* String|Function(): input file */,
output: function (input) { return input.replace(/(\.js)?$/, '.out.js') } /* [?] String|Function(input): output file */,
map: function (input, output) { return output + '.map' } /* [?] String|Function(input, output): source map file */,
exports: 'window.SuperLib' /* [?] String|Function(input, output): Object to wrap and put exports from top module into */
});
```
Expand Down
1 change: 1 addition & 0 deletions bin/pure-cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ program
.version(require(__dirname + '/../package.json').version)
.option('-i, --input <file>', 'input file (required)')
.option('-o, --output <file>', 'output file (defaults to <input>.out.js)')
.option('-m, --map [file]', 'file to store source map to (optional)')
.option('-e, --exports <id>', 'top module exports destination (optional)')
.parse(process.argv);

Expand Down
51 changes: 44 additions & 7 deletions lib/pure-cjs.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
var fs = require('fs'),
recast = require('recast'),
url = require('url'),
cwd = process.cwd(),
pathUtils = require('path'),
nodeResolve = require('resolve'),
Promise = require('davy'),

b = recast.builders,
n = recast.namedTypes,
types = recast.types,
b = types.builders,
n = types.namedTypes,

whenReadFile = Promise.wrap(fs.readFile),
whenWriteFile = Promise.wrap(fs.writeFile),
Expand All @@ -16,12 +20,16 @@ var fs = require('fs'),
astModuleArgs = [b.identifier('module'), b.identifier('exports')],
astRequire = b.identifier('_require'),
astLocalReqModules = b.memberExpression(astRequire, b.identifier('modules'), false),
astPreamble = recast.parse(fs.readFileSync(__dirname + '/preamble.js')).program.body;
astPreamble = recast.parse(fs.readFileSync(__dirname + '/preamble.js'), {sourceFileName: 'preamble.js'}).program.body;

function normalizePath(path) {
return url.resolve('', path.replace(badPathSep, '/'));
}

function relative(from, to) {
return pathUtils.relative(from, to).replace(badPathSep, '/');
}

function toValue(value) {
return value instanceof Function ? value.apply(null, Array.prototype.slice.call(arguments, 1)) : value;
}
Expand Down Expand Up @@ -64,22 +72,29 @@ var Replacer = recast.Visitor.extend({
this.map = map;
this.path = path;
this.promise = whenReadFile(path, {encoding: 'utf-8'}).then(function (js) {
var ast = recast.parse(js).program;
var ast = recast.parse(js, {sourceFileName: path}).program;
this.visit(ast);
return b.functionExpression(null, astModuleArgs, b.blockStatement(ast.body));
}.bind(this));
},

getDependency: function (path) {
path = url.resolve(this.path, path).replace(jsExtRegExp, '.js');
if (localRegEx.test(path)) {
path = url.resolve(this.path, path).replace(jsExtRegExp, '.js');
} else {
path = relative(cwd, nodeResolve.sync(path, {
basedir: pathUtils.resolve(cwd, pathUtils.dirname(this.path))
}));
}

return this.map.get(path);
},

visitCallExpression: function (node) {
var func = node.callee,
arg = node.arguments[0];

if (n.Identifier.check(func) && func.name === 'require' && n.Literal.check(arg) && localRegEx.test(arg.value)) {
if (n.Identifier.check(func) && func.name === 'require' && n.Literal.check(arg) && !nodeResolve.isCore(arg.value)) {
func.name = astRequire.name;
arg.value = this.getDependency(arg.value).id;
}
Expand All @@ -100,6 +115,16 @@ exports.transform = function (inOptions) {
options.input
));

if (inOptions.map) {
options.map = normalizePath(toValue(
inOptions.map !== true ? inOptions.map : function (input, output) {
return output + '.map';
},
options.input,
options.output
));
}

options.exports = toValue(inOptions.exports, options.input, options.output);

var map = new ReplacerMap(),
Expand Down Expand Up @@ -134,7 +159,19 @@ exports.transform = function (inOptions) {
stmts.push(b.expressionStatement(requireExpr));
}

return whenWriteFile(options.output, recast.print(b.program(stmts))).then(function () {
var output = recast.print(b.program(stmts), {sourceMapName: options.map}),
whenOut;

if (options.map) {
whenOut = Promise.all(
whenWriteFile(options.output, output.code + '\n//# sourceMappingURL=' + relative(pathUtils.dirname(options.output), options.map)),
whenWriteFile(options.map, JSON.stringify(output.map))
);
} else {
whenOut = whenWriteFile(options.output, output.code);
}

return whenOut.then(function () {
return options;
});
});
Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "pure-cjs",
"version": "1.4.0",
"version": "1.6.0",
"description": "Pure minimalistic CommonJS builder",
"bin": "./bin/pure-cjs",
"main": "./lib/pure-cjs",
"preferGlobal": true,
"scripts": {
"test": "node ./bin/pure-cjs -i sample/a.js -e window.A"
"test": "node ./bin/pure-cjs -i sample/a.js -m -e window.A"
},
"repository": {
"type": "git",
Expand All @@ -19,7 +19,8 @@
},
"dependencies": {
"commander": "~2.1.0",
"recast": "~0.4.25",
"davy": "0.0.8"
"resolve": "~0.6.1",
"davy": "0.0.8",
"recast": "~0.5.7"
}
}
1 change: 1 addition & 0 deletions sample/a.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script src="a.out.js"></script>
7 changes: 5 additions & 2 deletions sample/a.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
var url = require('url'),
var davy = require('davy'),
url = require('url'),
c = require('./c');

this.topValue = require('./sub/b.js') * 2;
this.topValue = require('./sub/b.js') * 2;

window.Promise = davy;
Loading

0 comments on commit 5180493

Please sign in to comment.