├── .gitignore ├── .jshintignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package.json └── test ├── coffee └── foo.coffee ├── expected-coffescript-sourcemap.json ├── expected-sourcemap.json ├── foo ├── dep.js └── dep2.js ├── index.html ├── module.js ├── regressions ├── a.js └── last-char-curly-brace.js ├── test.js └── withIndex └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | test/compiled.js 2 | test/compiled-for-source-maps.js 3 | test/compiled-for-coffee-source-maps.js 4 | node_modules 5 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test/compiled.js 3 | test/compiled-for-source-maps.js 4 | test/compiled-for-coffee-source-maps.js 5 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "noempty": true, 4 | "newcap": true, 5 | "eqeqeq": true, 6 | "eqnull": true, 7 | "undef": true, 8 | "devel": true, 9 | "node": true, 10 | "browser": true, 11 | "evil": false, 12 | "latedef": "func", 13 | "nonew": true, 14 | "trailing": true, 15 | "immed": true, 16 | "smarttabs": true, 17 | "strict": true, 18 | "predef": [ 19 | "before", 20 | "after", 21 | "describe", 22 | "require", 23 | "define", 24 | "it", 25 | "chai", 26 | "sinon" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.8" 4 | - "0.10" 5 | before_install: 6 | - npm install -g npm@~1.4.6 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Licensed under the standard MIT license: 2 | 3 | Copyright 2013 Esa-Matti Suuronen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # requireify 2 | 3 | Browserify v3 transform to allow access to all modules from browser console 4 | 5 | [![Build Status](https://travis-ci.org/johnkpaul/requireify.png)](https://travis-ci.org/johnkpaul/requireify) 6 | 7 | ![Usage](https://dl.dropboxusercontent.com/u/21266325/requireify.gif) 8 | 9 | ## Usage 10 | 11 | Install requireify locally to your project: 12 | 13 | npm install requireify --save-dev 14 | 15 | 16 | Then use it as Browserify transform or global transform module: 17 | 18 | browserify --transform requireify main.js > bundle.js 19 | # Will parse files in node_modules, for more see https://github.com/substack/node-browserify/issues/566 20 | browserify --global-transform=requireify main.js > bundle.js 21 | 22 | 23 | 24 | ```javascript 25 | // /index.js 26 | exports = module.exports = { 27 | hello: 'world' 28 | }; 29 | 30 | // /foo/dep.js 31 | 32 | var dep = require('./foo/dep'); 33 | console.log(dep.hello); // world 34 | ``` 35 | 36 | Now, inside your browser console, you can look up every module on the global require 37 | 38 | >> var hello = require('/foo/dep').hello; 39 | >> console.log(hello); // world 40 | 41 | You can also include all libraries in the browser console that have been installed using npm and used in your browserify'd code. 42 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var through = require('through'); 4 | var innersource = require('innersource'); 5 | var detective = require('detective'); 6 | var generator = require('inline-source-map'); 7 | var combine = require('combine-source-map'); 8 | var EOL = require('os').EOL; 9 | var newlineRegex = new RegExp(EOL, 'g'); 10 | 11 | var prepend = innersource(addRequire).replace(newlineRegex, ''); 12 | var postpend = innersource(addModule).replace(newlineRegex, ''); 13 | 14 | module.exports = function(filename) { 15 | var buffer = ''; 16 | 17 | return through(function(chunk) { 18 | buffer += chunk.toString(); 19 | }, 20 | function() { 21 | var nodeModuleRequires = getNodeModuleRequires(buffer); 22 | var totalPrelude = prepend + nodeModuleRequires; 23 | var offset = totalPrelude.split('\n').length - 0; 24 | 25 | var partial = totalPrelude + combine.removeComments(buffer) + ';'; 26 | 27 | var complete = partial + postpend; 28 | 29 | var map = combine.create().addFile({ sourceFile: filename, source: buffer}, {line: offset}); 30 | 31 | this.queue( complete + '\n' + map.comment()); 32 | 33 | this.queue(null); 34 | }); 35 | 36 | }; 37 | 38 | function addModule(){ 39 | var global = (function(){ return this; }).call(null); 40 | if(typeof __filename !== 'undefined'){ 41 | var moduleName = __filename.slice(0, __filename.lastIndexOf('.')).replace(/\\/g, '/'); 42 | global.require[moduleName] = module.exports; 43 | } 44 | } 45 | 46 | function addRequire(){ 47 | var global = (function(){ return this; }).call(null); 48 | if(!global.require){ 49 | global.require = function require(key){ 50 | return global.require[key.replace(/\\/g, '/')]; 51 | }; 52 | 53 | (function(){ 54 | var require = global.require; 55 | var ret = global.require; 56 | 57 | Object.defineProperty(global, 'require', { 58 | get: function(){ 59 | return ret; 60 | }, 61 | set: function(newRequire){ 62 | ret = function(key){ 63 | key = key.replace(/\\/g, '/'); 64 | 65 | if(require[key]){ 66 | return require[key]; 67 | }else if(require[key + '/index']){ 68 | return require[key + '/index']; 69 | }else{ 70 | var temp = ret; 71 | var module; 72 | ret = newRequire; 73 | try { 74 | module = newRequire(key); 75 | } 76 | catch(e){ 77 | ret = temp; 78 | throw e; 79 | } 80 | ret = temp; 81 | return module; 82 | } 83 | }; 84 | for(var key in require){ 85 | ret[key] = require[key]; 86 | } 87 | } 88 | }); 89 | 90 | })(); 91 | } 92 | 93 | } 94 | 95 | function getNodeModuleRequires(source){ 96 | var requires = detective(source); 97 | requires = requires.filter(function(require){ 98 | return require[0] !== '.'; 99 | }); 100 | return requires.map(function(require){ 101 | require = require.replace(/\\/g, '/'); 102 | return ";var global = (function(){ return this; }).call(null);global.require['"+require+"'] = require('"+require+"');"; 103 | }).join(''); 104 | } 105 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "requireify", 3 | "version": "1.0.0", 4 | "description": "Browserify plugin to access all modules from browser console", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test/test.js", 8 | "pretest": "npm run hint", 9 | "hint": "jshint --config .jshintrc ." 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/johnkpaul/requireify" 14 | }, 15 | "keywords": [ 16 | "browserify", 17 | "v2", 18 | "js", 19 | "plugin", 20 | "transform" 21 | ], 22 | "author": "John K. Paul", 23 | "license": "MIT", 24 | "dependencies": { 25 | "combine-source-map": "~0.2.0", 26 | "detective": "~4.2.0", 27 | "inline-source-map": "~0.2.5", 28 | "innersource": "0.0.2", 29 | "through": "~2.2.7" 30 | }, 31 | "devDependencies": { 32 | "jshint": "~2.1.11", 33 | "convert-source-map": "~0.2.6", 34 | "coffeeify": "~0.5.2", 35 | "browserify": ">=3.0.0" 36 | }, 37 | "peerDependencies": { 38 | "browserify": ">=3.0.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/coffee/foo.coffee: -------------------------------------------------------------------------------- 1 | module.exports = exports = -> 2 | console.log 'YO' 3 | debugger 4 | console.log 'BRO' 5 | 6 | exports() 7 | -------------------------------------------------------------------------------- /test/expected-coffescript-sourcemap.json: -------------------------------------------------------------------------------- 1 | "{\"version\":3,\"file\":\"generated.js\",\"sources\":[\"/Users/jpaul/workspace/requireify/node_modules/browserify/node_modules/browser-pack/_prelude.js\",\"/Users/jpaul/workspace/requireify/test/coffee/foo.coffee\"],\"names\":[],\"mappings\":\"AAAA;;;ACAA,IAAA,GAAA;;AAAA,CAAA,EAAiB,GAAX,CAAN,EAA2B;CACzB,CAAA,CAAA,CAAA,GAAO;CACP,UADA;CAEQ,EAAR,EAAA,EAAO,EAAP;CAHyB;;AAK3B,CALA,MAKA\",\"sourcesContent\":[\"(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\\\"function\\\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\\\"Cannot find module '\\\"+o+\\\"'\\\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\\\"function\\\"&&require;for(var o=0;o\\n console.log 'YO'\\n debugger\\n console.log 'BRO'\\n\\nexports()\\n\"]}" -------------------------------------------------------------------------------- /test/expected-sourcemap.json: -------------------------------------------------------------------------------- 1 | "{\"version\":3,\"file\":\"generated.js\",\"sources\":[\"/Users/jpaul/workspace/requireify/node_modules/browserify/node_modules/browser-pack/_prelude.js\",\"/Users/jpaul/workspace/requireify/node_modules/innersource/index.js\",\"/Users/jpaul/workspace/requireify/test/foo/dep.js\",\"/Users/jpaul/workspace/requireify/test/foo/dep2.js\",\"/Users/jpaul/workspace/requireify/test/module.js\",\"/Users/jpaul/workspace/requireify/test/withIndex/index.js\"],\"names\":[],\"mappings\":\"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACTA;AACA;;;;;;;ACDA;AACA\",\"sourcesContent\":[\"(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\\\"function\\\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\\\"Cannot find module '\\\"+o+\\\"'\\\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\\\"function\\\"&&require;for(var o=0;o 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var foo = require('./foo/dep'); 3 | var dep2 = require('./foo/dep2'); 4 | var withIndex = require('./withIndex'); 5 | var innersource = require('innersource'); 6 | 7 | exports = module.exports = { 8 | hello: foo.hello 9 | }; 10 | -------------------------------------------------------------------------------- /test/regressions/a.js: -------------------------------------------------------------------------------- 1 | /* jshint asi: true */ 2 | module.exports.foo = function () { 3 | "use strict"; 4 | return 'foo'; 5 | } -------------------------------------------------------------------------------- /test/regressions/last-char-curly-brace.js: -------------------------------------------------------------------------------- 1 | var a = require('./a'); 2 | console.log(a.foo()); -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var vm = require('vm'); 5 | var assert = require('assert'); 6 | var util = require('util'); 7 | 8 | var browserify = require('browserify'); 9 | var coffeeify = require('coffeeify'); 10 | var requireify = require('../index'); 11 | var innersource = require('innersource'); 12 | var convert = require('convert-source-map'); 13 | 14 | var modulePath = __dirname + '/module.js'; 15 | var exported = __dirname + '/compiled.js'; 16 | 17 | var b = browserify({ debug: true }); 18 | 19 | b.transform(requireify); 20 | 21 | b.require(__dirname + '/foo/dep2.js', {expose: 'x'}); 22 | 23 | b.add(modulePath) 24 | .bundle(function(err, src){ 25 | var completeScript = src+innersource(tests); 26 | var script = vm.createScript(completeScript); 27 | fs.writeFileSync(__dirname+'/compiled.js', completeScript); 28 | 29 | var context = getContext(); 30 | context.self = context.window; 31 | 32 | script.runInNewContext(context); 33 | 34 | assert.equal(context.window.test, 'world'); 35 | assert.equal(context.window.test2, 'world'); 36 | assert.equal(context.window.test3, 'tests();'); 37 | assert.equal(context.window.test4, 'works'); 38 | }); 39 | 40 | // test for sourcemaps 41 | b.add(modulePath) 42 | .bundle(function(err, src){ 43 | 44 | var sourceMapComment = src.toString('utf8').split('\n').slice(-2)[0]; 45 | var json = convert.fromComment(sourceMapComment); 46 | 47 | //expected was found by first checking by hand and then saving those mappings 48 | //fs.writeFileSync('./expected-sourcemap', JSON.stringify(json)); 49 | var expected = JSON.parse(require('./expected-sourcemap')).mappings; 50 | assert.equal(json.sourcemap.mappings, expected); 51 | }); 52 | 53 | var b = browserify({ debug: true }); 54 | 55 | 56 | // test for coffescript with sourcemaps 57 | b.transform(coffeeify).transform(requireify) 58 | .add(__dirname+'/coffee/foo.coffee') 59 | .bundle(function(err, src){ 60 | fs.writeFileSync(__dirname+'/compiled-for-coffee-source-maps.js', src); 61 | var sourceMapComment = src.toString('utf8').split('\n').slice(-2)[0]; 62 | var json = convert.fromComment(sourceMapComment); 63 | // fs.writeFileSync('./expected-coffeescript-sourcemap', JSON.stringify(json)); 64 | 65 | //expected was found by first checking by hand and then saving those mappings 66 | var expected = JSON.parse(require('./expected-coffescript-sourcemap')).mappings; 67 | assert.equal(json.sourcemap.mappings, expected); 68 | }); 69 | 70 | var b = browserify({ debug: true }); 71 | 72 | // test for last curly brace error in issue #4 73 | b.transform(requireify) 74 | .add(__dirname+'/regressions/last-char-curly-brace.js') 75 | .bundle(function(err, src){ 76 | if(err){ 77 | throw err; 78 | } 79 | var script = vm.createScript(src); 80 | var context = getContext(); 81 | script.runInNewContext(context); 82 | }); 83 | 84 | 85 | function getContext(){ 86 | return {console:{log: function(){ 87 | console.log.apply(console, arguments); 88 | }},window:{}}; 89 | 90 | } 91 | 92 | function tests(){ 93 | var innersource = require('innersource'); 94 | window.test = require("x"); 95 | try{ 96 | var dne = require('does_not_exist'); 97 | } 98 | catch(e){ 99 | dne = undefined; 100 | } 101 | window.test2 = require("/foo/dep").hello; 102 | window.test3 = innersource(function(){tests();}); 103 | window.test4 = require('/withIndex'); 104 | } 105 | -------------------------------------------------------------------------------- /test/withIndex/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 'works'; 2 | --------------------------------------------------------------------------------