├── .editorconfig ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── gulpfile.js ├── index.js ├── package-lock.json ├── package.json └── test ├── expected ├── main-define.js ├── main-windows.js ├── main.js ├── one.js ├── three.js └── two.js ├── fixtures ├── error.js ├── main-define.js ├── main.js ├── one.js ├── three.js └── two.js ├── test.js └── utils ├── compare.js ├── construct-buffer.js ├── expected.js ├── fixture.js ├── get-file.js └── test-stream.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [package.json] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.yml] 16 | indent_style = space 17 | indent_size = 2 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | .idea/ 4 | *.iml 5 | 6 | coverage/ 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # .gitignore contents 2 | /.idea/ 3 | *.iml 4 | 5 | # development-specific items 6 | .editorconfig 7 | .gitattributes 8 | .gitignore 9 | .npmignore 10 | .travis.yml 11 | gulpfile.js 12 | 13 | /coverage/ 14 | /test/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '4.0' 5 | 6 | script: npm run ci 7 | 8 | sudo: false 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jonathan Lounsbury 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 all 13 | 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 THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [gulp](http://gulpjs.com)-requirejs-optimize 2 | [![Build Status](https://travis-ci.org/jlouns/gulp-requirejs-optimize.svg?branch=master)](https://travis-ci.org/jlouns/gulp-requirejs-optimize) 3 | [![npm version](https://badge.fury.io/js/gulp-requirejs-optimize.svg)](http://badge.fury.io/js/gulp-requirejs-optimize) 4 | [![Coverage Status](https://coveralls.io/repos/jlouns/gulp-requirejs-optimize/badge.png)](https://coveralls.io/r/jlouns/gulp-requirejs-optimize) 5 | [![Dependency Status](https://david-dm.org/jlouns/gulp-requirejs-optimize.svg)](https://david-dm.org/jlouns/gulp-requirejs-optimize) 6 | 7 | Optimize AMD modules in javascript files using the requirejs optimizer. 8 | 9 | ## Install 10 | 11 | ```sh 12 | $ npm install --save-dev gulp-requirejs-optimize 13 | ``` 14 | 15 | ## Usage 16 | 17 | ### Simple 18 | 19 | ```js 20 | var gulp = require('gulp'); 21 | var requirejsOptimize = require('gulp-requirejs-optimize'); 22 | 23 | gulp.task('scripts', function () { 24 | return gulp.src('src/main.js') 25 | .pipe(requirejsOptimize()) 26 | .pipe(gulp.dest('dist')); 27 | }); 28 | ``` 29 | 30 | ### Custom options 31 | gulp-requirejs-optimize accepts almost all of the same options as [r.js optimize](https://github.com/jrburke/r.js/blob/master/build/example.build.js) (see below). 32 | 33 | ```js 34 | var gulp = require('gulp'); 35 | var requirejsOptimize = require('gulp-requirejs-optimize'); 36 | 37 | gulp.task('scripts', function () { 38 | return gulp.src('src/main.js') 39 | .pipe(requirejsOptimize({ 40 | optimize: 'none', 41 | insertRequire: ['foo/bar/bop'], 42 | })) 43 | .pipe(gulp.dest('dist')); 44 | }); 45 | ``` 46 | 47 | ### Multiple Modules 48 | Each file passed to the plugin is optimized as a separate module. 49 | 50 | ```js 51 | var gulp = require('gulp'); 52 | var requirejsOptimize = require('gulp-requirejs-optimize'); 53 | 54 | gulp.task('scripts', function () { 55 | return gulp.src('src/modules/*.js') 56 | .pipe(requirejsOptimize()) 57 | .pipe(gulp.dest('dist')); 58 | }); 59 | ``` 60 | 61 | ### Options generating function 62 | Options can also be specified in the form of an options-generating function to generate custom options for each file passed. This can be used to apply custom logic while optimizing multiple bundles or modules in an app. 63 | 64 | ```js 65 | var gulp = require('gulp'); 66 | var requirejsOptimize = require('gulp-requirejs-optimize'); 67 | 68 | gulp.task('scripts', function () { 69 | return gulp.src('src/modules/*.js') 70 | .pipe(requirejsOptimize(function(file) { 71 | return { 72 | name: '../vendor/bower/almond/almond', 73 | optimize: 'none', 74 | useStrict: true, 75 | baseUrl: 'path/to/base', 76 | include: 'subdir/' + file.relative 77 | }; 78 | })) 79 | .pipe(gulp.dest('dist')); 80 | }); 81 | ``` 82 | 83 | ### Sourcemaps support 84 | The plugin supports [gulp-sourcemaps](https://github.com/floridoo/gulp-sourcemaps) only if `preserveLicenseComments` is set to false, as described in the `r.js` docs. If `preserveLicenseComments` is not specified and the `gulp-sourcemaps` plugin is detected, the plugin will automatically set `preserveLicenseComments` to false. 85 | 86 | ```js 87 | var gulp = require('gulp'); 88 | var requirejsOptimize = require('gulp-requirejs-optimize'); 89 | var sourcemaps = require('gulp-sourcemaps'); 90 | 91 | gulp.task('scripts', function () { 92 | return gulp.src('src/main.js') 93 | .pipe(sourcemaps.init()) 94 | .pipe(requirejsOptimize()) 95 | .pipe(sourcemaps.write()) 96 | .pipe(gulp.dest('dist')); 97 | }); 98 | ``` 99 | 100 | ## API 101 | 102 | ### requirejsOptimize(options) 103 | 104 | #### options 105 | 106 | Options are the same as what is supported by the [r.js optimizer](https://github.com/jrburke/r.js/blob/master/build/example.build.js) except for `out`, `modules`, and `dir`. 107 | 108 | The options parameter can be specified as a static object or an options-generating function. Options-generating functions are passed a file object and are expected to generate an options object. 109 | 110 | ## Differences From r.js 111 | 112 | ### out 113 | r.js supports `out` as a string describing a path or a function which processes the output. Since we need to pass a virtual file as output, we only support the string version of `out`. 114 | 115 | ### modules and dir 116 | r.js supports an array of `modules` to optimize multiple modules at once, using the `dir` parameter for the output directory. The same thing can be accomplished with this plugin by passing the main file of each module as input to the plugin. `gulp.dest` can be used to specify the output directory. 117 | 118 | This means an r.js config file for optimizing multiple modules that looks like this: 119 | ```json 120 | { 121 | "baseUrl": "src/modules", 122 | "dir": "dist", 123 | "modules": [{ 124 | "name": "one" 125 | }, { 126 | "name": "two" 127 | }] 128 | } 129 | ``` 130 | 131 | Would look like this as a gulp task with this plugin: 132 | ```js 133 | gulp.task('scripts', function () { 134 | return gulp.src('src/modules/*.js') 135 | .pipe(requirejsOptimize()) 136 | .pipe(gulp.dest('dist')); 137 | }); 138 | ``` 139 | 140 | ## License 141 | 142 | MIT © [Jonathan Lounsbury](https://github.com/jlouns) 143 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var coveralls = require('gulp-coveralls'); 6 | var istanbul = require('gulp-istanbul'); 7 | var mocha = require('gulp-mocha'); 8 | var runSequence = require('run-sequence'); 9 | var xo = require('gulp-xo'); 10 | 11 | var paths = { 12 | scripts: 'index.js', 13 | tests: 'test/*.js' 14 | }; 15 | 16 | gulp.task('lint', function() { 17 | return gulp.src([paths.scripts, paths.tests, 'test/utils/*.js', 'gulpfile.js']) 18 | .pipe(xo()); 19 | }); 20 | 21 | gulp.task('pre-test', function() { 22 | return gulp.src(paths.scripts) 23 | .pipe(istanbul()) 24 | .pipe(istanbul.hookRequire()); 25 | }); 26 | 27 | gulp.task('test', ['pre-test'], function() { 28 | return gulp.src(paths.tests) 29 | .pipe(mocha()) 30 | .pipe(istanbul.writeReports()); 31 | }); 32 | 33 | gulp.task('coveralls', function() { 34 | return gulp.src('coverage/lcov.info') 35 | .pipe(coveralls()); 36 | }); 37 | 38 | gulp.task('ci', function(done) { 39 | runSequence('lint', 'test', 'coveralls', done); 40 | }); 41 | 42 | gulp.task('watch', function() { 43 | gulp.watch(paths.scripts, ['lint', 'test']); 44 | }); 45 | 46 | gulp.task('default', ['lint', 'test']); 47 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | var defaults = require('lodash.defaults'); 6 | var through = require('through2'); 7 | var requirejs = require('requirejs'); 8 | var chalk = require('chalk'); 9 | var Vinyl = require('vinyl'); 10 | var log = require('fancy-log'); 11 | var PluginError = require('plugin-error'); 12 | var applySourceMap = require('vinyl-sourcemaps-apply'); 13 | 14 | var PLUGIN_NAME = 'gulp-requirejs-optimize'; 15 | 16 | function pathToModuleId(path) { 17 | // replace Windows path separators to make sure this is a valid module ID 18 | path = path.replace(/\\/g, '/'); 19 | 20 | // remove the file extension if this is a .js file 21 | var filenameEndIndex = path.length - 3; 22 | var extensionIndex = path.indexOf('.js', filenameEndIndex); 23 | if (extensionIndex !== -1 && extensionIndex === filenameEndIndex) { 24 | path = path.substring(0, filenameEndIndex); 25 | } 26 | 27 | return path; 28 | } 29 | 30 | module.exports = function(options) { 31 | requirejs.define('node/print', [], function() { 32 | return function(msg) { 33 | if (msg.substring(0, 5) === 'Error') { 34 | log(chalk.red(msg)); 35 | } else { 36 | log(msg); 37 | } 38 | }; 39 | }); 40 | 41 | options = options || {}; 42 | 43 | var generateOptions; 44 | if (typeof options === 'function') { 45 | generateOptions = options; 46 | } else { 47 | generateOptions = function() { 48 | return options; 49 | }; 50 | } 51 | 52 | var error; 53 | 54 | return through.obj(function(file, enc, cb) { 55 | if (file.isNull()) { 56 | cb(null, file); 57 | return; 58 | } 59 | 60 | if (file.isStream()) { 61 | cb(new PluginError(PLUGIN_NAME, 'Streaming not supported')); 62 | return; 63 | } 64 | 65 | var optimizeOptions = generateOptions(file); 66 | if (typeof optimizeOptions !== 'object') { 67 | cb(new PluginError(PLUGIN_NAME, 'Options function must produce an options object')); 68 | return; 69 | } 70 | 71 | var sourceMapPresent = Boolean(file.sourceMap); 72 | var logLevelPresent = Boolean(optimizeOptions.logLevel); 73 | 74 | optimizeOptions = defaults({}, optimizeOptions, { 75 | logLevel: 2, 76 | baseUrl: file.base, 77 | out: file.relative, 78 | generateSourceMaps: sourceMapPresent 79 | }); 80 | 81 | if (optimizeOptions.generateSourceMaps) { 82 | defaults(optimizeOptions, { 83 | preserveLicenseComments: false 84 | }); 85 | } 86 | 87 | if (!optimizeOptions.include && !optimizeOptions.name) { 88 | optimizeOptions.include = pathToModuleId(file.relative); 89 | } 90 | 91 | if (typeof optimizeOptions.out !== 'string') { 92 | cb(new PluginError(PLUGIN_NAME, 'If `out` is supplied, it must be a string')); 93 | return; 94 | } 95 | 96 | var out = optimizeOptions.out; 97 | optimizeOptions.out = function(text, sourceMapText) { 98 | if (sourceMapPresent) { 99 | // uglify adds its own sourceMappingURL comment which will get duplicated by gulp-sourcemaps 100 | text = text.replace(/\/\/# sourceMappingURL=.*$/, ''); 101 | } 102 | 103 | var outfile = new Vinyl({ 104 | path: out, 105 | contents: new Buffer(text) 106 | }); 107 | 108 | if (sourceMapText) { 109 | applySourceMap(outfile, sourceMapText); 110 | } 111 | 112 | cb(null, outfile); 113 | }; 114 | 115 | var target; 116 | if (optimizeOptions.logLevel < 2) { 117 | target = path.resolve(file.path); 118 | } else { 119 | target = file.relative; 120 | } 121 | 122 | if (!logLevelPresent || optimizeOptions.logLevel < 2) { 123 | log('Optimizing ' + chalk.magenta(target)); 124 | } 125 | requirejs.optimize(optimizeOptions, null, function(err) { 126 | error = err; 127 | cb(); 128 | }); 129 | }, function(cb) { 130 | if (error) { 131 | cb(new PluginError(PLUGIN_NAME, error)); 132 | } 133 | 134 | cb(); 135 | }); 136 | }; 137 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-requirejs-optimize", 3 | "version": "1.3.0", 4 | "description": "RequireJS optimizer plugin for gulp", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "license": "MIT", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/jlouns/gulp-requirejs-optimize.git" 13 | }, 14 | "author": { 15 | "name": "Jonathan Lounsbury", 16 | "email": "jlouns@gmail.com", 17 | "url": "https://github.com/jlouns" 18 | }, 19 | "engines": { 20 | "node": ">=4.0" 21 | }, 22 | "dependencies": { 23 | "chalk": "^2.3.2", 24 | "fancy-log": "^1.3.2", 25 | "lodash.defaults": "^4.0.1", 26 | "plugin-error": "^1.0.1", 27 | "requirejs": "^2.2.0", 28 | "through2": "^2.0.1", 29 | "vinyl": "^2.1.0", 30 | "vinyl-sourcemaps-apply": "^0.2.1" 31 | }, 32 | "devDependencies": { 33 | "gulp": "^3.9.1", 34 | "gulp-coveralls": "^0.1.4", 35 | "gulp-istanbul": "^1.0.0", 36 | "gulp-mocha": "^3.0.1", 37 | "gulp-xo": "^0.17.1", 38 | "run-sequence": "^2.2.1", 39 | "should": "^13.2.1" 40 | }, 41 | "scripts": { 42 | "test": "gulp test", 43 | "ci": "gulp ci" 44 | }, 45 | "keywords": [ 46 | "gulpplugin" 47 | ], 48 | "xo": { 49 | "globals": [ 50 | "define" 51 | ], 52 | "rules": { 53 | "space-before-function-paren": [ 54 | "error", 55 | "never" 56 | ], 57 | "babel/object-curly-spacing": [ 58 | "error", 59 | "always", 60 | { 61 | "objectsInObjects": false, 62 | "arraysInObjects": false 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/expected/main-define.js: -------------------------------------------------------------------------------- 1 | define("three",[],function(){}),define("one",["./three"],function(){}),define("two",[],function(){}),define("main-define",["./one","./two"],function(){}); 2 | -------------------------------------------------------------------------------- /test/expected/main-windows.js: -------------------------------------------------------------------------------- 1 | define("test/fixtures/three",[],function(){}),define("test/fixtures/one",["./three"],function(){}),define("test/fixtures/two",[],function(){}),require(["./one","./two"],function(){}),define("test/fixtures/main",function(){}); 2 | -------------------------------------------------------------------------------- /test/expected/main.js: -------------------------------------------------------------------------------- 1 | define("three",[],function(){}),define("one",["./three"],function(){}),define("two",[],function(){}),require(["./one","./two"],function(){}),define("main",function(){}); 2 | -------------------------------------------------------------------------------- /test/expected/one.js: -------------------------------------------------------------------------------- 1 | define("three",[],function(){}),define("one",["./three"],function(){}); 2 | -------------------------------------------------------------------------------- /test/expected/three.js: -------------------------------------------------------------------------------- 1 | define("three",[],function(){}); 2 | -------------------------------------------------------------------------------- /test/expected/two.js: -------------------------------------------------------------------------------- 1 | define("two",[],function(){}); 2 | -------------------------------------------------------------------------------- /test/fixtures/error.js: -------------------------------------------------------------------------------- 1 | require(['./nonexistent'], function() { }); 2 | -------------------------------------------------------------------------------- /test/fixtures/main-define.js: -------------------------------------------------------------------------------- 1 | define(['./one', './two'], function() { }); 2 | -------------------------------------------------------------------------------- /test/fixtures/main.js: -------------------------------------------------------------------------------- 1 | require(['./one', './two'], function() { }); 2 | -------------------------------------------------------------------------------- /test/fixtures/one.js: -------------------------------------------------------------------------------- 1 | define(['./three'], function() { }); 2 | -------------------------------------------------------------------------------- /test/fixtures/three.js: -------------------------------------------------------------------------------- 1 | define([], function() { }); -------------------------------------------------------------------------------- /test/fixtures/two.js: -------------------------------------------------------------------------------- 1 | define([], function() { }); -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | 6 | var should = require('should'); 7 | var Vinyl = require('vinyl'); 8 | var requirejsOptimize = require('../'); 9 | 10 | var fixture = require('./utils/fixture'); 11 | var expected = require('./utils/expected'); 12 | 13 | var constructBuffer = require('./utils/construct-buffer'); 14 | 15 | var compare = require('./utils/compare'); 16 | 17 | var testStream = require('./utils/test-stream'); 18 | 19 | describe('gulp-requirejs-optimize', function() { 20 | it('should accept no options', function(done) { 21 | var stream = requirejsOptimize(); 22 | 23 | testStream(stream, 'main.js', 'main.js', done); 24 | }); 25 | 26 | it('should accept options object', function(done) { 27 | var stream = requirejsOptimize({ 28 | logLevel: 1 29 | }); 30 | 31 | testStream(stream, 'main.js', 'main.js', done); 32 | }); 33 | 34 | it('should accept options function', function(done) { 35 | var stream = requirejsOptimize(function() { 36 | return { }; 37 | }); 38 | 39 | testStream(stream, 'main.js', 'main.js', done); 40 | }); 41 | 42 | it('should accept name parameter', function(done) { 43 | var stream = requirejsOptimize({ 44 | name: 'main-define' 45 | }); 46 | 47 | testStream(stream, 'main-define.js', 'main-define.js', done); 48 | }); 49 | 50 | it('should pass through null file', function(done) { 51 | var stream = requirejsOptimize(); 52 | 53 | var buffer = constructBuffer(stream); 54 | 55 | stream.on('end', function() { 56 | try { 57 | buffer.should.have.length(1); 58 | 59 | var output = buffer[0]; 60 | 61 | output.isNull().should.be.true(); 62 | 63 | done(); 64 | } catch (err) { 65 | done(err); 66 | } 67 | }); 68 | 69 | stream.write(new Vinyl()); 70 | 71 | stream.end(); 72 | }); 73 | 74 | it('should error on stream file', function(done) { 75 | var stream = requirejsOptimize(); 76 | var contentStream = requirejsOptimize(); 77 | 78 | stream.on('error', function(err) { 79 | try { 80 | err.message.should.equal('Streaming not supported'); 81 | done(); 82 | } catch (err) { 83 | done(err); 84 | } 85 | }); 86 | 87 | stream.write(new Vinyl({ 88 | contents: contentStream 89 | })); 90 | }); 91 | 92 | it('should accept out filename', function(done) { 93 | var outpath = 'different/path/out.js'; 94 | 95 | var stream = requirejsOptimize({ 96 | out: outpath 97 | }); 98 | 99 | var buffer = constructBuffer(stream); 100 | 101 | stream.on('end', function() { 102 | try { 103 | buffer.should.have.length(1); 104 | 105 | var output = buffer[0]; 106 | 107 | output.relative.replace(/\\/g, '/').should.equal(outpath); 108 | compare(output, expected('main.js')); 109 | 110 | done(); 111 | } catch (err) { 112 | done(err); 113 | } 114 | }); 115 | 116 | stream.write(fixture('main.js')); 117 | 118 | stream.end(); 119 | }); 120 | 121 | it('should accept a non .js file', function(done) { 122 | var stream = requirejsOptimize({ 123 | out: 'main.js' 124 | }); 125 | 126 | var fixtureSupplier = function() { 127 | var input = fixture('main.js'); 128 | input.path = path.join('test', 'fixtures', 'main'); 129 | return input; 130 | }; 131 | 132 | testStream(stream, fixtureSupplier, 'main.js', done); 133 | }); 134 | 135 | it('should accept Windows paths', function(done) { 136 | var stream = requirejsOptimize({ 137 | out: 'main-windows.js' 138 | }); 139 | 140 | var fixtureSupplier = function() { 141 | var input = fixture('main.js'); 142 | input.base = '.'; 143 | input.path = path.join('test', 'fixtures', 'main.js').replace(/\//g, '\\'); 144 | return input; 145 | }; 146 | 147 | testStream(stream, fixtureSupplier, 'main-windows.js', done); 148 | }); 149 | 150 | it('should not accept out function', function(done) { 151 | var stream = requirejsOptimize({ 152 | out: function() { } 153 | }); 154 | 155 | stream.on('error', function(err) { 156 | try { 157 | err.message.should.equal('If `out` is supplied, it must be a string'); 158 | done(); 159 | } catch (err) { 160 | done(err); 161 | } 162 | }); 163 | 164 | stream.write(fixture('main.js')); 165 | }); 166 | 167 | it('should error on invalid options function', function(done) { 168 | var stream = requirejsOptimize(function() { 169 | return function() { }; 170 | }); 171 | 172 | stream.on('error', function(err) { 173 | try { 174 | err.message.should.equal('Options function must produce an options object'); 175 | done(); 176 | } catch (err) { 177 | done(err); 178 | } 179 | }); 180 | 181 | stream.write(fixture('main.js')); 182 | }); 183 | 184 | it('should emit errors from requirejs', function(done) { 185 | var stream = requirejsOptimize(); 186 | 187 | stream.write(fixture('error.js')); 188 | 189 | stream.on('error', function() { 190 | done(); 191 | }); 192 | 193 | stream.end(); 194 | }); 195 | 196 | it('should optimize multiple files', function(done) { 197 | var stream = requirejsOptimize(); 198 | 199 | var count = 0; 200 | 201 | var filenames = ['one.js', 'two.js', 'three.js']; 202 | 203 | stream.on('data', function(file) { 204 | try { 205 | count++; 206 | filenames.should.containEql(file.relative); 207 | compare(file, expected(file.relative)); 208 | 209 | if (count === 2) { 210 | done(); 211 | } 212 | } catch (err) { 213 | done(err); 214 | } 215 | }); 216 | 217 | filenames.forEach(function(filename) { 218 | stream.write(fixture(filename)); 219 | }); 220 | }); 221 | 222 | it('should support gulp-sourcemaps', function(done) { 223 | var stream = requirejsOptimize(); 224 | 225 | var buffer = constructBuffer(stream); 226 | 227 | stream.on('end', function() { 228 | try { 229 | buffer.should.have.length(1); 230 | 231 | var output = buffer[0]; 232 | 233 | should.exist(output.sourceMap); 234 | 235 | output.sourceMap.should 236 | .have.property('sources') 237 | .which.is.an.Array() 238 | .and.has.lengthOf(4); 239 | 240 | output.sourceMap.should 241 | .have.property('sourcesContent') 242 | .which.is.an.Array() 243 | .and.has.lengthOf(4); 244 | 245 | output.sourceMap.sources[0].should.equal('three.js'); 246 | output.sourceMap.sources[1].should.equal('one.js'); 247 | output.sourceMap.sources[2].should.equal('two.js'); 248 | output.sourceMap.sources[3].should.equal('main.js'); 249 | 250 | String(output.contents).should.not.containEql('sourceMappingURL'); 251 | 252 | done(); 253 | } catch (err) { 254 | done(err); 255 | } 256 | }); 257 | 258 | var file = fixture('main.js'); 259 | file.sourceMap = {}; 260 | 261 | stream.write(file); 262 | 263 | stream.end(); 264 | }); 265 | }); 266 | -------------------------------------------------------------------------------- /test/utils/compare.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('should'); 4 | 5 | module.exports = function compare(actual, expected) { 6 | String(actual.contents).trim().should.equal(String(expected.contents).trim()); 7 | }; 8 | -------------------------------------------------------------------------------- /test/utils/construct-buffer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function constructBuffer(stream) { 4 | var buffer = []; 5 | 6 | stream.on('data', function(file) { 7 | buffer.push(file); 8 | }); 9 | 10 | return buffer; 11 | }; 12 | -------------------------------------------------------------------------------- /test/utils/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | var getFile = require('./get-file'); 6 | 7 | module.exports = function expected(filepath) { 8 | return getFile(path.join('test', 'expected', filepath)); 9 | }; 10 | -------------------------------------------------------------------------------- /test/utils/fixture.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | var getFile = require('./get-file'); 6 | 7 | module.exports = function fixture(filepath) { 8 | return getFile(path.join('test', 'fixtures', filepath)); 9 | }; 10 | -------------------------------------------------------------------------------- /test/utils/get-file.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | 6 | var Vinyl = require('vinyl'); 7 | 8 | module.exports = function getFile(filepath) { 9 | return new Vinyl({ 10 | base: path.dirname(filepath), 11 | path: filepath, 12 | cwd: './test/', 13 | contents: fs.readFileSync(filepath) 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /test/utils/test-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('should'); 4 | 5 | var fixture = require('./fixture'); 6 | var expected = require('./expected'); 7 | 8 | var constructBuffer = require('./construct-buffer'); 9 | 10 | var compare = require('./compare'); 11 | 12 | module.exports = function testStream(stream, fixtureSupplier, expectedName, done) { 13 | var buffer = constructBuffer(stream); 14 | 15 | stream.on('end', function() { 16 | buffer.should.have.length(1); 17 | 18 | var output = buffer[0]; 19 | 20 | output.relative.should.equal(expectedName); 21 | compare(output, expected(expectedName)); 22 | 23 | done(); 24 | }); 25 | 26 | if (typeof fixtureSupplier === 'string') { 27 | fixtureSupplier = fixture.bind(null, fixtureSupplier); 28 | } 29 | 30 | stream.write(fixtureSupplier()); 31 | 32 | stream.end(); 33 | }; 34 | --------------------------------------------------------------------------------