pax_global_header00006660000000000000000000000064126575721400014523gustar00rootroot0000000000000052 comment=ae41cdcdfc3848f24c73e7622892ee9181b9e742 browserify-lite-0.5.0/000077500000000000000000000000001265757214000146535ustar00rootroot00000000000000browserify-lite-0.5.0/.gitignore000066400000000000000000000000161265757214000166400ustar00rootroot00000000000000/node_modules browserify-lite-0.5.0/LICENSE000066400000000000000000000020721265757214000156610ustar00rootroot00000000000000The MIT License (Expat) Copyright (c) 2014 Andrew Kelley 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. browserify-lite-0.5.0/README.md000066400000000000000000000015161265757214000161350ustar00rootroot00000000000000# browserify-lite browserify, minus some of the advanced features and heavy dependencies. * No builtin Node.js shims. * Naive AST tokenization for require instead of true AST parsing. - All require statements are found regardless of if they are in an `if` statement or a function body that is never called. * Only supports a single entry file and the `--outfile` parameter, nothing else. * No source maps. * Minimal dependencies. ## Usage ``` browserify-lite ./entry-file.js --outfile bundle.js Standard Options: --outfile Write the browserify bundle to this file. --standalone xyz Export as a window global. ``` ./src/app.js can depend on any modules using Node.js's [module resolution system](http://nodejs.org/docs/latest/api/modules.html#modules_all_together) and they will be bundled as well. browserify-lite-0.5.0/cli.js000077500000000000000000000020331265757214000157610ustar00rootroot00000000000000#!/usr/bin/env node var fs = require('fs'); var browserifyLite = require('./'); var options = {}; for (var i = 2; i < process.argv.length; i += 1) { var arg = process.argv[i]; if (arg === '--help') { usage(); } else if (arg === '--outfile') { if (++i >= process.argv.length) usage(); options.outBundlePath = process.argv[i]; } else if (arg === '--standalone') { if (++i >= process.argv.length) usage(); options.standalone = process.argv[i]; } else if (!options.entrySourcePath) { options.entrySourcePath = arg; } else { usage(); } } if (!options.outBundlePath || !options.entrySourcePath) { usage(); } browserifyLite.createBundle(options, function(err) { if (err) throw err; }); function usage() { console.error( "Usage: browserify-lite ./entry-file.js --outfile bundle.js\n" + "\n" + "Standard Options:\n" + "\n" + " --outfile Write the browserify bundle to this file\n" + " --standalone xyz Export as window.xyz"); process.exit(1); } browserify-lite-0.5.0/index.js000066400000000000000000000234311265757214000163230ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var Pend = require('pend'); exports.extractRequires = extractRequires; exports.createBundle = createBundle; exports.renderBundle = renderBundle; function createBundle(options, cb) { var outBundlePath = options.outBundlePath; renderBundle(options, function(err, output) { if (err) return cb(err); fs.writeFile(outBundlePath, output, cb); }); } function renderBundle(options, cb) { var entrySourcePath = options.entrySourcePath; var standalone = options.standalone; // data structure that is filled up with canonical source path as the key, // source code as the value. var sources = {}; // describes the dependency graph. key is canonical source path, value is // array of canonical source path dependencies var deps = {}; // each file has its own map of how require statements resolve. var depMap = {}; var sourceQueue = []; requireResolve(entrySourcePath, process.cwd(), function(err, resolvedPath) { if (err) return cb(err); sourceQueue.push(resolvedPath); collectDependencies(function(err) { if (err) return cb(err); render(resolvedPath, function(err, output) { if (err) return cb(err); cb(null, output); }); }); }); function collectDependencies(cb) { var canonicalSourcePath = sourceQueue.shift(); if (!canonicalSourcePath) return cb(); if (sources[canonicalSourcePath]) return collectDependencies(cb); fs.readFile(canonicalSourcePath, {encoding: 'utf8'}, function(err, source) { if (err) return cb(err); sources[canonicalSourcePath] = source; deps[canonicalSourcePath] = {}; depMap[canonicalSourcePath] = {}; var pend = new Pend(); extractRequires(source, function(err, requireList) { if (err) return cb(err); requireList.forEach(function(requireItem) { pend.go(function(cb) { requireResolve(requireItem, path.dirname(canonicalSourcePath), function(err, canonicalDepPath) { if (err) return cb(err); deps[canonicalSourcePath][canonicalDepPath] = true; depMap[canonicalSourcePath][requireItem] = canonicalDepPath; sourceQueue.push(canonicalDepPath); cb(); }); }); }); pend.wait(function(err) { if (err) return cb(err); collectDependencies(cb); }); }); }); } function render(entrySourcePath, cb) { var modules = Object.keys(sources); var aliases = {}; modules.forEach(function(canonicalSourcePath, index) { aliases[canonicalSourcePath] = index; }); modules.forEach(function(canonicalSourcePath, index) { var thisDepMap = depMap[canonicalSourcePath] for (var depSourcePath in thisDepMap) { thisDepMap[depSourcePath] = aliases[thisDepMap[depSourcePath]]; } }); var standaloneLine = standalone ? " window." + standalone + " = req(entry);\n" : " req(entry);\n"; var out = "(function(modules, cache, entry) {\n" + standaloneLine + " function req(name) {\n" + " if (cache[name]) return cache[name].exports;\n" + " var m = cache[name] = {exports: {}};\n" + " modules[name][0].call(m.exports, modRequire, m, m.exports, window);\n" + " return m.exports;\n" + " function modRequire(alias) {\n" + " var id = modules[name][1][alias];\n" + " if (!id) throw new Error(\"Cannot find module \" + alias);\n" + " return req(id);\n" + " }\n" + " }\n" + "})({"; modules.forEach(function(canonicalSourcePath) { out += aliases[canonicalSourcePath] + ": [function(require,module,exports,global){\n"; if (canonicalSourcePath.match(/\.json$/)) { out += "module.exports = "; } out += sources[canonicalSourcePath]; out += "\n}, " + JSON.stringify(depMap[canonicalSourcePath]) + "],"; }); out += "}, {}, " + aliases[entrySourcePath] + ");\n"; cb(null, out); } } function tokenizeSource(source) { var tokens = []; var inQuote = false; var quoteType; var qEscape = false; var token = ""; var inLineComment = false; var inMultiLineComment = false; var startComment = false; var endComment = false; for (var i = 0; i < source.length; i += 1) { var c = source[i]; if (inQuote) { if (qEscape) { token += c; qEscape = false; } else if (c === "\\") { qEscape = true; } else if (c === quoteType) { inQuote = false; tokens.push(token); token = ""; } else { token += c; } } else if (inLineComment) { if (c === "\n") { inLineComment = false; } } else if (inMultiLineComment) { if (c === '*') { endComment = true; } else if (c === '/') { if (endComment) { inMultiLineComment = false; endComment = false; } } else { endComment = false; } } else if (c === "\"" || c === "'") { startComment = false; if (token) tokens.push(token); token = ""; inQuote = true; quoteType = c; qEscape = false; } else if (c === '{') { startComment = false; if (token) tokens.push(token); token = ""; } else if (c === '}') { startComment = false; } else if (c === '/') { if (startComment) { if (token) tokens.push(token); token = ""; inLineComment = true; startComment = false; } else { startComment = true; } } else if (c === '*' && startComment) { if (token) tokens.push(token); token = ""; inMultiLineComment = true; startComment = false; } else { if (/\W/.test(c)) { if (token) tokens.push(token); token = ""; } if (/\S/.test(c)) { token += c; } } } if (token) tokens.push(token); return tokens; } var stateCount = 0; var STATE_WANT_REQUIRE = stateCount++; var STATE_WANT_LPAREN = stateCount++; var STATE_WANT_STR = stateCount++; var STATE_WANT_RPAREN = stateCount++; function extractRequires(source, cb) { var tokens = tokenizeSource(source); var requiresList = []; var state = STATE_WANT_REQUIRE; var requireName; for (var i = 0; i < tokens.length; i += 1) { var token = tokens[i]; if (state === STATE_WANT_REQUIRE && token === 'require') { state = STATE_WANT_LPAREN; } else if (state === STATE_WANT_LPAREN && token === '(') { state = STATE_WANT_STR; } else if (state === STATE_WANT_STR) { requireName = token; state = STATE_WANT_RPAREN; } else if (state === STATE_WANT_RPAREN && token === ')') { state = STATE_WANT_REQUIRE; requiresList.push(requireName); } else if (state === STATE_WANT_RPAREN && token !== ')') { state = STATE_WANT_REQUIRE; } } cb(null, requiresList); } function requireResolve(pkg, basedir, cb) { if (/^[.\/]/.test(pkg)) { requireResolvePath(path.resolve(basedir, pkg), cb); } else { requireResolveModule(pkg, basedir, cb); } } function requireResolveModule(pkg, basedir, cb) { var globalSearchPaths = process.env.NODE_PATH ? process.env.NODE_PATH.split(path.delimiter) : []; var localSearchPaths = []; var parts = basedir.split(path.sep); var it = "/"; for (var i = 0; i < parts.length; i += 1) { it = path.join(it, parts[i]); localSearchPaths.unshift(path.join(it, "node_modules")); } var searchPaths = localSearchPaths.concat(globalSearchPaths); var index = 0; trySearchPath(); function trySearchPath() { var searchPath = searchPaths[index]; if (!searchPath) return cb(new Error("module " + pkg + " in " + basedir + " not found")); requireResolvePath(path.resolve(searchPath, pkg), function(err, resolvedFilename) { if (!err) return cb(null, resolvedFilename); index += 1; trySearchPath(); }); } } function requireResolvePath(filename, cb) { resolveFile(filename, function(err, resolvedFilename) { if (!err) return cb(null, resolvedFilename); resolveFile(filename + '.js', function(err, resolvedFilename) { if (!err) return cb(null, resolvedFilename); resolveFile(filename + '.json', function(err, resolvedFilename) { if (!err) return cb(null, resolvedFilename); resolveDirectory(filename, cb); }); }); }); } function resolveFile(filename, cb) { fs.stat(filename, function(err, stat) { if (err) return cb(err); if (stat.isDirectory()) return cb(new Error("directory")); cb(null, filename); }); } function resolveDirectory(dirname, cb) { var packageJsonPath = path.resolve(dirname, "package.json"); fs.readFile(packageJsonPath, {encoding: 'utf8'}, function(err, packageJsonStr) { if (!err) { var packageJson; try { packageJson = JSON.parse(packageJsonStr); } catch (err) { cb(new Error("Invalid package.json: " + packageJsonPath + ": "+ err.message)); return; } var filename; var browserObject = packageJson.browserify || packageJson.browser; if (typeof browserObject === 'string') { filename = path.resolve(dirname, browserObject); requireResolvePath(filename, tryIndex); } else if (packageJson.main) { filename = path.resolve(dirname, packageJson.main); requireResolvePath(filename, tryIndex); } else { tryIndex(new Error("no main found in package.json")); } } else { tryIndex(new Error("no package.json found")); } function tryIndex(err, filename) { if (!err) return cb(null, filename); filename = path.resolve(dirname, "index.js"); resolveFile(filename, function(err) { if (!err) return cb(null, filename); filename = path.resolve(dirname, "index.json"); resolveFile(filename, cb); }); } }); } browserify-lite-0.5.0/package.json000066400000000000000000000010651265757214000171430ustar00rootroot00000000000000{ "name": "browserify-lite", "version": "0.5.0", "description": "browserify, minus some of the advanced features and heavy dependencies.", "main": "index.js", "scripts": { "test": "node test.js" }, "bin": { "browserify-lite": "./cli.js" }, "author": "Andrew Kelley ", "license": "MIT", "dependencies": { "pend": "~1.2.0" }, "repository": { "type": "git", "url": "git://github.com/andrewrk/browserify-lite.git" }, "bugs": { "url": "https://github.com/andrewrk/browserify-lite/issues" } } browserify-lite-0.5.0/test.js000066400000000000000000000037501265757214000161750ustar00rootroot00000000000000var assert = require('assert'); var browserifyLite = require('./'); var extractRequiresTests = [ { name: "basic", source: "require('./code')", output: [ "./code" ], }, { name: "multiple", source: "var EventEmitter = require('./event_emitter');\n" + "var inherits = require('./inherits');\n" + "var uuid = require('./uuid');\n" + "var MusicLibraryIndex = require('music-library-index');\n" + "var keese = require(\"keese\");\n" + "var curlydiff = require('curlydiff');\n", output: [ "./event_emitter", "./inherits", "./uuid", "music-library-index", "keese", "curlydiff", ], }, { name: "trick", source: "require('./code');\nvar a = \"require('foo');\";\nrequire(\"../morecode\");", output: [ "./code", "../morecode", ], }, { name: "unescape", source: "require('./code');\nvar a = \"require(\\\"foo\\\");\";\nrequire(\"../morecode\");", output: [ "./code", "../morecode", ], }, { name: "spaces", source: "var foo = require ( 'derp ' ) ;\n", output: [ "derp ", ], }, { name: "ignore braces", source: "var foo = require('derp'); { require('dont-ignore-this'); } require('this-ok')\n", output: [ "derp", "dont-ignore-this", "this-ok", ], }, { name: "ignore comments", source: "/* var foo = require('derp');*/ { require('dont-ignore-this'); } require('this-ok') // require('also-ignore-this'); \n require('this-also-ok')", output: [ "dont-ignore-this", "this-ok", "this-also-ok", ], } ]; process.stderr.write("extract requires tests:\n"); extractRequiresTests.forEach(function(extractRequiresTest) { process.stderr.write(extractRequiresTest.name + "..."); browserifyLite.extractRequires(extractRequiresTest.source, function(err, requiresList) { if (err) throw err; assert.deepEqual(extractRequiresTest.output, requiresList); process.stderr.write("OK\n"); }); });