From 61f4645e99a386183650206b5f1962dd1f1106c3 Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Tue, 14 Oct 2014 12:35:50 -0500 Subject: [PATCH 1/3] Refactor vinyl --- CONTRIBUTORS.md | 2 +- vinyl/vinyl-tests.ts | 178 +++++++++++++++++++++---------------------- vinyl/vinyl.d.ts | 123 ++++++++++++++++++++++-------- 3 files changed, 180 insertions(+), 123 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index df1493d8c..58718a076 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -406,7 +406,7 @@ All definitions files include a header with the author and editors, so at some p * [Viewporter](https://github.com/zynga/viewporter) (by [Boris Yankov](https://github.com/borisyankov)) * [Vimeo](http://developer.vimeo.com/player/js-api) (by [Daz Wilkin](https://github.com/DazWilkin/)) * [vinyl](https://github.com/wearefractal/vinyl) (by [vvakame](https://github.com/vvakame/)) -* [vinyl-fs](https://github.com/wearefractal/vinyl-fs) (by [vvakame](https://github.com/vvakame/)) +* [vinyl-fs](https://github.com/wearefractal/vinyl-fs) (by [vvakame](https://github.com/vvakame/) and [jedmao](https://github.com/jedmao)) * [WebRTC](http://dev.w3.org/2011/webrtc/editor/webrtc.html) (by [Ken Smith](https://github.com/smithkl42)) * [websocket](https://github.com/Worlize/WebSocket-Node) (by [Paul Loyd](https://github.com/loyd)) * [WinJS](http://msdn.microsoft.com/en-us/library/windows/apps/br229773.aspx) (from TypeScript samples) diff --git a/vinyl/vinyl-tests.ts b/vinyl/vinyl-tests.ts index e09539990..eb203bdae 100644 --- a/vinyl/vinyl-tests.ts +++ b/vinyl/vinyl-tests.ts @@ -7,77 +7,78 @@ import File = require('vinyl'); import Stream = require('stream'); import fs = require('fs'); -import should = require('should'); +declare var fakeStream: NodeJS.ReadWriteStream; -describe('File', function() { +describe('File', () => { - describe('constructor()', function() { - it('should default cwd to process.cwd', function(done) { + describe('constructor()', () => { + + it('should default cwd to process.cwd', done => { var file = new File(); file.cwd.should.equal(process.cwd()); done(); }); - it('should default base to cwd', function(done) { + it('should default base to cwd', done => { var cwd = "/"; var file = new File({cwd: cwd}); file.base.should.equal(cwd); done(); }); - it('should default base to cwd even when none is given', function(done) { + it('should default base to cwd even when none is given', done => { var file = new File(); file.base.should.equal(process.cwd()); done(); }); - it('should default path to null', function(done) { + it('should default path to null', done => { var file = new File(); should.not.exist(file.path); done(); }); - it('should default stat to null', function(done) { + it('should default stat to null', done => { var file = new File(); should.not.exist(file.stat); done(); }); - it('should default contents to null', function(done) { + it('should default contents to null', done => { var file = new File(); should.not.exist(file.contents); done(); }); - it('should set base to given value', function(done) { + it('should set base to given value', done => { var val = "/"; var file = new File({base: val}); file.base.should.equal(val); done(); }); - it('should set cwd to given value', function(done) { + it('should set cwd to given value', done => { var val = "/"; var file = new File({cwd: val}); file.cwd.should.equal(val); done(); }); - it('should set path to given value', function(done) { + it('should set path to given value', done => { var val = "/test.coffee"; var file = new File({path: val}); file.path.should.equal(val); done(); }); - it('should set stat to given value', function(done) { + it('should set stat to given value', done => { var val = {}; var file = new File({stat: val}); file.stat.should.equal(val); done(); }); - it('should set contents to given value', function(done) { + it('should set contents to given value', done => { var val = new Buffer("test"); var file = new File({contents: val}); file.contents.should.equal(val); @@ -85,102 +86,98 @@ describe('File', function() { }); }); - describe('isBuffer()', function() { - it('should return true when the contents are a Buffer', function(done) { + describe('isBuffer()', () => { + it('should return true when the contents are a Buffer', done => { var val = new Buffer("test"); var file = new File({contents: val}); file.isBuffer().should.equal(true); done(); }); - it('should return false when the contents are a Stream', function(done) { - var val: NodeJS.ReadWriteStream; // = new Stream(); - var file = new File({contents: val}); + it('should return false when the contents are a Stream', done => { + var file = new File({ contents: fakeStream}); file.isBuffer().should.equal(false); done(); }); - it('should return false when the contents are a null', function(done) { + it('should return false when the contents are a null', done => { var file = new File({contents: null}); file.isBuffer().should.equal(false); done(); }); }); - describe('isStream()', function() { - it('should return false when the contents are a Buffer', function(done) { + describe('isStream()', () => { + it('should return false when the contents are a Buffer', done => { var val = new Buffer("test"); var file = new File({contents: val}); file.isStream().should.equal(false); done(); }); - it('should return true when the contents are a Stream', function(done) { - var val: NodeJS.ReadWriteStream; // = new Stream(); - var file = new File({contents: val}); + it('should return true when the contents are a Stream', done => { + var file = new File({ contents: fakeStream}); file.isStream().should.equal(true); done(); }); - it('should return false when the contents are a null', function(done) { + it('should return false when the contents are a null', done => { var file = new File({contents: null}); file.isStream().should.equal(false); done(); }); }); - describe('isNull()', function() { - it('should return false when the contents are a Buffer', function(done) { + describe('isNull()', () => { + it('should return false when the contents are a Buffer', done => { var val = new Buffer("test"); var file = new File({contents: val}); file.isNull().should.equal(false); done(); }); - it('should return false when the contents are a Stream', function(done) { - var val: NodeJS.ReadWriteStream; // = new Stream(); - var file = new File({contents: val}); + it('should return false when the contents are a Stream', done => { + var file = new File({ contents: fakeStream}); file.isNull().should.equal(false); done(); }); - it('should return true when the contents are a null', function(done) { + it('should return true when the contents are a null', done => { var file = new File({contents: null}); file.isNull().should.equal(true); done(); }); }); - describe('isDirectory()', function() { + describe('isDirectory()', () => { var fakeStat = { - isDirectory: function() { + isDirectory: () => { return true; } }; - it('should return false when the contents are a Buffer', function(done) { + it('should return false when the contents are a Buffer', done => { var val = new Buffer("test"); var file = new File({contents: val, stat: fakeStat}); file.isDirectory().should.equal(false); done(); }); - it('should return false when the contents are a Stream', function(done) { - var val: NodeJS.ReadWriteStream; // = new Stream(); - var file = new File({contents: val, stat: fakeStat}); + it('should return false when the contents are a Stream', done => { + var file = new File({ contents: fakeStream, stat: fakeStat}); file.isDirectory().should.equal(false); done(); }); - it('should return true when the contents are a null', function(done) { + it('should return true when the contents are a null', done => { var file = new File({contents: null, stat: fakeStat}); file.isDirectory().should.equal(true); done(); }); }); - describe('clone()', function() { - it('should copy all attributes over with Buffer', function(done) { + describe('clone()', () => { + it('should copy all attributes over with Buffer', done => { var options = { cwd: "/", base: "/test/", @@ -199,12 +196,12 @@ describe('File', function() { done(); }); - it('should copy all attributes over with Stream', function(done) { + it('should copy all attributes over with Stream', done => { var options = { cwd: "/", base: "/test/", path: "/test/test.coffee", - contents: null // new Stream() + contents: fakeStream }; var file = new File(options); var file2 = file.clone(); @@ -217,12 +214,12 @@ describe('File', function() { done(); }); - it('should copy all attributes over with null', function(done) { + it('should copy all attributes over with null', done => { var options = { cwd: "/", base: "/test/", path: "/test/test.coffee", - contents: null + contents: fakeStream }; var file = new File(options); var file2 = file.clone(); @@ -235,7 +232,7 @@ describe('File', function() { done(); }); - it('should properly clone the `stat` property', function(done) { + it('should properly clone the `stat` property', done => { var options = { cwd: "/", base: "/test/", @@ -247,17 +244,17 @@ describe('File', function() { var file = new File(options); var copy = file.clone(); + // ReSharper disable WrongExpressionStatement copy.stat.isFile().should.be.true; copy.stat.isDirectory().should.be.false; - // should(file.stat instanceof fs.Stats).be.true; - // should(copy.stat instanceof fs.Stats).be.true; + // ReSharper restore WrongExpressionStatement done(); }); }); - describe('pipe()', function() { - it('should write to stream with Buffer', function(done) { + describe('pipe()', () => { + it('should write to stream with Buffer', done => { var options = { cwd: "/", base: "/test/", @@ -266,19 +263,19 @@ describe('File', function() { }; var file = new File(options); var stream = new Stream.PassThrough(); - stream.on('data', function(chunk:any) { + stream.on('data', (chunk: any) => { should.exist(chunk); (chunk instanceof Buffer).should.equal(true, 'should write as a buffer'); chunk.toString('utf8').should.equal(options.contents.toString('utf8')); }); - stream.on('end', function(chunk:any) { + stream.on('end', () => { done(); }); var ret = file.pipe(stream); ret.should.equal(stream, 'should return the stream'); }); - it('should pipe to stream with Stream', function(done) { + it('should pipe to stream with Stream', done => { var testChunk = new Buffer("test"); var options = { cwd: "/", @@ -288,7 +285,7 @@ describe('File', function() { }; var file = new File(options); var stream = new Stream.PassThrough(); - stream.on('data', function(chunk:any) { + stream.on('data', (chunk: any) => { should.exist(chunk); (chunk instanceof Buffer).should.equal(true, 'should write as a buffer'); chunk.toString('utf8').should.equal(testChunk.toString('utf8')); @@ -300,26 +297,26 @@ describe('File', function() { file.contents.write(testChunk); }); - it('should do nothing with null', function(done) { + it('should do nothing with null', done => { var options = { cwd: "/", base: "/test/", path: "/test/test.coffee", - contents: null + contents: fakeStream }; var file = new File(options); var stream = new Stream.PassThrough(); - stream.on('data', function(chunk:any) { + stream.on('data', () => { throw new Error("should not write"); }); - stream.on('end', function() { + stream.on('end', () => { done(); }); var ret = file.pipe(stream); ret.should.equal(stream, 'should return the stream'); }); - it('should write to stream with Buffer', function(done) { + it('should write to stream with Buffer', done => { var options = { cwd: "/", base: "/test/", @@ -328,20 +325,20 @@ describe('File', function() { }; var file = new File(options); var stream = new Stream.PassThrough(); - stream.on('data', function(chunk:any) { + stream.on('data', (chunk: any) => { should.exist(chunk); (chunk instanceof Buffer).should.equal(true, 'should write as a buffer'); chunk.toString('utf8').should.equal(options.contents.toString('utf8')); done(); }); - stream.on('end', function(chunk:any) { + stream.on('end', () => { throw new Error("should not end"); }); var ret = file.pipe(stream, {end: false}); ret.should.equal(stream, 'should return the stream'); }); - it('should pipe to stream with Stream', function(done) { + it('should pipe to stream with Stream', done => { var testChunk = new Buffer("test"); var options = { cwd: "/", @@ -351,13 +348,13 @@ describe('File', function() { }; var file = new File(options); var stream = new Stream.PassThrough(); - stream.on('data', function(chunk:any) { + stream.on('data', (chunk: any) => { should.exist(chunk); (chunk instanceof Buffer).should.equal(true, 'should write as a buffer'); chunk.toString('utf8').should.equal(testChunk.toString('utf8')); done(); }); - stream.on('end', function(chunk:any) { + stream.on('end', () => { throw new Error("should not end"); }); var ret = file.pipe(stream, {end: false}); @@ -366,19 +363,19 @@ describe('File', function() { file.contents.write(testChunk); }); - it('should do nothing with null', function(done) { + it('should do nothing with null', done => { var options = { cwd: "/", base: "/test/", path: "/test/test.coffee", - contents: null + contents: fakeStream }; var file = new File(options); var stream = new Stream.PassThrough(); - stream.on('data', function(chunk:any) { + stream.on('data', () => { throw new Error("should not write"); }); - stream.on('end', function(chunk:any) { + stream.on('end', () => { throw new Error("should not end"); }); var ret = file.pipe(stream, {end: false}); @@ -387,14 +384,14 @@ describe('File', function() { }); }); - describe('inspect()', function() { - it('should return correct format when no contents and no path', function(done) { + describe('inspect()', () => { + it('should return correct format when no contents and no path', done => { var file = new File(); file.inspect().should.equal(''); done(); }); - it('should return correct format when Buffer and no path', function(done) { + it('should return correct format when Buffer and no path', done => { var val = new Buffer("test"); var file = new File({ contents: val @@ -403,7 +400,7 @@ describe('File', function() { done(); }); - it('should return correct format when Buffer and relative path', function(done) { + it('should return correct format when Buffer and relative path', done => { var val = new Buffer("test"); var file = new File({ cwd: "/", @@ -415,7 +412,7 @@ describe('File', function() { done(); }); - it('should return correct format when Buffer and only path and no base', function(done) { + it('should return correct format when Buffer and only path and no base', done => { var val = new Buffer("test"); var file = new File({ cwd: "/", @@ -427,7 +424,7 @@ describe('File', function() { done(); }); - it('should return correct format when Stream and relative path', function(done) { + it('should return correct format when Stream and relative path', done => { var file = new File({ cwd: "/", base: "/test/", @@ -438,7 +435,7 @@ describe('File', function() { done(); }); - it('should return correct format when null and relative path', function(done) { + it('should return correct format when null and relative path', done => { var file = new File({ cwd: "/", base: "/test/", @@ -450,8 +447,8 @@ describe('File', function() { }); }); - describe('contents get/set', function() { - it('should work with Buffer', function(done) { + describe('contents get/set', () => { + it('should work with Buffer', done => { var val = new Buffer("test"); var file = new File(); file.contents = val; @@ -459,7 +456,7 @@ describe('File', function() { done(); }); - it('should work with Stream', function(done) { + it('should work with Stream', done => { var val = new Stream.PassThrough(); var file = new File(); file.contents = val; @@ -467,15 +464,14 @@ describe('File', function() { done(); }); - it('should work with null', function(done) { - var val:any = null; + it('should work with null', done => { var file = new File(); - file.contents = val; + file.contents = null; (file.contents === null).should.equal(true); done(); }); - it('should not work with string', function(done) { + it('should not work with string', done => { var val = "test"; var file = new File(); try { @@ -487,8 +483,8 @@ describe('File', function() { }); }); - describe('relative get/set', function() { - it('should error on set', function(done) { + describe('relative get/set', () => { + it('should error on set', done => { var file = new File(); try { file.relative = "test"; @@ -498,11 +494,12 @@ describe('File', function() { } }); - it('should error on get when no base', function(done) { - var a:any; + it('should error on get when no base', done => { + var a: string; var file = new File(); delete file.base; try { + // ReSharper disable once AssignedValueIsNeverUsed a = file.relative; } catch (err) { should.exist(err); @@ -510,10 +507,11 @@ describe('File', function() { } }); - it('should error on get when no path', function(done) { - var a:any; + it('should error on get when no path', done => { + var a: string; var file = new File(); try { + // ReSharper disable once AssignedValueIsNeverUsed a = file.relative; } catch (err) { should.exist(err); @@ -521,7 +519,7 @@ describe('File', function() { } }); - it('should return a relative path from base', function(done) { + it('should return a relative path from base', done => { var file = new File({ cwd: "/", base: "/test/", @@ -531,7 +529,7 @@ describe('File', function() { done(); }); - it('should return a relative path from cwd', function(done) { + it('should return a relative path from cwd', done => { var file = new File({ cwd: "/", path: "/test/test.coffee" diff --git a/vinyl/vinyl.d.ts b/vinyl/vinyl.d.ts index 72b688a5f..708f2c791 100644 --- a/vinyl/vinyl.d.ts +++ b/vinyl/vinyl.d.ts @@ -1,41 +1,100 @@ -// Type definitions for vinyl +// Type definitions for vinyl 0.4.3 // Project: https://github.com/wearefractal/vinyl -// Definitions by: vvakame +// Definitions by: vvakame , jedmao // Definitions: https://github.com/borisyankov/DefinitelyTyped /// -declare module Vinyl { - interface IOptions { - cwd?:string; - base?:string; - path?:string; - contents?:any; // Buffer or Stream +declare module 'vinyl' { + + import fs = require('fs'); + + /** + * A virtual file format. + */ + class File { + constructor(options?: { + /** + * Default: process.cwd() + */ + cwd?: string; + /** + * Used for relative pathing. Typically where a glob starts. + */ + base?: string; + /** + * Full path to the file. + */ + path?: string; + /** + * Type: Buffer|Stream|null (Default: null) + */ + contents?: any; + }); + + /** + * Default: process.cwd() + */ + public cwd: string; + /** + * Used for relative pathing. Typically where a glob starts. + */ + public base: string; + /** + * Full path to the file. + */ + public path: string; + public stat: fs.Stats; + /** + * Type: Buffer|Stream|null (Default: null) + */ + public contents: any; + /** + * Returns path.relative for the file base and file path. + * Example: + * var file = new File({ + * cwd: "/", + * base: "/test/", + * path: "/test/file.js" + * }); + * console.log(file.relative); // file.js + */ + public relative: string; + + public isBuffer(): boolean; + + public isStream(): boolean; + + public isNull(): boolean; + + public isDirectory(): boolean; + + /** + * Returns a new File object with all attributes cloned. Custom attributes are deep-cloned. + */ + public clone(): File; + + /** + * If file.contents is a Buffer, it will write it to the stream. + * If file.contents is a Stream, it will pipe it to the stream. + * If file.contents is null, it will do nothing. + */ + public pipe( + stream: T, + opts?: { + /** + * If false, the destination stream will not be ended (same as node core). + */ + end?: boolean; + } + ): T; + + /** + * Returns a pretty String interpretation of the File. Useful for console.log. + */ + public inspect(): string; } - interface IFileStatic { - new (file?:IOptions):IFile; - } + export = File; - interface IFile { - cwd:string; - base:string; - path:string; - stat:any; // stat = fs stats object - contents:any; // Buffer or Stream - relative:string; - - isBuffer():boolean; - isStream():boolean; - isNull():boolean; - isDirectory():boolean; - clone():IFile; - pipe(stream:T, opts?:{ end?: boolean; }):T; - inspect():string; - } -} - -declare module "vinyl" { - var _:Vinyl.IFileStatic; - export = _; } From 122d52957e92d0be2c1c1db9bb30c815dcaa77bd Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Wed, 15 Oct 2014 17:09:03 -0500 Subject: [PATCH 2/3] Fix through2 --- CONTRIBUTORS.md | 1 + through2/through2.d.ts | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 58718a076..b35cb0ee4 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -384,6 +384,7 @@ All definitions files include a header with the author and editors, so at some p * [text-buffer](https://github.com/atom/text-buffer) (by [vvakame](https://github.com/vvakame)) * [text-encoding](https://github.com/inexorabletash/text-encoding) (by [MIZUNE Pine](https://github.com/pine613)) * [three.js](http://mrdoob.github.com/three.js/) (by [Kon](http://phyzkit.net/)) +* [through2](https://github.com/rvagg/through2) (by [Bart van der Schoor](https://github.com/Bartvds) and [jedmao](https://github.com/jedmao)) * [TimelineJS](https://github.com/NUKnightLab/TimelineJS) (by [Roland Zwaga](https://github.com/rolandzwaga)) * [timezonecomplete](https://github.com/SpiritIT/timezonecomplete) (by [Rogier Schouten](https://github.com/rogierschouten)) * [Toastr](https://github.com/CodeSeven/toastr) (by [Boris Yankov](https://github.com/borisyankov)) diff --git a/through2/through2.d.ts b/through2/through2.d.ts index 3eb16f2e6..95cedf752 100644 --- a/through2/through2.d.ts +++ b/through2/through2.d.ts @@ -1,23 +1,26 @@ // Type definitions for through2 v 0.4.2 // Project: https://github.com/rvagg/through2 -// Definitions by: Bart van der Schoor +// Definitions by: Bart van der Schoor , jedmao // Definitions: https://github.com/borisyankov/DefinitelyTyped /// declare module 'through2' { + import stream = require('stream'); - var mod: mod.Through2; + function through2(transform?: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; + + function through2(opts: stream.DuplexOptions, transform?: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; + + module through2 { + + export function obj(transform: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; + + export function push(data: any): void; - module mod { - interface Through2 { - (transform?: (entry: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; - (opts: stream.DuplexOptions, transform?: (entry: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; - obj(transform: (entry: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; - push(data: any): void; - } } - export = mod; -} + export = through2; + +} From 5d4a87811a8282f01bc1cdf2156020d78515fa2e Mon Sep 17 00:00:00 2001 From: Jed Mao Date: Wed, 15 Oct 2014 17:09:26 -0500 Subject: [PATCH 3/3] Add gulp-util definitions, fix related --- chalk/chalk.d.ts | 1 + gulp-util/gulp-util-tests.ts | 597 +++++++++++++++++++++++++++++++++++ gulp-util/gulp-util.d.ts | 138 ++++++++ should/should.d.ts | 4 +- through2/through2.d.ts | 4 +- vinyl/vinyl.d.ts | 2 +- 6 files changed, 741 insertions(+), 5 deletions(-) create mode 100644 gulp-util/gulp-util-tests.ts create mode 100644 gulp-util/gulp-util.d.ts diff --git a/chalk/chalk.d.ts b/chalk/chalk.d.ts index 5cceb9514..ede294775 100644 --- a/chalk/chalk.d.ts +++ b/chalk/chalk.d.ts @@ -41,6 +41,7 @@ declare module Chalk { cyan: ChalkChain; white: ChalkChain; gray: ChalkChain; + grey: ChalkChain; // Background colors bgBlack: ChalkChain; diff --git a/gulp-util/gulp-util-tests.ts b/gulp-util/gulp-util-tests.ts new file mode 100644 index 000000000..6b5f75673 --- /dev/null +++ b/gulp-util/gulp-util-tests.ts @@ -0,0 +1,597 @@ +/// +/// +/// +/// +/// + +import gulp = require('gulp'); +import util = require('gulp-util'); +import path = require('path'); +import should = require('should'); +import Stream = require('stream'); +import through = require('through2'); +var es = require('event-stream'); + +// ReSharper disable WrongExpressionStatement +describe('File()', () => { + it('should return a valid file', done => { + var fname = path.join(__dirname, './fixtures/test.coffee'); + var base = path.join(__dirname, './fixtures/'); + var file = new util.File({ + base: base, + cwd: __dirname, + path: fname + }); + should.exist(file, 'root'); + should.exist(file.relative, 'relative'); + should.exist(file.path, 'path'); + should.exist(file.cwd, 'cwd'); + should.exist(file.base, 'base'); + file.path.should.equal(fname); + file.cwd.should.equal(__dirname); + file.base.should.equal(base); + file.relative.should.equal('test.coffee'); + done(); + }); + + it('should return a valid file 2', done => { + var fname = path.join(__dirname, './fixtures/test.coffee'); + var base = __dirname; + var file = new util.File({ + base: base, + cwd: __dirname, + path: fname + }); + should.exist(file, 'root'); + should.exist(file.relative, 'relative'); + should.exist(file.path, 'path'); + should.exist(file.cwd, 'cwd'); + should.exist(file.base, 'base'); + file.path.should.equal(fname); + file.cwd.should.equal(__dirname); + file.base.should.equal(base); + file.relative.should.equal(path.normalize('fixtures/test.coffee')); + done(); + }); +}); + +describe('replaceExtension()', () => { + it('should return a valid replaced extension on nested', done => { + var fname = path.join(__dirname, './fixtures/test.coffee'); + var expected = path.join(__dirname, './fixtures/test.js'); + var nu = util.replaceExtension(fname, '.js'); + should.exist(nu); + nu.should.equal(expected); + done(); + }); + + it('should return a valid replaced extension on flat', done => { + var fname = 'test.coffee'; + var expected = 'test.js'; + var nu = util.replaceExtension(fname, '.js'); + should.exist(nu); + nu.should.equal(expected); + done(); + }); + + it('should not return a valid replaced extension on empty string', done => { + var fname = ''; + var expected = ''; + var nu = util.replaceExtension(fname, '.js'); + should.exist(nu); + nu.should.equal(expected); + done(); + }); + +}); + +describe('colors', () => { + it('should be a chalk instance', done => { + util.colors.should.equal(require('chalk')); + done(); + }); +}); +util.log('stuff happened', 'Really it did', util.colors.cyan('123')); + +describe('date', () => { + it('should be a date format instance', done => { + util.date.should.equal(require('dateformat')); + done(); + }); + it('should return today\'s date', done => { + var time = new Date(); + var dateutil = util.date('HH:MM:ss'); + dateutil.should.equal(('0' + time.getHours()).slice(-2) + ':' + ('0' + time.getMinutes()).slice(-2) + ':' + ('0' + time.getSeconds()).slice(-2)); + done(); + }); +}); + +var now = new Date(); + +// Basic usage +util.date(now, 'dddd, mmmm dS, yyyy, h:MM:ss TT'); +// Saturday, June 9th, 2007, 5:46:21 PM + +// You can use one of several named masks +util.date(now, 'isoDateTime'); +// 2007-06-09T17:46:21 + +// ...Or add your own +util.date.masks.hammerTime = 'HH:MM! "Can\'t touch this!"'; +util.date(now, 'hammerTime'); +// 17:46! Can't touch this! + +// When using the standalone dateFormat function, +// you can also provide the date as a string +util.date('Jun 9 2007', 'fullDate'); +// Saturday, June 9, 2007 + +// Note that if you don't include the mask argument, +// dateFormat.masks.default is used +util.date(now); +// Sat Jun 09 2007 17:46:21 + +// And if you don't include the date argument, +// the current date and time is used +util.date(); +// Sat Jun 09 2007 17:46:22 + +// You can also skip the date argument (as long as your mask doesn't +// contain any numbers), in which case the current date/time is used +util.date('longTime'); +// 5:46:22 PM EST + +// And finally, you can convert local time to UTC time. Simply pass in +// true as an additional argument (no argument skipping allowed in this case): +util.date(now, 'longTime', true); +// 10:46:21 PM UTC + +// ...Or add the prefix 'UTC:' or 'GMT:' to your mask. +util.date(now, 'UTC:h:MM:ss TT Z'); +// 10:46:21 PM UTC + +// You can also get the ISO 8601 week of the year: +util.date(now, 'W'); +// 42 + +// and also get the ISO 8601 numeric representation of the day of the week: +util.date(now, 'N'); +// 6 + +describe('log()', () => { + it('should work i guess', done => { + var writtenValue = ''; + + util.log(1, 2, 3, 4, 'five'); + var time = util.date(new Date(), 'HH:MM:ss'); + writtenValue.should.eql('[' + util.colors.gray(time) + '] 1 2 3 4 five\n'); + + done(); + }); +}); + +describe('template()', () => { + it('should work with just a template', done => { + var opt = { + name: 'todd', + file: { + path: 'hi.js' + } + }; + var expected = 'test todd hi.js'; + + var tmpl = util.template('test <%= name %> <%= file.path %>'); + should.exist(tmpl); + 'function'.should.equal(typeof (tmpl)); + + // eval it now + var etmpl = tmpl(opt); + 'string'.should.equal(typeof (etmpl)); + etmpl.should.equal(expected); + done(); + }); + + it('should work with a template and data', done => { + var opt = { + name: 'todd', + file: { + path: 'hi.js' + } + }; + var expected = 'test todd hi.js'; + var tmpl = util.template('test <%= name %> <%= file.path %>', opt); + should.exist(tmpl); + 'string'.should.equal(typeof (tmpl)); + tmpl.should.equal(expected); + done(); + }); + + //it('should throw an error when no file object is passed', done => { + // var opt = { + // name: 'todd' + // }; + // try { + // var tmpl = util.template('test <%= name %> <%= file.path %>', opt); + // } catch (err) { + // should.exist(err); + // done(); + // } + //}); + + it('should ignore modified templateSettings', done => { + var templateSettings = require('lodash.templatesettings'); + templateSettings.interpolate = /\{\{([\s\S]+?)\}\}/g; + + var opt = { + name: 'todd', + file: { + path: 'hi.js' + } + }; + var expected = 'test {{name}} hi.js'; + + var tmpl = util.template('test {{name}} <%= file.path %>'); + should.exist(tmpl); + 'function'.should.equal(typeof (tmpl)); + + // eval it now + var etmpl = tmpl(opt); + 'string'.should.equal(typeof (etmpl)); + etmpl.should.equal(expected); + + done(); + }); + + it('should allow ES6 delimiters', done => { + var opt = { + name: 'todd', + file: { + path: 'hi.js' + } + }; + var expected = 'test todd hi.js'; + + var tmpl = util.template('test ${name} ${file.path}'); + should.exist(tmpl); + 'function'.should.equal(typeof (tmpl)); + + // eval it now + var etmpl = tmpl(opt); + 'string'.should.equal(typeof (etmpl)); + etmpl.should.equal(expected); + + done(); + }); + +}); + +describe('env', () => { + it('should exist', done => { + should.exist(util.env); + should.exist(util.env._); + done(); + }); +}); + +describe('noop()', () => { + it('should return a stream', done => { + util.isStream(util.noop()).should.equal(true); + done(); + }); + it('should return a stream that passes through all data', done => { + var inp = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + var stream = util.noop(); + es.readArray(inp) + .pipe(stream) + .pipe(es.writeArray((err: Error, arr: any[]) => { + should.not.exist(err); + should.exist(arr); + arr.should.eql(inp); + done(); + })); + }); +}); + +describe('beep()', () => { + it('should send the right code to stdout', done => { + var writtenValue = ''; + + util.beep(); + writtenValue.should.equal('\x07'); + + done(); + }); +}); + +describe('isStream()', () => { + it('should work on a stream', done => { + util.isStream(through()).should.equal(true); + done(); + }); + it('should not work on a buffer', done => { + util.isStream(new Buffer('huh')).should.equal(false); + done(); + }); +}); + +describe('isBuffer()', () => { + it('should work on a buffer', done => { + util.isBuffer(new Buffer('huh')).should.equal(true); + done(); + }); + it('should not work on a stream', done => { + util.isBuffer(through()).should.equal(false); + done(); + }); +}); + +describe('isNull()', () => { + it('should work on a null', done => { + util.isNull(null).should.equal(true); + done(); + }); + it('should not work on a stream', done => { + util.isNull(through()).should.equal(false); + done(); + }); + it('should not work on undefined', done => { + util.isNull(undefined).should.equal(false); + done(); + }); +}); + +// linefeed +declare var lines: string[]; +lines.join(util.linefeed); + +describe('combine()', () => { + it('should return a function', done => { + var src = [1, 2, 3]; + var inp = es.readArray(src); + var factory = util.combine(inp); + factory.should.be.type('function'); + done(); + }); + it('should return a function that returns a stream combination', done => { + var src = [1, 2, 3]; + var inp = es.readArray(src); + var inp2 = es.writeArray((err: Error, data: any[]) => { + should.not.exist(err); + data.should.eql(src); + done(); + }); + var factory = util.combine(inp, inp2); + factory().should.be.instanceof(Stream.Readable); + }); + it('should return a function that returns a stream combination when given an array', done => { + var src = [1, 2, 3]; + var inp = es.readArray(src); + var inp2 = es.writeArray((err: Error, data: any[]) => { + should.not.exist(err); + data.should.eql(src); + done(); + }); + var factory = util.combine([inp, inp2]); + factory().should.be.instanceof(Stream.Readable); + }); +}); + +describe('buffer()', () => { + it('should buffer stuff and return an array into the callback', done => { + var src = [1, 2, 3]; + var inp = es.readArray(src); + inp.pipe(util.buffer((err: Error, data: any[]) => { + should.not.exist(err); + should.exist(data); + data.should.eql(src); + done(); + })); + }); + it('should buffer stuff and emit it as a data event', done => { + var src = [1, 2, 3]; + var inp = es.readArray(src); + inp.pipe(util.buffer()).on('data', (data: any[]) => { + should.exist(data); + data.should.eql(src); + done(); + }); + }); + it('should buffer stuff and return a stream with the buffered data', done => { + var src = [1, 2, 3]; + var inp = es.readArray(src); + inp.pipe(util.buffer()).pipe(es.through((data: any[]) => { + should.exist(data); + data.should.eql(src); + done(); + })); + }); +}); + +describe('PluginError()', () => { + it('should default name to Error', () => { + var err = new util.PluginError('test', 'something broke'); + err.name.should.equal('Error'); + }); + + it('should default name to Error, even when wrapped error has no name', () => { + var realErr = { message: 'something broke' }; + var err = new util.PluginError('test', realErr); + err.name.should.equal('Error'); + }); + + it('should print the plugin name in toString', () => { + var err = new util.PluginError('test', 'something broke'); + err.toString().indexOf('test').should.not.equal(-1); + }); + + it('should not include the stack by default in toString', () => { + var err = new util.PluginError('test', 'something broke'); + // just check that there are no 'at' lines + err.toString().indexOf('at').should.equal(-1); + }); + + it('should include the stack when specified in toString', () => { + var err = new util.PluginError('test', 'something broke', { stack: "at huh", showStack: true }); + // just check that there are 'at' lines + err.toString().indexOf('at').should.not.equal(-1); + }); + + it('should take arguments as one object', () => { + var err = new util.PluginError({ + plugin: 'test', + message: 'something broke' + }); + err.plugin.should.equal('test'); + err.message.should.equal('something broke'); + }); + + it('should take arguments as plugin name and one object', () => { + var err = new util.PluginError('test', { + message: 'something broke' + }); + err.plugin.should.equal('test'); + err.message.should.equal('something broke'); + }); + + it('should take arguments as plugin name and message', () => { + var err = new util.PluginError('test', 'something broke'); + err.plugin.should.equal('test'); + err.message.should.equal('something broke'); + }); + + it('should take arguments as plugin name, message, and one object', () => { + var err = new util.PluginError('test', 'something broke', { showStack: true }); + err.plugin.should.equal('test'); + err.message.should.equal('something broke'); + err.showStack.should.equal(true); + }); + + it('should take arguments as plugin name, error, and one object', () => { + var realErr = new Error('something broke'); + (realErr).fileName = 'original.js'; + var err = new util.PluginError('test', realErr, { showStack: true, fileName: 'override.js' }); + err.plugin.should.equal('test'); + err.message.should.equal('something broke'); + err.fileName.should.equal('override.js'); + err.showStack.should.equal(true); + }); + + it('should take properties from error', () => { + var realErr = new Error('something broke'); + (realErr).abstractProperty = 'abstract'; + var err = new util.PluginError('test', realErr); + err.plugin.should.equal('test'); + err.message.should.equal('something broke'); + (err).abstractProperty.should.equal('abstract'); + }); + + it('should be configured to show properties by default', () => { + var err = new util.PluginError('test', 'something broke'); + err.showProperties.should.be.true; + }); + + it('should not be configured to take option to show properties', () => { + var err = new util.PluginError('test', 'something broke', { showProperties: false }); + err.showProperties.should.be.false; + }); + + it('should show properties', () => { + var err = new util.PluginError('test', 'it broke', { showProperties: true }); + err.fileName = 'original.js'; + err.lineNumber = 35; + err.toString().indexOf('it broke').should.not.equal(-1); + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.not.equal(-1); + }); + + it('should show properties', () => { + var realErr = new Error('something broke'); + (realErr).fileName = 'original.js'; + (realErr).lineNumber = 35; + var err = new util.PluginError('test', realErr, { showProperties: true }); + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.not.equal(-1); + }); + + it('should not show properties', () => { + var realErr = new Error('something broke'); + (realErr).fileName = 'original.js'; + (realErr).lineNumber = 35; + var err = new util.PluginError('test', realErr, { showProperties: false }); + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.equal(-1); + }); + + it('should not show properties, but should show stack', () => { + var err = new util.PluginError('test', 'it broke', { stack: 'test stack', showStack: true, showProperties: false }); + err.fileName = 'original.js'; + err.lineNumber = 35; + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.equal(-1); + err.toString().indexOf('test stack').should.not.equal(-1); + }); + + it('should not show properties, but should show stack for real error', () => { + var realErr = new Error('something broke'); + (realErr).fileName = 'original.js'; + (realErr).lineNumber = 35; + (realErr).stack = 'test stack'; + var err = new util.PluginError('test', realErr, { showStack: true, showProperties: false }); + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.equal(-1); + err.toString().indexOf('test stack').should.not.equal(-1); + }); + + it('should not show properties, but should show stack for _stack', () => { + var realErr = new Error('something broke'); + (realErr).fileName = 'original.js'; + (realErr).lineNumber = 35; + (realErr)._stack = 'test stack'; + var err = new util.PluginError('test', realErr, { showStack: true, showProperties: false }); + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.equal(-1); + err.toString().indexOf('test stack').should.not.equal(-1); + }); + + it('should show properties and stack', () => { + var realErr = new Error('something broke'); + (realErr).fileName = 'original.js'; + (realErr).stack = 'test stack'; + var err = new util.PluginError('test', realErr, { showStack: true }); + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.not.equal(-1); + err.toString().indexOf('test stack').should.not.equal(-1); + }); + + it('should show properties added after the error is created', () => { + var realErr = new Error('something broke'); + var err = new util.PluginError('test', realErr); + err.fileName = 'original.js'; + err.toString().indexOf('message:').should.equal(-1); + err.toString().indexOf('fileName:').should.not.equal(-1); + }); + + it('should toString quickly', function(done) { + this.timeout(100); + + var err = new util.PluginError('test', 'it broke', { showStack: true }); + var str = err.toString(); + + done(); + }); + + it('should toString quickly with original error', function(done) { + this.timeout(100); + + var realErr = new Error('it broke'); + var err = new util.PluginError('test', realErr, { showStack: true }); + var str = err.toString(); + + done(); + }); + + it('should not show "Details:" if there are no properties to show', () => { + var err = new util.PluginError('plugin', 'message'); + err.toString().indexOf('Details:').should.equal(-1); + }); +}); diff --git a/gulp-util/gulp-util.d.ts b/gulp-util/gulp-util.d.ts new file mode 100644 index 000000000..33ea20f79 --- /dev/null +++ b/gulp-util/gulp-util.d.ts @@ -0,0 +1,138 @@ +// Type definitions for gulp-util v3.0.x +// Project: https://github.com/gulpjs/gulp-util +// Definitions by: jedmao +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/// +/// +/// +/// + +declare module 'gulp-util' { + + import vinyl = require('vinyl'); + import chalk = require('chalk'); + import through2 = require('through2'); + + export class File extends vinyl { } + + /** + * Replaces a file extension in a path. Returns the new path. + */ + export function replaceExtension(npath: string, ext: string): string; + + export var colors: typeof chalk; + + export var date: { + (now?: Date, mask?: string, convertLocalTimeToUTC?: boolean): any; + (date?: string, mask?: string, convertLocalTimeToUTC?: boolean): any; + masks: any; + }; + + /** + * Logs stuff. Already prefixed with [gulp] and all that. Use the right colors + * for values. If you pass in multiple arguments it will join them by a space. + */ + export function log(message?: any, ...optionalParams: any[]): void; + + /** + * 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 for more info. + */ + export function template(tmpl: string): (opt: { file: { path: string } }) => string; + export function template(tmpl: string, opt: { file: { path: string } }): string; + + export var env: any; + + export function beep(): void; + + /** + * Returns a stream that does nothing but pass data straight through. + */ + export var noop: typeof through2; + + export function isStream(obj: any): boolean; + + export function isBuffer(obj: any): boolean; + + export function isNull(obj: any): boolean; + + export var linefeed: string; + + export function combine(streams: NodeJS.ReadWriteStream[]): () => NodeJS.ReadWriteStream; + export function combine(...streams: NodeJS.ReadWriteStream[]): () => NodeJS.ReadWriteStream; + + /** + * 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). + */ + export function buffer(cb?: (err: Error, data: any[]) => void): NodeJS.ReadWriteStream; + + export class PluginError implements Error, PluginErrorOptions { + constructor(options?: PluginErrorOptions); + constructor(pluginName: string, options?: PluginErrorOptions); + constructor(pluginName: string, message: string, options?: PluginErrorOptions); + constructor(pluginName: string, message: Error, options?: PluginErrorOptions); + /** + * The module name of your plugin. + */ + name: string; + /** + * Can be a string or an existing error. + */ + message: any; + fileName: string; + lineNumber: number; + /** + * You need to include the message along with this stack. If you pass an + * error in as the message the stack will be pulled from that, otherwise one + * will be created. + */ + stack: string; + /** + * By default the stack will not be shown. Set this to true if you think the + * stack is important for your error. + */ + showStack: boolean; + /** + * Error properties will be included in err.toString(). Can be omitted by + * setting this to false. + */ + showProperties: boolean; + plugin: string; + error: Error; + } + +} + +interface PluginErrorOptions { + /** + * The module name of your plugin. + */ + name?: string; + /** + * Can be a string or an existing error. + */ + message?: any; + fileName?: string; + lineNumber?: number; + /** + * You need to include the message along with this stack. If you pass an + * error in as the message the stack will be pulled from that, otherwise one + * will be created. + */ + stack?: string; + /** + * By default the stack will not be shown. Set this to true if you think the + * stack is important for your error. + */ + showStack?: boolean; + /** + * Error properties will be included in err.toString(). Can be omitted by + * setting this to false. + */ + showProperties?: boolean; + plugin?: string; + error?: Error; +} diff --git a/should/should.d.ts b/should/should.d.ts index 27650cc3f..a787b622c 100644 --- a/should/should.d.ts +++ b/should/should.d.ts @@ -87,8 +87,8 @@ interface ShouldAssertion { interface ShouldInternal { // should.js's extras - exist(actual: any): void; - exists(actual: any): void; + exist(actual: any, msg?: string): void; + exists(actual: any, msg?: string): void; not: ShouldInternal; } diff --git a/through2/through2.d.ts b/through2/through2.d.ts index 95cedf752..7481fa910 100644 --- a/through2/through2.d.ts +++ b/through2/through2.d.ts @@ -11,11 +11,11 @@ declare module 'through2' { function through2(transform?: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; - function through2(opts: stream.DuplexOptions, transform?: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; + function through2(opts?: stream.DuplexOptions, transform?: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; module through2 { - export function obj(transform: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; + export function obj(transform?: (chunk: any, enc: string, callback: () => void) => void, flush?: () => void): NodeJS.ReadWriteStream; export function push(data: any): void; diff --git a/vinyl/vinyl.d.ts b/vinyl/vinyl.d.ts index 708f2c791..81aa781f9 100644 --- a/vinyl/vinyl.d.ts +++ b/vinyl/vinyl.d.ts @@ -72,7 +72,7 @@ declare module 'vinyl' { /** * Returns a new File object with all attributes cloned. Custom attributes are deep-cloned. */ - public clone(): File; + public clone(opts?: { contents?: boolean }): File; /** * If file.contents is a Buffer, it will write it to the stream.