├── .gitattributes ├── lib ├── isNull.js ├── noop.js ├── env.js ├── isStream.js ├── isBuffer.js ├── combine.js ├── buffer.js ├── log.js ├── template.js └── PluginError.js ├── .github ├── FUNDING.yml └── security.md ├── .gitignore ├── test ├── linefeed.js ├── colors.js ├── env.js ├── isBuffer.js ├── isStream.js ├── isNull.js ├── date.js ├── beep.js ├── noop.js ├── buffer.js ├── replaceExtension.js ├── combine.js ├── log.js ├── File.js ├── template.js └── PluginError.js ├── .travis.yml ├── .jshintrc ├── .editorconfig ├── index.js ├── LICENSE ├── package.json └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /lib/isNull.js: -------------------------------------------------------------------------------- 1 | module.exports = function(v) { 2 | return v === null; 3 | }; 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [phated] 2 | tidelift: npm/gulp-util 3 | open_collective: gulpjs 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.log 3 | node_modules 4 | build 5 | *.node 6 | components 7 | coverage 8 | -------------------------------------------------------------------------------- /lib/noop.js: -------------------------------------------------------------------------------- 1 | var through = require('through2'); 2 | 3 | module.exports = function () { 4 | return through.obj(); 5 | }; 6 | -------------------------------------------------------------------------------- /lib/env.js: -------------------------------------------------------------------------------- 1 | var parseArgs = require('minimist'); 2 | var argv = parseArgs(process.argv.slice(2)); 3 | 4 | module.exports = argv; 5 | -------------------------------------------------------------------------------- /lib/isStream.js: -------------------------------------------------------------------------------- 1 | var Stream = require('stream').Stream; 2 | 3 | module.exports = function(o) { 4 | return !!o && o instanceof Stream; 5 | }; 6 | -------------------------------------------------------------------------------- /test/linefeed.js: -------------------------------------------------------------------------------- 1 | /* 2 | var util = require('..'); 3 | var should = require('should'); 4 | var path = require('path'); 5 | require('mocha'); 6 | */ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "iojs" 5 | - "0.12" 6 | - "0.10" 7 | after_script: 8 | - npm run coveralls 9 | git: 10 | depth: 10 11 | -------------------------------------------------------------------------------- /.github/security.md: -------------------------------------------------------------------------------- 1 | ## Security contact information 2 | 3 | To report a security vulnerability, please use the 4 | [Tidelift security contact](https://tidelift.com/security). 5 | Tidelift will coordinate the fix and disclosure. 6 | -------------------------------------------------------------------------------- /lib/isBuffer.js: -------------------------------------------------------------------------------- 1 | var buf = require('buffer'); 2 | var Buffer = buf.Buffer; 3 | 4 | // could use Buffer.isBuffer but this is the same exact thing... 5 | module.exports = function(o) { 6 | return typeof o === 'object' && o instanceof Buffer; 7 | }; 8 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "eqeqeq": true, 4 | "expr": true, 5 | "latedef": true, 6 | "newcap": true, 7 | "quotmark": "single", 8 | "regexp": true, 9 | "undef": true, 10 | "unused": true, 11 | "node": true, 12 | "mocha": true 13 | } 14 | -------------------------------------------------------------------------------- /test/colors.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | require('should'); 3 | require('mocha'); 4 | 5 | describe('colors', function(){ 6 | it('should be a chalk instance', function(done){ 7 | util.colors.should.equal(require('chalk')); 8 | done(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | end_of_line = lf 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /test/env.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | require('mocha'); 4 | 5 | describe('env', function(){ 6 | it('should exist', function(done){ 7 | should.exist(util.env); 8 | should.exist(util.env._); 9 | done(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /lib/combine.js: -------------------------------------------------------------------------------- 1 | var pipeline = require('multipipe'); 2 | 3 | module.exports = function(){ 4 | var args = arguments; 5 | if (args.length === 1 && Array.isArray(args[0])) { 6 | args = args[0]; 7 | } 8 | return function(){ 9 | return pipeline.apply(pipeline, args); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /lib/buffer.js: -------------------------------------------------------------------------------- 1 | var through = require('through2'); 2 | 3 | module.exports = function(fn) { 4 | var buf = []; 5 | var end = function(cb) { 6 | this.push(buf); 7 | cb(); 8 | if(fn) fn(null, buf); 9 | }; 10 | var push = function(data, enc, cb) { 11 | buf.push(data); 12 | cb(); 13 | }; 14 | return through.obj(push, end); 15 | }; 16 | -------------------------------------------------------------------------------- /test/isBuffer.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var through = require('through2'); 3 | require('should'); 4 | require('mocha'); 5 | 6 | describe('isBuffer()', function(){ 7 | it('should work on a buffer', function(done){ 8 | util.isBuffer(new Buffer('huh')).should.equal(true); 9 | done(); 10 | }); 11 | it('should not work on a stream', function(done){ 12 | util.isBuffer(through()).should.equal(false); 13 | done(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/isStream.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var through = require('through2'); 3 | require('should'); 4 | require('mocha'); 5 | 6 | describe('isStream()', function(){ 7 | it('should work on a stream', function(done){ 8 | util.isStream(through()).should.equal(true); 9 | done(); 10 | }); 11 | it('should not work on a buffer', function(done){ 12 | util.isStream(new Buffer('huh')).should.equal(false); 13 | done(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /lib/log.js: -------------------------------------------------------------------------------- 1 | var hasGulplog = require('has-gulplog'); 2 | 3 | module.exports = function(){ 4 | if(hasGulplog()){ 5 | // specifically deferring loading here to keep from registering it globally 6 | var gulplog = require('gulplog'); 7 | gulplog.info.apply(gulplog, arguments); 8 | } else { 9 | // specifically defering loading because it might not be used 10 | var fancylog = require('fancy-log'); 11 | fancylog.apply(null, arguments); 12 | } 13 | return this; 14 | }; 15 | -------------------------------------------------------------------------------- /test/isNull.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var through = require('through2'); 3 | require('should'); 4 | require('mocha'); 5 | 6 | describe('isNull()', function(){ 7 | it('should work on a null', function(done){ 8 | util.isNull(null).should.equal(true); 9 | done(); 10 | }); 11 | it('should not work on a stream', function(done){ 12 | util.isNull(through()).should.equal(false); 13 | done(); 14 | }); 15 | it('should not work on undefined', function(done){ 16 | util.isNull(undefined).should.equal(false); 17 | done(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/date.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | require('should'); 3 | require('mocha'); 4 | 5 | describe('date', function() { 6 | it('should be a date format instance', function(done) { 7 | util.date.should.equal(require('dateformat')); 8 | done(); 9 | }); 10 | it('should return today\'s date', function(done) { 11 | var time = new Date(); 12 | var dateutil = util.date('HH:MM:ss'); 13 | dateutil.should.equal(('0' + time.getHours()).slice(-2) + ':' + ('0' + time.getMinutes()).slice(-2) + ':' + ('0' + time.getSeconds()).slice(-2)); 14 | done(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/beep.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | require('should'); 3 | require('mocha'); 4 | 5 | describe('beep()', function(){ 6 | it('should send the right code to stdout', function(done){ 7 | var writtenValue; 8 | 9 | // Stub process.stdout.write 10 | var stdout_write = process.stdout.write; 11 | process.stdout.write = function(value) { 12 | writtenValue = value; 13 | }; 14 | 15 | util.beep(); 16 | writtenValue.should.equal('\x07'); 17 | 18 | // Restore process.stdout.write 19 | process.stdout.write = stdout_write; 20 | done(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | File: require('vinyl'), 3 | replaceExtension: require('replace-ext'), 4 | colors: require('chalk'), 5 | date: require('dateformat'), 6 | log: require('./lib/log'), 7 | template: require('./lib/template'), 8 | env: require('./lib/env'), 9 | beep: require('beeper'), 10 | noop: require('./lib/noop'), 11 | isStream: require('./lib/isStream'), 12 | isBuffer: require('./lib/isBuffer'), 13 | isNull: require('./lib/isNull'), 14 | linefeed: '\n', 15 | combine: require('./lib/combine'), 16 | buffer: require('./lib/buffer'), 17 | PluginError: require('./lib/PluginError') 18 | }; 19 | -------------------------------------------------------------------------------- /test/noop.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | var es = require('event-stream'); 4 | require('mocha'); 5 | 6 | describe('noop()', function(){ 7 | it('should return a stream', function(done){ 8 | util.isStream(util.noop()).should.equal(true); 9 | done(); 10 | }); 11 | it('should return a stream that passes through all data', function(done){ 12 | var inp = [1,2,3,4,5,6,7,8,9]; 13 | var stream = util.noop(); 14 | es.readArray(inp) 15 | .pipe(stream) 16 | .pipe(es.writeArray(function(err, arr){ 17 | should.not.exist(err); 18 | should.exist(arr); 19 | arr.should.eql(inp); 20 | done(); 21 | })); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /lib/template.js: -------------------------------------------------------------------------------- 1 | var template = require('lodash.template'); 2 | var reEscape = require('lodash._reescape'); 3 | var reEvaluate = require('lodash._reevaluate'); 4 | var reInterpolate = require('lodash._reinterpolate'); 5 | 6 | var forcedSettings = { 7 | escape: reEscape, 8 | evaluate: reEvaluate, 9 | interpolate: reInterpolate 10 | }; 11 | 12 | module.exports = function(tmpl, data) { 13 | var fn = template(tmpl, forcedSettings); 14 | 15 | var wrapped = function(o) { 16 | if (typeof o === 'undefined' || typeof o.file === 'undefined') { 17 | throw new Error('Failed to provide the current file as "file" to the template'); 18 | } 19 | return fn(o); 20 | }; 21 | 22 | return (data ? wrapped(data) : wrapped); 23 | }; 24 | -------------------------------------------------------------------------------- /test/buffer.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | var es = require('event-stream'); 4 | require('mocha'); 5 | 6 | describe('buffer()', function(){ 7 | it('should buffer stuff and return an array into the callback', function(done){ 8 | var src = [1,2,3]; 9 | var inp = es.readArray(src); 10 | inp.pipe(util.buffer(function(err, data){ 11 | should.not.exist(err); 12 | should.exist(data); 13 | data.should.eql(src); 14 | done(); 15 | })); 16 | }); 17 | it('should buffer stuff and emit it as a data event', function(done){ 18 | var src = [1,2,3]; 19 | var inp = es.readArray(src); 20 | inp.pipe(util.buffer()).on('data', function(data){ 21 | should.exist(data); 22 | data.should.eql(src); 23 | done(); 24 | }); 25 | }); 26 | it('should buffer stuff and return a stream with the buffered data', function(done){ 27 | var src = [1,2,3]; 28 | var inp = es.readArray(src); 29 | inp.pipe(util.buffer()).pipe(es.through(function(data) { 30 | should.exist(data); 31 | data.should.eql(src); 32 | done(); 33 | })); 34 | }); 35 | }); -------------------------------------------------------------------------------- /test/replaceExtension.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | var path = require('path'); 4 | require('mocha'); 5 | 6 | describe('replaceExtension()', function() { 7 | it('should return a valid replaced extension on nested', function(done) { 8 | var fname = path.join(__dirname, './fixtures/test.coffee'); 9 | var expected = path.join(__dirname, './fixtures/test.js'); 10 | var nu = util.replaceExtension(fname, '.js'); 11 | should.exist(nu); 12 | nu.should.equal(expected); 13 | done(); 14 | }); 15 | 16 | it('should return a valid replaced extension on flat', function(done) { 17 | var fname = 'test.coffee'; 18 | var expected = 'test.js'; 19 | var nu = util.replaceExtension(fname, '.js'); 20 | should.exist(nu); 21 | nu.should.equal(expected); 22 | done(); 23 | }); 24 | 25 | it('should not return a valid replaced extension on empty string', function(done) { 26 | var fname = ''; 27 | var expected = ''; 28 | var nu = util.replaceExtension(fname, '.js'); 29 | should.exist(nu); 30 | nu.should.equal(expected); 31 | done(); 32 | }); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Fractal 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/combine.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | var es = require('event-stream'); 4 | var Stream = require('stream'); 5 | require('mocha'); 6 | 7 | describe('combine()', function(){ 8 | it('should return a function', function(done){ 9 | var src = [1,2,3]; 10 | var inp = es.readArray(src); 11 | var factory = util.combine(inp); 12 | factory.should.be.type('function'); 13 | done(); 14 | }); 15 | it('should return a function that returns a stream combination', function(done){ 16 | var src = [1,2,3]; 17 | var inp = es.readArray(src); 18 | var inp2 = es.writeArray(function(err, data){ 19 | should.not.exist(err); 20 | data.should.eql(src); 21 | done(); 22 | }); 23 | var factory = util.combine(inp, inp2); 24 | factory().should.be.instanceof(Stream); 25 | }); 26 | it('should return a function that returns a stream combination when given an array', function(done){ 27 | var src = [1,2,3]; 28 | var inp = es.readArray(src); 29 | var inp2 = es.writeArray(function(err, data){ 30 | should.not.exist(err); 31 | data.should.eql(src); 32 | done(); 33 | }); 34 | var factory = util.combine([inp, inp2]); 35 | factory().should.be.instanceof(Stream); 36 | }); 37 | }); -------------------------------------------------------------------------------- /test/log.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | require('should'); 3 | require('mocha'); 4 | 5 | describe('log()', function(){ 6 | it('should work i guess', function(done){ 7 | var count = 0; 8 | var writtenValue = ''; 9 | 10 | // Stub process.stdout.write 11 | var stdout_write = process.stdout.write; 12 | process.stdout.write = function(value) { 13 | writtenValue += value; 14 | if(++count > 2){ 15 | // Restore process.stdout.write after test 16 | process.stdout.write = stdout_write; 17 | } 18 | }; 19 | 20 | util.log(1, 2, 3, 4, 'five'); 21 | var time = util.date(new Date(), 'HH:MM:ss'); 22 | writtenValue.should.eql('[' + util.colors.grey(time) + '] 1 2 3 4 \'five\'\n'); 23 | 24 | done(); 25 | }); 26 | 27 | it('should accept formatting', function(done){ 28 | var count = 0; 29 | var writtenValue = ''; 30 | 31 | // Stub process.stdout.write 32 | var stdout_write = process.stdout.write; 33 | process.stdout.write = function(value) { 34 | writtenValue += value; 35 | if(++count > 2){ 36 | // Restore process.stdout.write after test 37 | process.stdout.write = stdout_write; 38 | } 39 | }; 40 | 41 | util.log('%s %d %j', 'something', 0.1, {key: 'value'}); 42 | var time = util.date(new Date(), 'HH:MM:ss'); 43 | writtenValue.should.eql( 44 | '[' + util.colors.grey(time) + '] '+ 45 | 'something 0.1 {\"key\":\"value\"}\n' 46 | ); 47 | 48 | done(); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-util", 3 | "description": "Utility functions for gulp plugins", 4 | "version": "3.0.8", 5 | "repository": "gulpjs/gulp-util", 6 | "author": "Fractal (http://wearefractal.com/)", 7 | "files": [ 8 | "index.js", 9 | "lib" 10 | ], 11 | "dependencies": { 12 | "array-differ": "^1.0.0", 13 | "array-uniq": "^1.0.2", 14 | "beeper": "^1.0.0", 15 | "chalk": "^1.0.0", 16 | "dateformat": "^2.0.0", 17 | "fancy-log": "^1.1.0", 18 | "gulplog": "^1.0.0", 19 | "has-gulplog": "^0.1.0", 20 | "lodash._reescape": "^3.0.0", 21 | "lodash._reevaluate": "^3.0.0", 22 | "lodash._reinterpolate": "^3.0.0", 23 | "lodash.template": "^3.0.0", 24 | "minimist": "^1.1.0", 25 | "multipipe": "^0.1.2", 26 | "object-assign": "^3.0.0", 27 | "replace-ext": "0.0.1", 28 | "through2": "^2.0.0", 29 | "vinyl": "^0.5.0" 30 | }, 31 | "devDependencies": { 32 | "buffer-equal": "^0.0.1", 33 | "coveralls": "^2.11.2", 34 | "event-stream": "^3.1.7", 35 | "istanbul": "^0.3.5", 36 | "istanbul-coveralls": "^1.0.1", 37 | "jshint": "^2.5.11", 38 | "lodash.templatesettings": "^3.0.0", 39 | "mocha": "^2.0.1", 40 | "rimraf": "^2.2.8", 41 | "should": "^7.0.1" 42 | }, 43 | "scripts": { 44 | "test": "jshint *.js lib/*.js test/*.js && mocha", 45 | "coveralls": "istanbul cover _mocha --report lcovonly && istanbul-coveralls" 46 | }, 47 | "engines": { 48 | "node": ">=0.10" 49 | }, 50 | "license": "MIT" 51 | } 52 | -------------------------------------------------------------------------------- /test/File.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | var path = require('path'); 4 | require('mocha'); 5 | 6 | describe('File()', function() { 7 | it('should return a valid file', function(done) { 8 | var fname = path.join(__dirname, './fixtures/test.coffee'); 9 | var base = path.join(__dirname, './fixtures/'); 10 | var file = new util.File({ 11 | base: base, 12 | cwd: __dirname, 13 | path: fname 14 | }); 15 | should.exist(file, 'root'); 16 | should.exist(file.relative, 'relative'); 17 | should.exist(file.path, 'path'); 18 | should.exist(file.cwd, 'cwd'); 19 | should.exist(file.base, 'base'); 20 | file.path.should.equal(fname); 21 | file.cwd.should.equal(__dirname); 22 | file.base.should.equal(base); 23 | file.relative.should.equal('test.coffee'); 24 | done(); 25 | }); 26 | 27 | it('should return a valid file 2', function(done) { 28 | var fname = path.join(__dirname, './fixtures/test.coffee'); 29 | var base = __dirname; 30 | var file = new util.File({ 31 | base: base, 32 | cwd: __dirname, 33 | path: fname 34 | }); 35 | should.exist(file, 'root'); 36 | should.exist(file.relative, 'relative'); 37 | should.exist(file.path, 'path'); 38 | should.exist(file.cwd, 'cwd'); 39 | should.exist(file.base, 'base'); 40 | file.path.should.equal(fname); 41 | file.cwd.should.equal(__dirname); 42 | file.base.should.equal(base); 43 | file.relative.should.equal(path.normalize('fixtures/test.coffee')); 44 | done(); 45 | }); 46 | }); -------------------------------------------------------------------------------- /test/template.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | var should = require('should'); 3 | require('mocha'); 4 | 5 | describe('template()', function(){ 6 | it('should work with just a template', function(done){ 7 | var opt = { 8 | name:'todd', 9 | file: { 10 | path: 'hi.js' 11 | } 12 | }; 13 | var expected = 'test todd hi.js'; 14 | 15 | var tmpl = util.template('test <%= name %> <%= file.path %>'); 16 | should.exist(tmpl); 17 | 'function'.should.equal(typeof(tmpl)); 18 | 19 | // eval it now 20 | var etmpl = tmpl(opt); 21 | 'string'.should.equal(typeof(etmpl)); 22 | etmpl.should.equal(expected); 23 | done(); 24 | }); 25 | 26 | it('should work with a template and data', function(done){ 27 | var opt = { 28 | name:'todd', 29 | file: { 30 | path: 'hi.js' 31 | } 32 | }; 33 | var expected = 'test todd hi.js'; 34 | var tmpl = util.template('test <%= name %> <%= file.path %>', opt); 35 | should.exist(tmpl); 36 | 'string'.should.equal(typeof(tmpl)); 37 | tmpl.should.equal(expected); 38 | done(); 39 | }); 40 | 41 | it('should throw an error when no file object is passed', function(){ 42 | var opt = { 43 | name:'todd' 44 | }; 45 | 46 | should.throws(function() { 47 | util.template('test <%= name %> <%= file.path %>', opt); 48 | }); 49 | }); 50 | 51 | it('should ignore modified templateSettings', function(done){ 52 | var templateSettings = require('lodash.templatesettings'); 53 | templateSettings.interpolate = /\{\{([\s\S]+?)\}\}/g; 54 | 55 | var opt = { 56 | name:'todd', 57 | file: { 58 | path: 'hi.js' 59 | } 60 | }; 61 | var expected = 'test {{name}} hi.js'; 62 | 63 | var tmpl = util.template('test {{name}} <%= file.path %>'); 64 | should.exist(tmpl); 65 | 'function'.should.equal(typeof(tmpl)); 66 | 67 | // eval it now 68 | var etmpl = tmpl(opt); 69 | 'string'.should.equal(typeof(etmpl)); 70 | etmpl.should.equal(expected); 71 | 72 | done(); 73 | }); 74 | 75 | it('should allow ES6 delimiters', function(done){ 76 | var opt = { 77 | name:'todd', 78 | file: { 79 | path: 'hi.js' 80 | } 81 | }; 82 | var expected = 'test todd hi.js'; 83 | 84 | var tmpl = util.template('test ${name} ${file.path}'); 85 | should.exist(tmpl); 86 | 'function'.should.equal(typeof(tmpl)); 87 | 88 | // eval it now 89 | var etmpl = tmpl(opt); 90 | 'string'.should.equal(typeof(etmpl)); 91 | etmpl.should.equal(expected); 92 | 93 | done(); 94 | }); 95 | 96 | }); 97 | -------------------------------------------------------------------------------- /lib/PluginError.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | var arrayDiffer = require('array-differ'); 3 | var arrayUniq = require('array-uniq'); 4 | var chalk = require('chalk'); 5 | var objectAssign = require('object-assign'); 6 | 7 | var nonEnumberableProperties = ['name', 'message', 'stack']; 8 | var propertiesNotToDisplay = nonEnumberableProperties.concat(['plugin', 'showStack', 'showProperties', '__safety', '_stack']); 9 | 10 | // wow what a clusterfuck 11 | var parseOptions = function(plugin, message, opt) { 12 | opt = opt || {}; 13 | if (typeof plugin === 'object') { 14 | opt = plugin; 15 | } else { 16 | if (message instanceof Error) { 17 | opt.error = message; 18 | } else if (typeof message === 'object') { 19 | opt = message; 20 | } else { 21 | opt.message = message; 22 | } 23 | opt.plugin = plugin; 24 | } 25 | 26 | return objectAssign({ 27 | showStack: false, 28 | showProperties: true 29 | }, opt); 30 | }; 31 | 32 | function PluginError(plugin, message, opt) { 33 | if (!(this instanceof PluginError)) throw new Error('Call PluginError using new'); 34 | 35 | Error.call(this); 36 | 37 | var options = parseOptions(plugin, message, opt); 38 | var self = this; 39 | 40 | // if options has an error, grab details from it 41 | if (options.error) { 42 | // These properties are not enumerable, so we have to add them explicitly. 43 | arrayUniq(Object.keys(options.error).concat(nonEnumberableProperties)) 44 | .forEach(function(prop) { 45 | self[prop] = options.error[prop]; 46 | }); 47 | } 48 | 49 | var properties = ['name', 'message', 'fileName', 'lineNumber', 'stack', 'showStack', 'showProperties', 'plugin']; 50 | 51 | // options object can override 52 | properties.forEach(function(prop) { 53 | if (prop in options) this[prop] = options[prop]; 54 | }, this); 55 | 56 | // defaults 57 | if (!this.name) this.name = 'Error'; 58 | 59 | if (!this.stack) { 60 | // Error.captureStackTrace appends a stack property which relies on the toString method of the object it is applied to. 61 | // Since we are using our own toString method which controls when to display the stack trace if we don't go through this 62 | // safety object, then we'll get stack overflow problems. 63 | var safety = { 64 | toString: function() { 65 | return this._messageWithDetails() + '\nStack:'; 66 | }.bind(this) 67 | }; 68 | Error.captureStackTrace(safety, arguments.callee || this.constructor); 69 | this.__safety = safety; 70 | } 71 | 72 | if (!this.plugin) throw new Error('Missing plugin name'); 73 | if (!this.message) throw new Error('Missing error message'); 74 | } 75 | 76 | util.inherits(PluginError, Error); 77 | 78 | PluginError.prototype._messageWithDetails = function() { 79 | var messageWithDetails = 'Message:\n ' + this.message; 80 | var details = this._messageDetails(); 81 | 82 | if (details !== '') { 83 | messageWithDetails += '\n' + details; 84 | } 85 | 86 | return messageWithDetails; 87 | }; 88 | 89 | PluginError.prototype._messageDetails = function() { 90 | if (!this.showProperties) { 91 | return ''; 92 | } 93 | 94 | var properties = arrayDiffer(Object.keys(this), propertiesNotToDisplay); 95 | 96 | if (properties.length === 0) { 97 | return ''; 98 | } 99 | 100 | var self = this; 101 | properties = properties.map(function stringifyProperty(prop) { 102 | return ' ' + prop + ': ' + self[prop]; 103 | }); 104 | 105 | return 'Details:\n' + properties.join('\n'); 106 | }; 107 | 108 | PluginError.prototype.toString = function () { 109 | var sig = chalk.red(this.name) + ' in plugin \'' + chalk.cyan(this.plugin) + '\''; 110 | var detailsWithStack = function(stack) { 111 | return this._messageWithDetails() + '\nStack:\n' + stack; 112 | }.bind(this); 113 | 114 | var msg; 115 | if (this.showStack) { 116 | if (this.__safety) { // There is no wrapped error, use the stack captured in the PluginError ctor 117 | msg = this.__safety.stack; 118 | } else if (this._stack) { 119 | msg = detailsWithStack(this._stack); 120 | } else { // Stack from wrapped error 121 | msg = detailsWithStack(this.stack); 122 | } 123 | } else { 124 | msg = this._messageWithDetails(); 125 | } 126 | 127 | return sig + '\n' + msg; 128 | }; 129 | 130 | module.exports = PluginError; 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | __This module has been deprecated. More information at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5__ 2 | 3 | __Here are some things you can use instead:__ 4 | 5 | * `gutil.File` => https://www.npmjs.com/package/vinyl 6 | * `gutil.replaceExtension` => The `.extname` property on vinyl objects or https://www.npmjs.com/package/replace-ext 7 | * `gutil.colors` => https://www.npmjs.com/package/ansi-colors 8 | * `gutil.date` => https://www.npmjs.com/package/date-format 9 | * `gutil.log` => https://www.npmjs.com/package/fancy-log 10 | * `gutil.template` => https://www.npmjs.com/package/lodash.template 11 | * `gutil.env` => https://www.npmjs.com/package/minimist 12 | * `gutil.beep` => https://www.npmjs.com/package/beeper 13 | * `gutil.noop` => https://www.npmjs.com/package/through2 14 | * `gutil.isStream` => Use the `.isStream()` method on vinyl objects 15 | * `gutil.isBuffer` => Use the `.isBuffer()` method on vinyl objects 16 | * `gutil.isNull` => Use the `.isNull()` method on vinyl objects 17 | * `gutil.linefeed` => Use the string `'\n'` in your code 18 | * `gutil.combine` => https://www.npmjs.com/package/multipipe 19 | * `gutil.buffer` => https://www.npmjs.com/package/list-stream 20 | * `gutil.PluginError` => https://www.npmjs.com/package/plugin-error 21 | 22 | # gulp-util [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Dependency Status][depstat-image]][depstat-url] 23 | 24 | ## Information 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
Packagegulp-util
DescriptionUtility functions for gulp plugins
Node Version>= 0.10
39 | 40 | ## Usage 41 | 42 | ```javascript 43 | var gutil = require('gulp-util'); 44 | 45 | gutil.log('stuff happened', 'Really it did', gutil.colors.magenta('123')); 46 | 47 | gutil.replaceExtension('file.coffee', '.js'); // file.js 48 | 49 | var opt = { 50 | name: 'todd', 51 | file: someGulpFile 52 | }; 53 | gutil.template('test <%= name %> <%= file.path %>', opt) // test todd /js/hi.js 54 | ``` 55 | 56 | ### log(msg...) 57 | 58 | Logs stuff. Already prefixed with [gulp] and all that. If you pass in multiple arguments it will join them by a space. 59 | 60 | The default gulp coloring using gutil.colors.: 61 | ``` 62 | values (files, module names, etc.) = cyan 63 | numbers (times, counts, etc) = magenta 64 | ``` 65 | 66 | ### colors 67 | 68 | Is an instance of [chalk](https://github.com/sindresorhus/chalk). 69 | 70 | ### replaceExtension(path, newExtension) 71 | 72 | Replaces a file extension in a path. Returns the new path. 73 | 74 | ### isStream(obj) 75 | 76 | Returns true or false if an object is a stream. 77 | 78 | ### isBuffer(obj) 79 | 80 | Returns true or false if an object is a Buffer. 81 | 82 | ### template(string[, data]) 83 | 84 | This is a lodash.template function wrapper. You must pass in a valid gulp file object so it is available to the user or it will error. You can not configure any of the delimiters. Look at the [lodash docs](http://lodash.com/docs#template) for more info. 85 | 86 | ## new File(obj) 87 | 88 | This is just [vinyl](https://github.com/wearefractal/vinyl) 89 | 90 | ```javascript 91 | var file = new gutil.File({ 92 | base: path.join(__dirname, './fixtures/'), 93 | cwd: __dirname, 94 | path: path.join(__dirname, './fixtures/test.coffee') 95 | }); 96 | ``` 97 | 98 | ## noop() 99 | 100 | Returns a stream that does nothing but pass data straight through. 101 | 102 | ```javascript 103 | // gulp should be called like this : 104 | // $ gulp --type production 105 | gulp.task('scripts', function() { 106 | gulp.src('src/**/*.js') 107 | .pipe(concat('script.js')) 108 | .pipe(gutil.env.type === 'production' ? uglify() : gutil.noop()) 109 | .pipe(gulp.dest('dist/')); 110 | }); 111 | ``` 112 | 113 | ## buffer(cb) 114 | 115 | This is similar to es.wait but instead of buffering text into one string it buffers anything into an array (so very useful for file objects). 116 | 117 | Returns a stream that can be piped to. 118 | 119 | The stream will emit one data event after the stream piped to it has ended. The data will be the same array passed to the callback. 120 | 121 | Callback is optional and receives two arguments: error and data 122 | 123 | ```javascript 124 | gulp.src('stuff/*.js') 125 | .pipe(gutil.buffer(function(err, files) { 126 | 127 | })); 128 | ``` 129 | 130 | ## new PluginError(pluginName, message[, options]) 131 | 132 | - pluginName should be the module name of your plugin 133 | - message can be a string or an existing error 134 | - By default the stack will not be shown. Set `options.showStack` to true if you think the stack is important for your error. 135 | - If you pass an error in as the message the stack will be pulled from that, otherwise one will be created. 136 | - Note that if you pass in a custom stack string you need to include the message along with that. 137 | - Error properties will be included in `err.toString()`. Can be omitted by including `{showProperties: false}` in the options. 138 | 139 | These are all acceptable forms of instantiation: 140 | 141 | ```javascript 142 | var err = new gutil.PluginError('test', { 143 | message: 'something broke' 144 | }); 145 | 146 | var err = new gutil.PluginError({ 147 | plugin: 'test', 148 | message: 'something broke' 149 | }); 150 | 151 | var err = new gutil.PluginError('test', 'something broke'); 152 | 153 | var err = new gutil.PluginError('test', 'something broke', {showStack: true}); 154 | 155 | var existingError = new Error('OMG'); 156 | var err = new gutil.PluginError('test', existingError, {showStack: true}); 157 | ``` 158 | 159 | ## gulp-util for enterprise 160 | 161 | Available as part of the Tidelift Subscription 162 | 163 | The maintainers of gulp-util and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-gulp-util?utm_source=npm-gulp-util&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) 164 | 165 | 166 | [npm-url]: https://www.npmjs.com/package/gulp-util 167 | [npm-image]: https://badge.fury.io/js/gulp-util.svg 168 | [travis-url]: https://travis-ci.org/gulpjs/gulp-util 169 | [travis-image]: https://img.shields.io/travis/gulpjs/gulp-util.svg?branch=master 170 | [coveralls-url]: https://coveralls.io/r/gulpjs/gulp-util 171 | [coveralls-image]: https://img.shields.io/coveralls/gulpjs/gulp-util.svg 172 | [depstat-url]: https://david-dm.org/gulpjs/gulp-util 173 | [depstat-image]: https://david-dm.org/gulpjs/gulp-util.svg 174 | -------------------------------------------------------------------------------- /test/PluginError.js: -------------------------------------------------------------------------------- 1 | var util = require('..'); 2 | require('should'); 3 | require('mocha'); 4 | 5 | describe('PluginError()', function(){ 6 | it('should default name to Error', function() { 7 | var err = new util.PluginError('test', 'something broke'); 8 | err.name.should.equal('Error'); 9 | }); 10 | 11 | it('should default name to Error, even when wrapped error has no name', function() { 12 | var realErr = { message: 'something broke' }; 13 | var err = new util.PluginError('test', realErr); 14 | err.name.should.equal('Error'); 15 | }); 16 | 17 | it('should print the plugin name in toString', function(){ 18 | var err = new util.PluginError('test', 'something broke'); 19 | err.toString().should.containEql('test'); 20 | }); 21 | 22 | it('should not include the stack by default in toString', function(){ 23 | var err = new util.PluginError('test', 'something broke'); 24 | // just check that there are no 'at' lines 25 | err.toString().should.not.containEql('at'); 26 | }); 27 | 28 | it('should include the stack when specified in toString', function(){ 29 | var err = new util.PluginError('test', 'something broke', {stack: 'at huh', showStack: true}); 30 | // just check that there are 'at' lines 31 | err.toString().should.containEql('at'); 32 | }); 33 | 34 | it('should take arguments as one object', function(){ 35 | var err = new util.PluginError({ 36 | plugin: 'test', 37 | message: 'something broke' 38 | }); 39 | err.plugin.should.equal('test'); 40 | err.message.should.equal('something broke'); 41 | }); 42 | 43 | it('should take arguments as plugin name and one object', function(){ 44 | var err = new util.PluginError('test', { 45 | message: 'something broke' 46 | }); 47 | err.plugin.should.equal('test'); 48 | err.message.should.equal('something broke'); 49 | }); 50 | 51 | it('should take arguments as plugin name and message', function(){ 52 | var err = new util.PluginError('test', 'something broke'); 53 | err.plugin.should.equal('test'); 54 | err.message.should.equal('something broke'); 55 | }); 56 | 57 | it('should take arguments as plugin name, message, and one object', function(){ 58 | var err = new util.PluginError('test', 'something broke', {showStack: true}); 59 | err.plugin.should.equal('test'); 60 | err.message.should.equal('something broke'); 61 | err.showStack.should.equal(true); 62 | }); 63 | 64 | it('should take arguments as plugin name, error, and one object', function(){ 65 | var realErr = new Error('something broke'); 66 | realErr.fileName = 'original.js'; 67 | var err = new util.PluginError('test', realErr, {showStack: true, fileName: 'override.js'}); 68 | err.plugin.should.equal('test'); 69 | err.message.should.equal('something broke'); 70 | err.fileName.should.equal('override.js'); 71 | err.showStack.should.equal(true); 72 | }); 73 | 74 | it('should take properties from error', function() { 75 | var realErr = new Error('something broke'); 76 | realErr.abstractProperty = 'abstract'; 77 | var err = new util.PluginError('test', realErr); 78 | err.plugin.should.equal('test'); 79 | err.message.should.equal('something broke'); 80 | err.abstractProperty.should.equal('abstract'); 81 | }); 82 | 83 | it('should be configured to show properties by default', function(){ 84 | var err = new util.PluginError('test', 'something broke'); 85 | err.showProperties.should.be.true; 86 | }); 87 | 88 | it('should not be configured to take option to show properties', function(){ 89 | var err = new util.PluginError('test', 'something broke', {showProperties: false}); 90 | err.showProperties.should.be.false; 91 | }); 92 | 93 | it('should show properties', function() { 94 | var err = new util.PluginError('test', 'it broke', {showProperties: true}); 95 | err.fileName = 'original.js'; 96 | err.lineNumber = 35; 97 | err.toString().should.containEql('it broke'); 98 | err.toString().should.not.containEql('message:'); 99 | err.toString().should.containEql('fileName:'); 100 | }); 101 | 102 | it('should show properties', function() { 103 | var realErr = new Error('something broke'); 104 | realErr.fileName = 'original.js'; 105 | realErr.lineNumber = 35; 106 | var err = new util.PluginError('test', realErr, {showProperties: true}); 107 | err.toString().should.not.containEql('message:'); 108 | err.toString().should.containEql('fileName:'); 109 | }); 110 | 111 | it('should not show properties', function() { 112 | var realErr = new Error('something broke'); 113 | realErr.fileName = 'original.js'; 114 | realErr.lineNumber = 35; 115 | var err = new util.PluginError('test', realErr, {showProperties: false}); 116 | err.toString().should.not.containEql('message:'); 117 | err.toString().should.not.containEql('fileName:'); 118 | }); 119 | 120 | it('should not show properties, but should show stack', function() { 121 | var err = new util.PluginError('test', 'it broke', {stack: 'test stack', showStack: true, showProperties: false}); 122 | err.fileName = 'original.js'; 123 | err.lineNumber = 35; 124 | err.toString().should.not.containEql('message:'); 125 | err.toString().should.not.containEql('fileName:'); 126 | err.toString().should.containEql('test stack'); 127 | }); 128 | 129 | it('should not show properties, but should show stack for real error', function() { 130 | var realErr = new Error('something broke'); 131 | realErr.fileName = 'original.js'; 132 | realErr.lineNumber = 35; 133 | realErr.stack = 'test stack'; 134 | var err = new util.PluginError('test', realErr, {showStack: true, showProperties: false}); 135 | err.toString().indexOf('message:').should.equal(-1); 136 | err.toString().indexOf('fileName:').should.equal(-1); 137 | err.toString().indexOf('test stack').should.not.equal(-1); 138 | }); 139 | 140 | it('should not show properties, but should show stack for _stack', function() { 141 | var realErr = new Error('something broke'); 142 | realErr.fileName = 'original.js'; 143 | realErr.lineNumber = 35; 144 | realErr._stack = 'test stack'; 145 | var err = new util.PluginError('test', realErr, {showStack: true, showProperties: false}); 146 | err.toString().indexOf('message:').should.equal(-1); 147 | err.toString().indexOf('fileName:').should.equal(-1); 148 | err.toString().indexOf('test stack').should.not.equal(-1); 149 | }); 150 | 151 | it('should show properties and stack', function(){ 152 | var realErr = new Error('something broke'); 153 | realErr.fileName = 'original.js'; 154 | realErr.stack = 'test stack'; 155 | var err = new util.PluginError('test', realErr, {showStack: true}); 156 | err.toString().indexOf('message:').should.equal(-1); 157 | err.toString().indexOf('fileName:').should.not.equal(-1); 158 | err.toString().indexOf('test stack').should.not.equal(-1); 159 | }); 160 | 161 | it('should show properties added after the error is created', function(){ 162 | var realErr = new Error('something broke'); 163 | var err = new util.PluginError('test', realErr); 164 | err.fileName = 'original.js'; 165 | err.toString().indexOf('message:').should.equal(-1); 166 | err.toString().indexOf('fileName:').should.not.equal(-1); 167 | }); 168 | 169 | it('should toString quickly', function(done) { 170 | this.timeout(100); 171 | 172 | var err = new util.PluginError('test', 'it broke', {showStack: true}); 173 | err.toString(); 174 | 175 | done(); 176 | }); 177 | 178 | it('should toString quickly with original error', function(done) { 179 | this.timeout(100); 180 | 181 | var realErr = new Error('it broke'); 182 | var err = new util.PluginError('test', realErr, {showStack: true}); 183 | err.toString(); 184 | 185 | done(); 186 | }); 187 | 188 | it('should not show "Details:" if there are no properties to show', function() { 189 | var err = new util.PluginError('plugin', 'message'); 190 | err.toString().indexOf('Details:').should.equal(-1); 191 | }); 192 | }); 193 | --------------------------------------------------------------------------------