diff --git a/index.js b/index.js index 5ca9cec..a116c49 100644 --- a/index.js +++ b/index.js @@ -1,152 +1,187 @@ -var staticModule = require('static-module'); -var quote = require('quote-stream'); -var through = require('through2'); -var fs = require('fs'); -var path = require('path'); -var resolve = require('resolve'); +var staticModule = require("static-module"); +var quote = require("quote-stream"); +var through = require("through2"); +var fs = require("fs"); +var path = require("path"); +var resolve = require("resolve"); module.exports = function (file, opts) { - if (/\.json$/.test(file)) return through(); - - function resolver (p) { - return resolve.sync(p, { basedir: path.dirname(file) }); - } - var vars = { - __filename: file, - __dirname: path.dirname(file), - require: { resolve: resolver } - }; - if (!opts) opts = {}; - if (opts.vars) Object.keys(opts.vars).forEach(function (key) { - vars[key] = opts.vars[key]; + if (/\.json$/.test(file)) return through(); + + function resolver(p) { + return resolve.sync(p, { basedir: path.dirname(file) }); + } + function convertTransformOptionToStream(f, args) { + if (typeof f === "function") { + return f.apply(null, args); + } + + return f; + } + var vars = { + __filename: file, + __dirname: path.dirname(file), + require: { resolve: resolver }, + }; + if (!opts) opts = {}; + if (opts.vars) + Object.keys(opts.vars).forEach(function (key) { + vars[key] = opts.vars[key]; }); - - var sm = staticModule( - { - fs: { - readFileSync: readFileSync, - readFile: readFile, - readdirSync: readdirSync, - readdir: readdir - } - }, - { - vars: vars, - varModules: { path: path }, - parserOpts: opts && opts.parserOpts, - sourceMap: opts && (opts.sourceMap || opts._flags && opts._flags.debug), - inputFilename: file - } - ); - return sm; - - function readFile (file, enc, cb) { - if (typeof enc === 'function') { - cb = enc; - enc = null; - } - if (enc && typeof enc === 'object' && enc.encoding) { - enc = enc.encoding; - } - var isBuffer = false; - if (enc === null || enc === undefined) { - isBuffer = true; - enc = 'base64'; - } - - var stream = through(write, end); - stream.push('process.nextTick(function(){(' + cb + ')(null,'); - if (isBuffer) stream.push('Buffer('); - - var s = fs.createReadStream(file, { encoding: enc }); - s.on('error', function (err) { sm.emit('error', err) }); - return s.pipe(quote()).pipe(stream); - - function write (buf, enc, next) { - this.push(buf); - next(); - } - function end (next) { - if (isBuffer) this.push(',"base64")'); - this.push(')})'); - this.push(null); - sm.emit('file', file); - next() - } + + var sm = staticModule( + { + fs: { + readFileSync: readFileSync, + readFile: readFile, + readdirSync: readdirSync, + readdir: readdir, + }, + }, + { + vars: vars, + varModules: { path: path }, + parserOpts: opts && opts.parserOpts, + sourceMap: opts && (opts.sourceMap || (opts._flags && opts._flags.debug)), + inputFilename: file, + } + ); + return sm; + + function readFile(file, enc, cb) { + if (file === undefined) { + throw new Error('file is not resolvable'); } - function readFileSync (file, enc) { - var isBuffer = false; - if (enc === null || enc === undefined) { - isBuffer = true; - enc = 'base64'; - } - if (enc && typeof enc === 'object' && enc.encoding) { - enc = enc.encoding; - } - var stream = fs.createReadStream(file, { encoding: enc }) - .on('error', function (err) { sm.emit('error', err) }) - .pipe(quote()).pipe(through(write, end)) - ; - if (isBuffer) { - stream.push('Buffer('); - } - return stream; - - function write (buf, enc, next) { - this.push(buf); - next(); - } - function end (next) { - if (isBuffer) this.push(',"base64")'); - this.push(null); - sm.emit('file', file); - next(); - } + if (typeof enc === "function") { + cb = enc; + enc = null; + } + if (enc && typeof enc === "object" && enc.encoding) { + enc = enc.encoding; + } + var isBuffer = false; + if (enc === null || enc === undefined) { + isBuffer = true; + enc = "base64"; + } + + var stream = through(write, end); + stream.push("process.nextTick(function(){(" + cb + ")(null,"); + if (isBuffer) stream.push("Buffer("); + + var s = fs.createReadStream(file, { encoding: enc }); + s.on("error", function (err) { + sm.emit("error", err); + }); + + if (opts.readFileTransform) { + s = s.pipe( + convertTransformOptionToStream(opts.readFileTransform, [file]) + ); + } + + return s.pipe(quote()).pipe(stream); + + function write(buf, enc, next) { + this.push(buf); + next(); + } + function end(next) { + if (isBuffer) this.push(',"base64")'); + this.push(")})"); + this.push(null); + sm.emit("file", file); + next(); + } + } + + function readFileSync(file, enc) { + if (file === undefined) { + throw new Error('file is not resolvable'); } - function readdir(path, cb) { - var stream = through(write, end); - - stream.push('process.nextTick(function(){(' + cb + ')(null,'); - fs.readdir(path, function (err, src) { - if (err) { - stream.emit('error', err); - return; - } - stream.push(JSON.stringify(src)); - stream.end(')})'); - }); - return stream; - - function write (buf, enc, next) { - this.push(buf); - next(); - } - function end (next) { - this.push(null); - next(); - } - } - - function readdirSync (path) { - var stream = through(write, end); - fs.readdir(path, function (err, src) { - if (err) { - stream.emit('error', err); - return; - } - stream.end(JSON.stringify(src)); - }); - return stream; - - function write (buf, enc, next) { - this.push(buf); - next(); - } - function end (next) { - this.push(null); - next(); - } + var isBuffer = false; + if (enc === null || enc === undefined) { + isBuffer = true; + enc = "base64"; + } + if (enc && typeof enc === "object" && enc.encoding) { + enc = enc.encoding; + } + var stream = fs + .createReadStream(file, { encoding: enc }) + .on("error", function (err) { + sm.emit("error", err); + }); + + if (opts.readFileTransform) { + stream = stream.pipe( + convertTransformOptionToStream(opts.readFileTransform, [file]) + ); + } + + stream = stream.pipe(quote()).pipe(through(write, end)); + + if (isBuffer) { + stream.push("Buffer("); + } + return stream; + + function write(buf, enc, next) { + this.push(buf); + next(); + } + function end(next) { + if (isBuffer) this.push(',"base64")'); + this.push(null); + sm.emit("file", file); + next(); + } + } + + function readdir(path, cb) { + var stream = through(write, end); + + stream.push("process.nextTick(function(){(" + cb + ")(null,"); + fs.readdir(path, function (err, src) { + if (err) { + stream.emit("error", err); + return; + } + stream.push(JSON.stringify(src)); + stream.end(")})"); + }); + return stream; + + function write(buf, enc, next) { + this.push(buf); + next(); + } + function end(next) { + this.push(null); + next(); + } + } + + function readdirSync(path) { + var stream = through(write, end); + fs.readdir(path, function (err, src) { + if (err) { + stream.emit("error", err); + return; + } + stream.end(JSON.stringify(src)); + }); + return stream; + + function write(buf, enc, next) { + this.push(buf); + next(); + } + function end(next) { + this.push(null); + next(); } + } }; diff --git a/readme.markdown b/readme.markdown index 19058a8..e8d714a 100644 --- a/readme.markdown +++ b/readme.markdown @@ -16,15 +16,15 @@ projects. for a main.js: -``` js -var fs = require('fs'); -var html = fs.readFileSync(__dirname + '/robot.html', 'utf8'); +```js +var fs = require("fs"); +var html = fs.readFileSync(__dirname + "/robot.html", "utf8"); console.log(html); ``` and a robot.html: -``` html +```html beep boop ``` @@ -38,65 +38,67 @@ $ browserify -t brfs example/main.js > bundle.js now in the bundle output file, -``` js -var html = fs.readFileSync(__dirname + '/robot.html', 'utf8'); +```js +var html = fs.readFileSync(__dirname + "/robot.html", "utf8"); ``` turns into: -``` js +```js var html = "beep boop\n"; ``` ## or with the api -``` js -var browserify = require('browserify'); -var fs = require('fs'); +```js +var browserify = require("browserify"); +var fs = require("fs"); -var b = browserify('example/main.js'); -b.transform('brfs'); +var b = browserify("example/main.js"); +b.transform("brfs"); -b.bundle().pipe(fs.createWriteStream('bundle.js')); +b.bundle().pipe(fs.createWriteStream("bundle.js")); ``` ## async You can also use `fs.readFile()`: -``` js -var fs = require('fs'); -fs.readFile(__dirname + '/robot.html', 'utf8', function (err, html) { - console.log(html); +```js +var fs = require("fs"); +fs.readFile(__dirname + "/robot.html", "utf8", function (err, html) { + console.log(html); }); ``` When you run this code through brfs, it turns into: -``` js -var fs = require('fs'); -process.nextTick(function () {(function (err, html) { +```js +var fs = require("fs"); +process.nextTick(function () { + (function (err, html) { console.log(html); -})(null,"beep boop\n")}); + })(null, "beep boop\n"); +}); ``` # methods brfs looks for: -* `fs.readFileSync(pathExpr, enc=null)` -* `fs.readFile(pathExpr, enc=null, cb)` -* `fs.readdirSync(pathExpr)` -* `fs.readdir(pathExpr, cb)` +- `fs.readFileSync(pathExpr, enc=null)` +- `fs.readFile(pathExpr, enc=null, cb)` +- `fs.readdirSync(pathExpr)` +- `fs.readdir(pathExpr, cb)` Inside of each `pathExpr`, you can use [statically analyzable](http://npmjs.org/package/static-eval) expressions and these variables and functions: -* `__dirname` -* `__filename` -* `path` if you `var path = require('path')` first -* `require.resolve()` +- `__dirname` +- `__filename` +- `path` if you `var path = require('path')` first +- `require.resolve()` Just like node, the default encoding is `null` and will give back a `Buffer`. If you want differently-encoded file contents for your inline content you can @@ -112,8 +114,8 @@ updated automatically. If you want to use this plugin directly, not through browserify, the api follows. -``` js -var brfs = require('brfs') +```js +var brfs = require("brfs"); ``` ## var tr = brfs(file, opts) @@ -128,6 +130,9 @@ in addition to `__dirname` and `__filename`. `opts.parserOpts` can be used to configure the parser brfs uses, [acorn](https://github.com/acornjs/acorn#main-parser). +`opts.readFileTransform` can be used to transform the filestream of +the given file. For example you can minify the content. + # events ## tr.on('file', function (file) {}) @@ -143,13 +148,13 @@ A tiny command-line program ships with this module to make debugging easier. usage: brfs file - + Inline `fs.readFileSync()` calls from `file`, printing the transformed file contents to stdout. brfs brfs - - + Inline `fs.readFileSync()` calls from stdin, printing the transformed file contents to stdout. @@ -168,18 +173,18 @@ the browserify api. # gotchas -Since `brfs` evaluates your source code *statically*, you can't use dynamic expressions that need to be evaluated at run time. For example: +Since `brfs` evaluates your source code _statically_, you can't use dynamic expressions that need to be evaluated at run time. For example: ```js // WILL NOT WORK! var file = window.someFilePath; -var str = require('fs').readFileSync(file, 'utf8'); +var str = require("fs").readFileSync(file, "utf8"); ``` Instead, you must use simpler expressions that can be resolved at build-time: ```js -var str = require('fs').readFileSync(__dirname + '/file.txt', 'utf8'); +var str = require("fs").readFileSync(__dirname + "/file.txt", "utf8"); ``` Another gotcha: `brfs` does not yet support ES module `import` statements. See [brfs-babel](https://github.com/Jam3/brfs-babel) for an experimental replacement that supports this syntax.