From b426d8833e2b5eb6004b1f2ca80d9a147beab1e4 Mon Sep 17 00:00:00 2001 From: Bernhard Waldbrunner Date: Mon, 22 Jun 2015 02:06:56 +0200 Subject: [PATCH] Adds support for Browserify --- lib/helpers/memoized.js | 2 +- lib/helpers/raw.js | 13 ++- lib/javascript/index.js | 82 +++++++++++++++---- lib/javascript/processors/es.js | 3 + package.json | 78 +++++++++++++----- .../javascripts/browserify/Math.coffee | 4 + test/fixtures/javascripts/browserify/Math.js | 5 ++ .../javascripts/browserify/comment.coffee | 3 + .../javascripts/browserify/comment.es | 5 ++ .../javascripts/browserify/declared.coffee | 6 ++ .../javascripts/browserify/declared.es | 7 ++ .../browserify/require_coffee.coffee | 3 + .../javascripts/browserify/require_coffee.es | 3 + .../javascripts/browserify/require_js.coffee | 3 + .../javascripts/browserify/require_js.es | 3 + test/javascripts.js | 64 +++++++++++++++ 16 files changed, 246 insertions(+), 38 deletions(-) create mode 100644 lib/javascript/processors/es.js create mode 100644 test/fixtures/javascripts/browserify/Math.coffee create mode 100644 test/fixtures/javascripts/browserify/Math.js create mode 100644 test/fixtures/javascripts/browserify/comment.coffee create mode 100644 test/fixtures/javascripts/browserify/comment.es create mode 100644 test/fixtures/javascripts/browserify/declared.coffee create mode 100644 test/fixtures/javascripts/browserify/declared.es create mode 100644 test/fixtures/javascripts/browserify/require_coffee.coffee create mode 100644 test/fixtures/javascripts/browserify/require_coffee.es create mode 100644 test/fixtures/javascripts/browserify/require_js.coffee create mode 100644 test/fixtures/javascripts/browserify/require_js.es diff --git a/lib/helpers/memoized.js b/lib/helpers/memoized.js index 5b79ebafe..7d04ee32f 100644 --- a/lib/helpers/memoized.js +++ b/lib/helpers/memoized.js @@ -32,4 +32,4 @@ exports.walkData = helpers.walkData exports.isTemplate = helpers.isTemplate exports.isStylesheet = helpers.isStylesheet exports.isJavaScript = helpers.isJavaScript - +exports.needsBrowserify = helpers.needsBrowserify diff --git a/lib/helpers/raw.js b/lib/helpers/raw.js index 5a0bd006b..c51fcf7ff 100644 --- a/lib/helpers/raw.js +++ b/lib/helpers/raw.js @@ -15,7 +15,7 @@ var TerraformError = exports.TerraformError = require("../error").TerraformError var processors = exports.processors = { "html": ["jade", "ejs", "md"], "css" : ["styl", "less", "scss", "sass"], - "js" : ["coffee"] + "js" : ["coffee", "es"] } @@ -496,3 +496,14 @@ exports.isJavaScript = function(filePath){ return processors["js"].indexOf(ext) !== -1 } + +/** + * needsBrowserify + * + * returns true if the code uses require, exports or module but doesn't declare them + */ + +exports.needsBrowserify = function(source) { + return /^[^#\/'"*]*(require|module|exports)\b/m.test(source) + && !(/\b(function|var|global) +(require|module|exports)\b|\b(module|require) *=[^=]/.test(source)) +} diff --git a/lib/javascript/index.js b/lib/javascript/index.js index d5ec6b6bf..28fe2ec07 100644 --- a/lib/javascript/index.js +++ b/lib/javascript/index.js @@ -1,7 +1,9 @@ -var path = require("path") -var fs = require("fs") -var helpers = require('../helpers') -var minify = require('minify') +var path = require("path") +var fs = require("fs") +var helpers = require('../helpers') +var minify = require('minify') +var browserify = require('browserify') +var through = require('through') /** * Build Processor list for javascripts. @@ -13,10 +15,12 @@ var minify = require('minify') * } * */ - var processors = {} + var extensions = [], processors = {} helpers.processors["js"].forEach(function(sourceType){ + extensions.push('.' + sourceType) processors[sourceType] = require("./processors/" + sourceType) }) +processors['js'] = processors['es'] // so it's possible to require .js files module.exports = function(root, filePath, callback){ @@ -41,18 +45,62 @@ module.exports = function(root, filePath, callback){ * Lookup Directories */ - var render = processors[ext].compile(srcPath, data, function(err, js) { - if (err) return callback(err); - - /** - * Consistently minify - */ - var post = minify.js(js, { - compress: false, - mangle: true - }); - callback(null, post); - }) + var render = function(ext, data, cb) { + processors[ext].compile(srcPath, data, function(err, js) { + if (err) return cb(err) + + /** + * Consistently minify + */ + var post = minify.js(js, { + compress: false, + mangle: true + }) + cb(null, post) + }) + } + + if(helpers.needsBrowserify(data.toString())) { + var post = '', success = true + + var exceptionHandler = function(err) { + success = false + console.log(err.message) + render(ext, data, callback) + } + + process.once('uncaughtException', exceptionHandler) + browserify(filePath, {extensions: extensions}).transform(function(file) { + var result = '' + return through(write, end) + + function write(buf) { + result += buf + } + function end() { + if(success) { + var that = this + render(path.extname(file).replace(/^\./, '').toLowerCase(), result, function(err, data) { + that.queue(data) + that.queue(null) + }) + } + } + }).on('error', exceptionHandler).bundle() + .on('data', function(buf) { + if (success) { + post += buf + } + }).on('end', function() { + if (success) { + process.removeListener('uncaughtException', exceptionHandler) + callback(null, post) + } + }) + } + else { + render(ext, data, callback) + } }) diff --git a/lib/javascript/processors/es.js b/lib/javascript/processors/es.js new file mode 100644 index 000000000..4291f1541 --- /dev/null +++ b/lib/javascript/processors/es.js @@ -0,0 +1,3 @@ +exports.compile = function(filePath, fileContents, callback){ + callback(null, fileContents.toString()) +} diff --git a/package.json b/package.json index d74702f8f..a75514647 100644 --- a/package.json +++ b/package.json @@ -12,32 +12,72 @@ }, "author": "Brock Whitten ", "contributors": [ - { "name": "Brock Whitten", "email": "brock@chloi.io" }, - { "name": "Brian Donovan", "email": "donovan@squareup.com" }, - { "name": "Kenneth Ormandy", "email": "kenneth@chloi.io" }, - { "name": "Zhang Yichao", "email": "echaozh@gmail.com" }, - { "name": "Carlos Rodriguez" }, - { "name": "Zeke Sikelianos", "email": "zeke@sikelianos.com" }, - { "name": "Guilherme Rodrigues", "email": "gadr90@gmail.com" }, - { "name": "Radu Brehar", "email": "radu@jslog.com" }, - { "name": "Glen Maddern", "email": "glenmaddern@gmail.com" }, - { "name": "Jed Foster", "email": "jed@jedfoster.com" }, - { "name": "Sehrope Sarkuni", "email": "sehrope@jackdb.com" }, - { "name": "Keiichiro Matsumoto", "email": "matsumos@gmail.com" }, - { "name": "Najam Khn", "email": "najamkhn@gmail.com" } + { + "name": "Brock Whitten", + "email": "brock@chloi.io" + }, + { + "name": "Brian Donovan", + "email": "donovan@squareup.com" + }, + { + "name": "Kenneth Ormandy", + "email": "kenneth@chloi.io" + }, + { + "name": "Zhang Yichao", + "email": "echaozh@gmail.com" + }, + { + "name": "Carlos Rodriguez" + }, + { + "name": "Zeke Sikelianos", + "email": "zeke@sikelianos.com" + }, + { + "name": "Guilherme Rodrigues", + "email": "gadr90@gmail.com" + }, + { + "name": "Radu Brehar", + "email": "radu@jslog.com" + }, + { + "name": "Glen Maddern", + "email": "glenmaddern@gmail.com" + }, + { + "name": "Jed Foster", + "email": "jed@jedfoster.com" + }, + { + "name": "Sehrope Sarkuni", + "email": "sehrope@jackdb.com" + }, + { + "name": "Keiichiro Matsumoto", + "email": "matsumos@gmail.com" + }, + { + "name": "Najam Khn", + "email": "najamkhn@gmail.com" + } ], "license": "MIT", "dependencies": { - "lru-cache": "2.6.1", - "jade": "git://github.com/harp/jade#v1.9.3-bc.2", + "autoprefixer": "5.1.0", + "browserify": "^10.2.4", "coffee-script": "1.9.2", "ejs": "1.0.0", - "node-sass": "3.0.0-beta.5", - "marked": "0.3.3", + "jade": "git://github.com/harp/jade#v1.9.3-bc.2", "less": "2.5.0", - "stylus": "0.47.3", + "lru-cache": "2.6.1", + "marked": "0.3.3", "minify": "git://github.com/kennethormandy/minify#v0.3.0", - "autoprefixer": "5.1.0" + "node-sass": "3.0.0-beta.5", + "stylus": "0.47.3", + "through": "^2.3.7" }, "devDependencies": { "mocha": "1.8.2", diff --git a/test/fixtures/javascripts/browserify/Math.coffee b/test/fixtures/javascripts/browserify/Math.coffee new file mode 100644 index 000000000..ee5932f46 --- /dev/null +++ b/test/fixtures/javascripts/browserify/Math.coffee @@ -0,0 +1,4 @@ +# Let's see if we can mix .coffee & .es + +exports.pow = (num) -> + num * num diff --git a/test/fixtures/javascripts/browserify/Math.js b/test/fixtures/javascripts/browserify/Math.js new file mode 100644 index 000000000..c462e3352 --- /dev/null +++ b/test/fixtures/javascripts/browserify/Math.js @@ -0,0 +1,5 @@ +// Let's see if we can mix .es & .js + +exports.pow = function(num) { + return num * num; +}; diff --git a/test/fixtures/javascripts/browserify/comment.coffee b/test/fixtures/javascripts/browserify/comment.coffee new file mode 100644 index 000000000..a1fb7b864 --- /dev/null +++ b/test/fixtures/javascripts/browserify/comment.coffee @@ -0,0 +1,3 @@ +# pow = require('./Math').pow; + +console.log(pow(4)); diff --git a/test/fixtures/javascripts/browserify/comment.es b/test/fixtures/javascripts/browserify/comment.es new file mode 100644 index 000000000..93418d714 --- /dev/null +++ b/test/fixtures/javascripts/browserify/comment.es @@ -0,0 +1,5 @@ +/* + * pow = require('./Math').pow; + */ + +console.log(pow(4)); diff --git a/test/fixtures/javascripts/browserify/declared.coffee b/test/fixtures/javascripts/browserify/declared.coffee new file mode 100644 index 000000000..c209946aa --- /dev/null +++ b/test/fixtures/javascripts/browserify/declared.coffee @@ -0,0 +1,6 @@ +require = (file) -> + # custom implementation + +pow = require('./Math').pow + +console.log pow(4) diff --git a/test/fixtures/javascripts/browserify/declared.es b/test/fixtures/javascripts/browserify/declared.es new file mode 100644 index 000000000..40484a0fb --- /dev/null +++ b/test/fixtures/javascripts/browserify/declared.es @@ -0,0 +1,7 @@ +var require = function(file) { + // custom implementation +}; + +var pow = require('./Math').pow; + +console.log(pow(4)); diff --git a/test/fixtures/javascripts/browserify/require_coffee.coffee b/test/fixtures/javascripts/browserify/require_coffee.coffee new file mode 100644 index 000000000..43b6e2e87 --- /dev/null +++ b/test/fixtures/javascripts/browserify/require_coffee.coffee @@ -0,0 +1,3 @@ +pow = require('./Math.coffee').pow + +console.log pow(4) diff --git a/test/fixtures/javascripts/browserify/require_coffee.es b/test/fixtures/javascripts/browserify/require_coffee.es new file mode 100644 index 000000000..86a4bc2a3 --- /dev/null +++ b/test/fixtures/javascripts/browserify/require_coffee.es @@ -0,0 +1,3 @@ +var pow = require('./Math.coffee').pow; + +console.log(pow(4)); diff --git a/test/fixtures/javascripts/browserify/require_js.coffee b/test/fixtures/javascripts/browserify/require_js.coffee new file mode 100644 index 000000000..614e2afc8 --- /dev/null +++ b/test/fixtures/javascripts/browserify/require_js.coffee @@ -0,0 +1,3 @@ +pow = require('./Math.js').pow + +console.log pow(4) diff --git a/test/fixtures/javascripts/browserify/require_js.es b/test/fixtures/javascripts/browserify/require_js.es new file mode 100644 index 000000000..2d2e69f5e --- /dev/null +++ b/test/fixtures/javascripts/browserify/require_js.es @@ -0,0 +1,3 @@ +var pow = require('./Math.js').pow; + +console.log(pow(4)); diff --git a/test/javascripts.js b/test/javascripts.js index 432b16d35..707861573 100644 --- a/test/javascripts.js +++ b/test/javascripts.js @@ -41,5 +41,69 @@ describe("javascripts", function(){ }) }) + + describe("browserify", function() { + var root = __dirname + "/fixtures/javascripts/browserify" + var poly = polymer.root(root) + + process.chdir(root) + + it("should require coffeescript file in coffeescript", function(done) { + poly.render("require_coffee.coffee", function(errors, body) { + should.not.exist(errors) + body.should.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should require javascript file in coffeescript", function(done) { + poly.render("require_js.coffee", function(errors, body) { + should.not.exist(errors) + body.should.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should require coffeescript file in javascript", function(done) { + poly.render("require_coffee.es", function(errors, body) { + should.not.exist(errors) + body.should.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should require javascript file in javascript", function(done) { + poly.render("require_js.es", function(errors, body) { + should.not.exist(errors) + body.should.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should skip commented require in coffeescript", function(done) { + poly.render("comment.coffee", function(errors, body) { + should.not.exist(errors) + body.should.not.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should skip commented require in javascript", function(done) { + poly.render("comment.es", function(errors, body) { + should.not.exist(errors) + body.should.not.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should skip already declared require in coffeescript", function(done) { + poly.render("declared.coffee", function(errors, body) { + should.not.exist(errors) + body.should.not.include("MODULE_NOT_FOUND") + done() + }) + }) + it("should skip already declared require in javascript", function(done) { + poly.render("declared.es", function(errors, body) { + should.not.exist(errors) + body.should.not.include("MODULE_NOT_FOUND") + done() + }) + }) + }) })