initial commit
This commit is contained in:
commit
d3fcd7f10c
3159 files changed
+349702
No files matched your search
+232
@@ -0,0 +1,232 @@
|
||||
## gulp API docs
|
||||
|
||||
### gulp.src(globs[, options])
|
||||
|
||||
Takes a glob and represents a file structure. Can be piped to plugins.
|
||||
|
||||
```javascript
|
||||
gulp.src('./client/templates/*.jade')
|
||||
.pipe(jade())
|
||||
.pipe(minify())
|
||||
.pipe(gulp.dest('./build/minified_templates'));
|
||||
```
|
||||
|
||||
#### globs
|
||||
Type: `String` or `Array`
|
||||
|
||||
Glob or globs to read.
|
||||
|
||||
#### options
|
||||
Type: `Object`
|
||||
|
||||
Options to pass to [node-glob] through [glob-stream].
|
||||
|
||||
gulp adds two additional options in addition to the [options supported by node-glob][node-glob documentation]:
|
||||
|
||||
#### options.buffer
|
||||
Type: `Boolean`
|
||||
Default: `true`
|
||||
|
||||
Setting this to `false` will return `file.contents` as a stream and not buffer files. This is useful when working with large files. **Note:** Plugins may not implement support for streams.
|
||||
|
||||
#### options.read
|
||||
Type: `Boolean`
|
||||
Default: `true`
|
||||
|
||||
Setting this to `false` will return `file.contents` as null and not read the file at all.
|
||||
|
||||
|
||||
### gulp.dest(path)
|
||||
|
||||
Can be piped to and it will write files. Re-emits all data passed to it so you can pipe to multiple folders.
|
||||
|
||||
```javascript
|
||||
gulp.src('./client/templates/*.jade')
|
||||
.pipe(jade())
|
||||
.pipe(gulp.dest('./build/templates'))
|
||||
.pipe(minify())
|
||||
.pipe(gulp.dest('./build/minified_templates'));
|
||||
```
|
||||
|
||||
#### path
|
||||
Type: `String`
|
||||
|
||||
The path (folder) to write files to.
|
||||
|
||||
|
||||
### gulp.task(name[, deps], fn)
|
||||
|
||||
Define a task using [Orchestrator].
|
||||
|
||||
```javascript
|
||||
gulp.task('somename', function() {
|
||||
// Do stuff
|
||||
});
|
||||
```
|
||||
|
||||
#### name
|
||||
|
||||
The name of the task. Tasks that you want to run from the command line should not have spaces in them.
|
||||
|
||||
#### deps
|
||||
Type: `Array`
|
||||
|
||||
An array of tasks to be executed and completed before your task will run.
|
||||
|
||||
```javascript
|
||||
gulp.task('mytask', ['array', 'of', 'task', 'names'], function() {
|
||||
// Do stuff
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** Are your tasks running before the dependencies are complete? Make sure your dependency tasks
|
||||
are correctly using the async run hints: take in a callback or return a promise or event stream.
|
||||
|
||||
#### fn
|
||||
|
||||
The function that performs the task's operations. Generally this takes the form of `gulp.src().pipe(someplugin())`.
|
||||
|
||||
#### Async task support
|
||||
|
||||
Tasks can be made asynchronous if its `fn` does one of the following:
|
||||
|
||||
##### Accept a callback
|
||||
|
||||
```javascript
|
||||
gulp.task('somename', function(cb) {
|
||||
// Do stuff
|
||||
cb(err);
|
||||
});
|
||||
```
|
||||
|
||||
##### Return a stream
|
||||
|
||||
```javascript
|
||||
gulp.task('somename', function() {
|
||||
var stream = gulp.src('./client/**/*.js')
|
||||
.pipe(minify())
|
||||
.pipe(gulp.dest('/build'));
|
||||
return stream;
|
||||
});
|
||||
```
|
||||
|
||||
##### Return a promise
|
||||
|
||||
```javascript
|
||||
var Q = require('q');
|
||||
|
||||
gulp.task('somename', function() {
|
||||
var deferred = Q.defer();
|
||||
|
||||
// Do async stuff
|
||||
setTimeout(function() {
|
||||
deferred.resolve();
|
||||
}, 1);
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** By default, tasks run with maximum concurrency -- e.g. it launches all the tasks at once and waits for nothing.
|
||||
If you want to create a series where tasks run in a particular order, you need to do two things:
|
||||
|
||||
- give it a hint to tell it when the task is done,
|
||||
- and give it a hint that a task depends on completion of another.
|
||||
|
||||
For these examples, let's presume you have two tasks, "one" and "two" that you specifically want to run in this order:
|
||||
|
||||
1. In task "one" you add a hint to tell it when the task is done. Either take in a callback and call it when you're
|
||||
done or return a promise or stream that the engine should wait to resolve or end respectively.
|
||||
|
||||
2. In task "two" you add a hint telling the engine that it depends on completion of the first task.
|
||||
|
||||
So this example would look like this:
|
||||
|
||||
```javascript
|
||||
var gulp = require('gulp');
|
||||
|
||||
// takes in a callback so the engine knows when it'll be done
|
||||
gulp.task('one', function (cb) {
|
||||
// do stuff -- async or otherwise
|
||||
cb(err); // if err is not null and not undefined, the run will stop, and note that it failed
|
||||
});
|
||||
|
||||
// identifies a dependent task must be complete before this one begins
|
||||
gulp.task('two', ['one'], function () {
|
||||
// task 'one' is done now
|
||||
});
|
||||
|
||||
gulp.task('default', ['one', 'two']);
|
||||
```
|
||||
|
||||
|
||||
### gulp.watch(glob [, opts], tasks) or gulp.watch(glob [, opts, cb])
|
||||
|
||||
Watch files and do something when a file changes. This always returns an EventEmitter that emits `changed` events.
|
||||
|
||||
### gulp.watch(glob[, opts], tasks)
|
||||
|
||||
#### glob
|
||||
Type: `String` or `Array`
|
||||
|
||||
A single glob or array of globs that indicate which files to watch for changes.
|
||||
|
||||
#### opts
|
||||
Type: `Object`
|
||||
|
||||
Options, that are passed to [`gaze`](https://github.com/shama/gaze).
|
||||
|
||||
#### tasks
|
||||
Type: `Array`
|
||||
|
||||
Names of task(s) to run when a file changes, added with `gulp.task()`
|
||||
|
||||
```javascript
|
||||
var watcher = gulp.watch('js/**/*.js', ['uglify','reload']);
|
||||
watcher.on('changed', function(event){
|
||||
console.log('File '+event.path+' was '+event.type+', running tasks...');
|
||||
});
|
||||
```
|
||||
|
||||
### gulp.watch(glob[, opts, cb])
|
||||
|
||||
#### glob
|
||||
Type: `String` or `Array`
|
||||
|
||||
A single glob or array of globs that indicate which files to watch for changes.
|
||||
|
||||
#### opts
|
||||
Type: `Object`
|
||||
|
||||
Options, that are passed to [`gaze`](https://github.com/shama/gaze).
|
||||
|
||||
#### cb(event)
|
||||
Type: `Function`
|
||||
|
||||
Callback to be called on each change.
|
||||
|
||||
```javascript
|
||||
gulp.watch('js/**/*.js', function(event) {
|
||||
console.log('File '+event.path+' was '+event.type+', running tasks...');
|
||||
});
|
||||
```
|
||||
|
||||
The callback will be passed an object, `event`, that describes the change:
|
||||
|
||||
##### event.type
|
||||
Type: `String`
|
||||
|
||||
The type of change that occurred, either `added`, `changed` or `deleted`.
|
||||
|
||||
##### event.path
|
||||
Type: `String`
|
||||
|
||||
The path to the file that triggered the event.
|
||||
|
||||
|
||||
[node-optimist]: https://github.com/substack/node-optimist
|
||||
[node-glob documentation]: https://github.com/isaacs/node-glob#options
|
||||
[node-glob]: https://github.com/isaacs/node-glob
|
||||
[glob-stream]: https://github.com/wearefractal/glob-stream
|
||||
[gulp-if]: https://github.com/robrich/gulp-if
|
||||
[Orchestrator]: https://github.com/robrich/orchestrator
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
## gulp CLI docs
|
||||
|
||||
### Flags
|
||||
|
||||
gulp has very few flags to know about. All other flags are for tasks to use if needed.
|
||||
|
||||
- `-V` or `--version` will display the global and local gulp versions
|
||||
- `--require <module path>` will require a module before running the gulpfile. This is useful for transpilers but also has other applications. You can use multiple `--require` flags
|
||||
- `--gulpfile <gulpfile path>` manually set path of gulpfile. Useful if you have multiple gulpfiles. This will set the CWD to the gulpfile directory as well.
|
||||
- `--cwd <dir path>` manually set the CWD. The search for the gulpfile, as well as the relativity of all requires will be from here.
|
||||
- `-T` or `--tasks` will display the task dependency tree for the loaded gulpfile
|
||||
|
||||
### Tasks
|
||||
|
||||
Tasks can be executed by running `gulp <task> <othertask>`. Just running `gulp` will execute the task you registered called `default`. If there is no `default` task gulp will error.
|
||||
|
||||
### Compilers
|
||||
|
||||
You can use any language you want for your gulpfile. You will have to specify the language module name so the CLI can load it (and its associated extensions) before attempting to find your gulpfile. Make sure you have this module installed accessible by the folder you are running the CLI in.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
gulp dosomething --require coffee-script/register
|
||||
```
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
# FAQ
|
||||
|
||||
## Why gulp? Why not ____?
|
||||
|
||||
See the [gulp introduction slideshow] for a rundown on how gulp came to be.
|
||||
|
||||
## Is it "gulp" or "Gulp"?
|
||||
|
||||
gulp is always lowercase.
|
||||
|
||||
## Where can I find a list of gulp plugins?
|
||||
|
||||
gulp plugins always include the `gulpplugin` keyword. [Search gulp plugins][search-gulp-plugins] or [view all plugins][npm plugin search].
|
||||
|
||||
## I want to write a gulp plugin, how do I get started?
|
||||
|
||||
See the [Writing a gulp plugin] wiki page for guidelines and an example to get you started.
|
||||
|
||||
## My plugin does ____, is it doing too much?
|
||||
|
||||
Probably. Ask yourself:
|
||||
|
||||
1. Is my plugin doing something that other plugins may need to do?
|
||||
- If so, that piece of functionality should be a separate plugin. [Check if it already exists on npm][npm plugin search].
|
||||
1. Is my plugin doing two, completely different things based on a configuration option?
|
||||
- If so, it may serve the community better to release it as two separate plugins
|
||||
- If the two tasks are different, but very closely related, it's probably OK
|
||||
|
||||
## How should newlines be represented in plugin output?
|
||||
|
||||
Always use gulp-util.newline (which is \n) to prevent diff issues between operating systems.
|
||||
|
||||
## Where can I get updates on gulp?
|
||||
|
||||
gulp updates can be found on the following twitters:
|
||||
|
||||
- [@wearefractal](https://twitter.com/wearefractal)
|
||||
- [@eschoff](https://twitter.com/eschoff)
|
||||
- [@funkytek](https://twitter.com/funkytek)
|
||||
- [@gulpjs](https://twitter.com/gulpjs)
|
||||
|
||||
## Does gulp have an IRC channel?
|
||||
|
||||
Yes, come chat with us in #gulpjs on [Freenode].
|
||||
|
||||
[Writing a gulp plugin]: writing-a-plugin/README.md
|
||||
[gulp introduction slideshow]: http://slid.es/contra/gulp
|
||||
[Freenode]: http://freenode.net/
|
||||
[search-gulp-plugins]: http://gratimax.github.io/search-gulp-plugins/
|
||||
[npm plugin search]: https://npmjs.org/browse/keyword/gulpplugin
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
# gulp documentation
|
||||
|
||||
* [Getting Started](getting-started.md) - How to get going with gulp
|
||||
* [API documentation](API.md) - Learn the ins and outs of using gulp
|
||||
* [CLI documentation](CLI.md) - Learn how to call tasks and use compilers
|
||||
* [Writing a Plugin](writing-a-plugin/README.md) - So you're writing a gulp plugin? Go here for the essential dos and don'ts.
|
||||
|
||||
## FAQ
|
||||
|
||||
See [the FAQ](FAQ.md) for the answers to commonly asked questions.
|
||||
|
||||
## Recipes
|
||||
|
||||
The community has compiled guides on how to use gulp for common use cases. Check out the [recipes folder](recipes) for a full list.
|
||||
|
||||
## Articles
|
||||
|
||||
* [Introduction to node.js streams](https://github.com/substack/stream-handbook)
|
||||
* [Video introduction to node.js streams](http://www.youtube.com/watch?v=QgEuZ52OZtU)
|
||||
* [Getting started with gulp (by @markgdyr)](http://markgoodyear.com/2014/01/getting-started-with-gulp/)
|
||||
* [Why you shouldn’t create a gulp plugin (or, how to stop worrying and learn to love existing node packages)](http://blog.overzealous.com/post/74121048393/why-you-shouldnt-create-a-gulp-plugin-or-how-to-stop)
|
||||
* [Inspiration (slides) about why gulp was made](http://slid.es/contra/gulp)
|
||||
|
||||
## License
|
||||
|
||||
All the documentation is covered by the CC0 license *(do whatever you want with it - public domain)*.
|
||||
|
||||
[](http://creativecommons.org/publicdomain/zero/1.0/)
|
||||
|
||||
To the extent possible under law, [Fractal](http://wearefractal.com) has waived all copyright and related or neighboring rights to this work.
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
## Getting Started
|
||||
|
||||
### 1. Install gulp globally:
|
||||
|
||||
```
|
||||
npm install -g gulp
|
||||
```
|
||||
|
||||
### 2. Install gulp and gulp-util in your project devDependencies:
|
||||
|
||||
```
|
||||
npm install --save-dev gulp gulp-util
|
||||
```
|
||||
|
||||
### 3. Create a `gulpfile.js` at the root of your project:
|
||||
|
||||
```javascript
|
||||
var gulp = require('gulp');
|
||||
var gutil = require('gulp-util');
|
||||
|
||||
gulp.task('default', function(){
|
||||
// place code for your default task here
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Run gulp
|
||||
|
||||
```
|
||||
gulp
|
||||
```
|
||||
|
||||
The default task will run and do nothing.
|
||||
|
||||
To run individual tasks, use `gulp <task> <othertask>`
|
||||
|
||||
## Where do I go now?
|
||||
|
||||
You have an empty gulpfile and everything is installed. How do you REALLY get started? Check out the [recipes and articles section](README.md#articles-and-recipes) for more information
|
||||
|
||||
## .src, .watch, .dest, CLI args - How do I use these things?
|
||||
|
||||
For API specific documentation you can check out the [documentation for that](API.md)
|
||||
|
||||
## Available Plugins
|
||||
|
||||
The gulp community is growing, with new plugins being added daily. See the [main website](http://gulpjs.com/) for a complete list.
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
# Combining streams to handle errors #
|
||||
|
||||
By default, emitting an error on a stream will cause it to be thrown
|
||||
unless it already has a listener attached to the `error` event. This
|
||||
gets a bit tricky when you're working with longer pipelines of streams.
|
||||
|
||||
By using [gulp-util](https://github.com/gulpjs/gulp-util)'s `combine`
|
||||
method you can turn a series of streams into a single stream, meaning you
|
||||
only need to listen to the `error` event in one place in your code.
|
||||
|
||||
Here's an example of using it in a gulpfile:
|
||||
|
||||
``` javascript
|
||||
var combine = require('gulp-util').combine
|
||||
var uglify = require('gulp-uglify')
|
||||
var gulp = require('gulp')
|
||||
|
||||
gulp.task('test', function() {
|
||||
var combined = combine(
|
||||
gulp.src('bootstrap/js/*.js'),
|
||||
uglify(),
|
||||
gulp.dest('public/bootstrap')
|
||||
)
|
||||
|
||||
// any errors in the above streams
|
||||
// will get caught by this listener,
|
||||
// instead of being thrown:
|
||||
combined.on('error', function(err) {
|
||||
console.warn(err.message)
|
||||
})
|
||||
|
||||
return combined
|
||||
})
|
||||
```
|
||||
|
||||
You can use this technique in your gulp plugins and node modules too using
|
||||
the [multipipe](http://npmjs.org/package/multipipe) module, and is a generally useful means of ensuring that errors aren't thrown from inaccessible streams
|
||||
somewhere deep inside `./node_modules`.
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
# Mocha test-runner with gulp
|
||||
|
||||
### Passing shared module in all tests
|
||||
|
||||
```js
|
||||
var gulp = require('gulp');
|
||||
var mocha = require('gulp-mocha');
|
||||
|
||||
gulp.task('tests', function() {
|
||||
return gulp.src(['test/test-*.js'], { read: false })
|
||||
.pipe(mocha({
|
||||
reporter: 'spec',
|
||||
globals: {
|
||||
should: require('should')
|
||||
}
|
||||
}));
|
||||
});
|
||||
```
|
||||
|
||||
### Running mocha tests when files change
|
||||
|
||||
With bundled `gulp.watch` and [`gulp-batch`](https://github.com/floatdrop/gulp-batch) (see readme of gulp-batch for reasons):
|
||||
|
||||
```js
|
||||
// npm install gulp gulp-watch gulp-mocha gulp-batch
|
||||
|
||||
var gulp = require('gulp');
|
||||
var mocha = require('gulp-mocha');
|
||||
var batch = require('gulp-batch');
|
||||
var gutil = require('gulp-util');
|
||||
|
||||
gulp.task('mocha', function () {
|
||||
return gulp.src(['test/*.js'], { read: false })
|
||||
.pipe(mocha({ reporter: 'list' }))
|
||||
.on('error', gutil.log);
|
||||
});
|
||||
|
||||
gulp.watch(['lib/**', 'test/**'], batch(function(events, cb) {
|
||||
gulp.run('mocha', cb);
|
||||
}));
|
||||
```
|
||||
|
||||
With [`gulp-watch`](https://github.com/floatdrop/gulp-watch) plugin:
|
||||
|
||||
```js
|
||||
// npm i gulp gulp-watch gulp-mocha
|
||||
|
||||
var gulp = require('gulp');
|
||||
var mocha = require('gulp-mocha');
|
||||
var watch = require('gulp-watch');
|
||||
var gutil = require('gulp-util')
|
||||
|
||||
gulp.task('mocha', function () {
|
||||
return gulp.src(['test/*.js'], { read: false })
|
||||
.pipe(mocha({ reporter: 'list' }))
|
||||
.on('error', gutil.log);
|
||||
});
|
||||
|
||||
gulp.task('watch', function() {
|
||||
return gulp.src(['lib/**', 'test/**'], { read: false })
|
||||
.pipe(watch(function(events, cb) {
|
||||
gulp.run('mocha', cb);
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('default', ['mocha', 'watch']);
|
||||
|
||||
// run `gulp watch` or just `gulp` for watching and rerunning tests
|
||||
```
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# Only pass through changed files
|
||||
|
||||
Files are passed through the whole pipe chain on every run by default. By using [gulp-changed](https://github.com/sindresorhus/gulp-changed) only changed files will be passed through. This can speed up consecutive runs considerably.
|
||||
|
||||
|
||||
```js
|
||||
// run `npm install gulp gulp-changed gulp-jscs gulp-uglify`
|
||||
var gulp = require('gulp');
|
||||
var changed = require('gulp-changed');
|
||||
var jscs = require('gulp-jscs');
|
||||
var uglify = require('gulp-uglify');
|
||||
|
||||
// we define some constants here so they can be reused
|
||||
var SRC = 'src/*.js';
|
||||
var DEST = 'dist';
|
||||
|
||||
gulp.task('default', function () {
|
||||
return gulp.src(SRC)
|
||||
// the `changed` task needs to know the destination directory
|
||||
// upfront to be able to figure out which files changed
|
||||
.pipe(changed(DEST))
|
||||
// only files that has changed will pass through here
|
||||
.pipe(jscs())
|
||||
.pipe(uglify())
|
||||
.pipe(gulp.dest(DEST));
|
||||
});
|
||||
```
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Pass parameters from the command line
|
||||
## bonus: keeping those tasks DRY
|
||||
|
||||
---
|
||||
|
||||
`gulpfile.js`
|
||||
|
||||
```js
|
||||
// npm install gulp gulp-util gulp-if gulp-uglify
|
||||
var gulp = require('gulp');
|
||||
var gutil = require('gulp-util');
|
||||
var gulpif = require('gulp-if');
|
||||
var uglify = require('gulp-uglify');
|
||||
|
||||
var isProduction = gutil.env.type === 'production';
|
||||
|
||||
gulp.task('scripts', function () {
|
||||
return gulp.src('**/*.js')
|
||||
.pipe(gulpif(isProduction, uglify())) // only minify if production
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
`cli`
|
||||
|
||||
`gulp scripts --type production`
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Rebuild only files that change
|
||||
|
||||
With [`gulp-watch`](https://github.com/floatdrop/gulp-watch):
|
||||
|
||||
```js
|
||||
var gulp = require('gulp');
|
||||
var sass = require('gulp-sass');
|
||||
var watch = require('gulp-watch');
|
||||
|
||||
gulp.task('default', function() {
|
||||
return gulp.src('./sass/*.scss')
|
||||
.pipe(watch())
|
||||
.pipe(sass())
|
||||
.pipe(gulp.dest('./dist/'));
|
||||
});
|
||||
```
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# Running tasks in series
|
||||
|
||||
By default, tasks run with maximum concurrency -- e.g. it launches all the tasks at once and waits for nothing.
|
||||
If you want to create a series where tasks run in a particular order, you need to do two things:
|
||||
|
||||
- give it a hint to tell it when the task is done,
|
||||
- and give it a hint that a task depends on completion of another.
|
||||
|
||||
For these examples, let's presume you have two tasks, "one" and "two" that you specifically want to run in this order:
|
||||
|
||||
1. In task "one" you add a hint to tell it when the task is done. Either take in a callback and call it when you're
|
||||
done or return a promise or stream that the engine should wait to resolve or end respectively.
|
||||
|
||||
2. In task "two" you add a hint telling the engine that it depends on completion of the first task.
|
||||
|
||||
So this example would look like this:
|
||||
|
||||
```javascript
|
||||
var gulp = require('gulp');
|
||||
|
||||
// takes in a callback so the engine knows when it'll be done
|
||||
gulp.task('one', function (cb) {
|
||||
// do stuff -- async or otherwise
|
||||
cb(err); // if err is not null and not undefined, the orchestration will stop, and 'two' will not run
|
||||
});
|
||||
|
||||
// identifies a dependent task must be complete before this one begins
|
||||
gulp.task('two', ['one'], function () {
|
||||
// task 'one' is done now
|
||||
});
|
||||
|
||||
gulp.task('default', ['one', 'two']);
|
||||
// alternatively: gulp.task('default', ['two']);
|
||||
```
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# Specifying a new cwd (current working directory)
|
||||
|
||||
This is helpful for projects using a nested directory structure, such as:
|
||||
|
||||
```
|
||||
/project
|
||||
/layer1
|
||||
/layer2
|
||||
```
|
||||
|
||||
You can use the gulp CLI option `--cwd`
|
||||
|
||||
From the `project/` directory
|
||||
|
||||
```bash
|
||||
gulp --cwd ./layer1/
|
||||
```
|
||||
|
||||
Another option is to use `process.chdir` which is just vanilla node.
|
||||
|
||||
`gulpfile.js`
|
||||
|
||||
```js
|
||||
var gulp = require('gulp');
|
||||
|
||||
try {
|
||||
process.chdir(gulp.env.cwd);
|
||||
} catch (err) {
|
||||
console.error('Unable to chdir to %s', gulp.env.cwd);
|
||||
}
|
||||
```
|
||||
|
||||
If you only need to specify a cwd for a certain glob, you can use the `cwd` option on a [glob-stream](https://github.com/wearefractal/glob-stream)
|
||||
|
||||
```js
|
||||
gulp.src('./some/dir/**/*.js', { cwd: './public' });
|
||||
```
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# Using coffee-script for gulpfile
|
||||
|
||||
As discussed in [issue #103](https://github.com/gulpjs/gulp/issues/103), there are 2 ways to do this.
|
||||
|
||||
1. Use `gulp --require coffee-script/register` at the command line
|
||||
|
||||
2. Require in `gulpfile.coffee` after requiring `coffee-script` in `gulpfile.js`
|
||||
|
||||
`gulpfile.js`
|
||||
|
||||
```js
|
||||
require('coffee-script/register');
|
||||
require('./gulpfile.coffee');
|
||||
```
|
||||
|
||||
`gulpfile.coffee`
|
||||
|
||||
```coffeescript
|
||||
gulp = require 'gulp'
|
||||
|
||||
gulp.task 'default', ->
|
||||
console.log('default task called')
|
||||
```
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# Using external config file
|
||||
## bonus: keeping those tasks DRY
|
||||
## bonus2: config.json can be used by another task runner, like `Grunt`
|
||||
|
||||
---
|
||||
|
||||
`config.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"desktop" : {
|
||||
"src" : [
|
||||
"dev/desktop/js/**/*.js",
|
||||
"!dev/desktop/js/vendor/**"
|
||||
],
|
||||
"dest" : "build/desktop/js"
|
||||
},
|
||||
"mobile" : {
|
||||
"src" : [
|
||||
"dev/mobile/js/**/*.js",
|
||||
"!dev/mobile/js/vendor/**"
|
||||
],
|
||||
"dest" : "build/mobile/js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
`gulpfile.js`
|
||||
|
||||
```js
|
||||
// npm install gulp gulp-uglify
|
||||
var gulp = require('gulp');
|
||||
var uglify = require('gulp-uglify');
|
||||
var config = require('./config.json');
|
||||
|
||||
function doStuff(cfg) {
|
||||
return gulp.src(cfg.src)
|
||||
.pipe(uglify())
|
||||
.pipe(gulp.dest(cfg.dest));
|
||||
}
|
||||
|
||||
gulp.task('dry', function () {
|
||||
doStuff(config.desktop);
|
||||
doStuff(config.mobile);
|
||||
});
|
||||
```
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
# Using multiple sources in one task
|
||||
|
||||
```js
|
||||
// npm install gulp event-stream
|
||||
|
||||
var gulp = require('gulp');
|
||||
var es = require('event-stream');
|
||||
|
||||
gulp.task('test', function(cb) {
|
||||
return es.concat(
|
||||
gulp.src('bootstrap/js/*.js')
|
||||
.pipe(gulp.dest('public/bootstrap')),
|
||||
gulp.src('jquery.cookie/jquery.cookie.js')
|
||||
.pipe(gulp.dest('public/jquery'))
|
||||
);
|
||||
});
|
||||
```
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
# Writing a plugin
|
||||
|
||||
If you plan to create your own Gulp plugin, you will save time by reading the full documentation.
|
||||
|
||||
* [Guidelines](guidelines.md) (a MUST read)
|
||||
* [Using buffers](using-buffers.md)
|
||||
* [Dealing with streams](dealing-with-streams.md)
|
||||
* [Testing](testing.md)
|
||||
* [README conventions](readme-conventions.md)
|
||||
|
||||
## What it does
|
||||
|
||||
### Streaming file objects
|
||||
|
||||
A gulp plugin always returns a stream in [object mode](http://nodejs.org/api/stream.html#stream_object_mode) that does the following:
|
||||
|
||||
1. Takes in [vinyl File objects](http://github.com/wearefractal/vinyl)
|
||||
2. Outputs [vinyl File objects](http://github.com/wearefractal/vinyl)
|
||||
|
||||
These are known as [transform streams](http://nodejs.org/api/stream.html#stream_class_stream_transform_1) (also sometimes called through streams). Transform streams are streams that are readable and writable which manipulate objects as they're being passed through.
|
||||
|
||||
### Modifying file content
|
||||
|
||||
Vinyl files can have 3 possible forms for the contents attribute:
|
||||
|
||||
- [Streams](dealing-with-streams.md)
|
||||
- [Buffers](using-buffers.md)
|
||||
- Empty (null) - Useful for things like rimraf, clean, where contents is not neeeded.
|
||||
|
||||
## Useful resources
|
||||
|
||||
* [File object](https://github.com/wearefractal/gulp-util/#new-fileobj)
|
||||
* [PluginError](https://github.com/gulpjs/gulp-util#new-pluginerrorpluginname-message-options)
|
||||
* [event-stream](https://github.com/dominictarr/event-stream)
|
||||
* [BufferStream](https://github.com/nfroidure/BufferStream)
|
||||
* [gulp-util](https://github.com/wearefractal/gulp-util)
|
||||
|
||||
|
||||
## Sample plugins
|
||||
|
||||
* [sindresorhus' gulp plugins](https://github.com/search?q=%40sindresorhus+gulp-)
|
||||
* [Fractal's gulp plugins](https://github.com/search?q=%40wearefractal+gulp-)
|
||||
* [gulp-replace](https://github.com/lazd/gulp-replace)
|
||||
|
||||
|
||||
## About streams
|
||||
|
||||
If you're unfamiliar with streams, you will need to read up on them:
|
||||
|
||||
* https://github.com/substack/stream-handbook (a MUST read)
|
||||
* http://nodejs.org/api/stream.html
|
||||
|
||||
Other libraries that are not file manipulating through streams but are made for use with gulp are tagged with the [gulpfriendly](https://npmjs.org/browse/keyword/gulpfriendly) keyword on npm.
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
# Dealing with streams
|
||||
|
||||
> It is highly recommended to write plugins supporting streams. Here is some information on creating a gulp plugin that supports streams.
|
||||
|
||||
> Make sure to follow the best practice regarging error handling and add the line that make the gulp plugin re-emit the first error catched during the transformation of the content
|
||||
|
||||
[Writing a Plugin](README.md) > Writing stream based plugins
|
||||
|
||||
## Dealing with streams
|
||||
|
||||
Let's implement a plugin prepending some text to files. This plugin supports all possible forms of file.contents.
|
||||
|
||||
```js
|
||||
var through = require('through2');
|
||||
var gutil = require('gulp-util');
|
||||
var PluginError = gutil.PluginError;
|
||||
|
||||
// Consts
|
||||
const PLUGIN_NAME = 'gulp-prefixer';
|
||||
|
||||
function prefixStream(prefixText) {
|
||||
var stream = through();
|
||||
stream.write(prefixText);
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Plugin level function (dealing with files)
|
||||
function gulpPrefixer(prefixText) {
|
||||
|
||||
if (!prefixText) {
|
||||
throw PluginError(PLUGIN_NAME, "Missing prefix text!");
|
||||
}
|
||||
prefixText = new Buffer(prefixText); // allocate ahead of time
|
||||
|
||||
// Creating a stream through which each file will pass
|
||||
var stream = through.obj(function (file, enc, callback) {
|
||||
if (file.isNull()) {
|
||||
this.push(file); // Do nothing if no contents
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (file.isBuffer()) {
|
||||
this.emit('error', new PluginError(PLUGIN_NAME, 'Buffers not supported!'));
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (file.isStream()) {
|
||||
// define the streamer that will transform the content
|
||||
var streamer = prefixStream(prefixText);
|
||||
// catch errors from the streamer and emit a gulp plugin error
|
||||
streamer.on('error', this.emit.bind(this, 'error'));
|
||||
// start the transformation
|
||||
file.contents = file.contents.pipe(streamer);
|
||||
// make sure the file goes through the next gulp plugin
|
||||
this.push(file);
|
||||
// tell the stream engine that we are done with this file
|
||||
return callback();
|
||||
}
|
||||
});
|
||||
|
||||
// returning the file stream
|
||||
return stream;
|
||||
};
|
||||
|
||||
// Exporting the plugin main function
|
||||
module.exports = gulpPrefixer;
|
||||
```
|
||||
|
||||
The above plugin can be used like this:
|
||||
|
||||
```js
|
||||
var gulp = require('gulp');
|
||||
var gulpPrefixer = require('gulp-prefixer');
|
||||
|
||||
gulp.src('files/**/*.js')
|
||||
.pipe(gulpPrefixer('prepended string'))
|
||||
.pipe(gulp.dest('/modified-files/'));
|
||||
```
|
||||
|
||||
## Some plugins using streams
|
||||
|
||||
* [gulp-svgicons2svgfont](https://github.com/nfroidure/gulp-svgiconstosvgfont)
|
||||
* gulp-browserify (Soon)
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
# Guidelines
|
||||
|
||||
> While these guidelines are totally optional, we **HIGHLY** recommend that everyone follows them. Nobody wants to use a bad plugin. These guidelines will actually help make your life easier by giving you assurance that your plugin fits well within gulp.
|
||||
|
||||
[Writing a Plugin](README.md) > Guidelines
|
||||
|
||||
1. Your plugin should not do something that can be done easily with an existing node module
|
||||
- Wrapping every possible thing just for the sake of wrapping it will pollute the ecosystem with low quality plugins that don't make sense
|
||||
1. Your plugin should only do **one thing**, and do it well.
|
||||
- Avoid config options that make your plugin do completely different tasks
|
||||
1. Your plugin shouldn't do things that other plugins are responsible for
|
||||
- It should not concat, [gulp-concat](https://github.com/wearefractal/gulp-concat) does that
|
||||
- It should not add headers, [gulp-header](https://github.com/godaddy/gulp-header) does that
|
||||
- It should not add footers, [gulp-footer](https://github.com/godaddy/gulp-footer) does that
|
||||
- If it's a common but optional use case, document that your plugin is often used with another plugin
|
||||
- If it's an internal requirement, make use of existing plugins by piping your plugin's output to them
|
||||
1. Your plugin **must be tested**
|
||||
- Testing a gulp plugin is easy, you don't even need gulp to test it
|
||||
- Look at other plugins for examples
|
||||
1. Add `gulpplugin` as a keyword in your `package.json` so you show up on our search
|
||||
1. Do not throw errors inside a stream
|
||||
- Instead, you should emit it as an **error** event.
|
||||
- If you encounter an error **outside** the stream, such as invalid configuration, you may throw it.
|
||||
1. Prefix any errors with the name of your plugin
|
||||
- For example: `gulp-replace: Cannot do regexp replace on a stream`
|
||||
- Use gulp-util's [PluginError](https://github.com/gulpjs/gulp-util#new-pluginerrorpluginname-message-options) class to make this easy
|
||||
1. The type of `file.contents` should always be the same going out as it was when it came in
|
||||
- If file.contents is null (non-read) just ignore the file and pass it along
|
||||
- If file.contents is a Stream and you don't support that just emit an error
|
||||
- If you choose to support file.contents as a Stream, use [BufferStream](https://github.com/nfroidure/BufferStream) to make this easy
|
||||
1. Do not pass the `file` object downstream until you are done with it
|
||||
1. Make use of the [gulp-util](https://github.com/gulpjs/gulp-util) library
|
||||
- It provides templating, CLI colors, logging, changing file extensions
|
||||
- Try looking for common things there first and add it if it doesn't exist
|
||||
1. Do NOT require `gulp` as a dependency or peerDependency
|
||||
- There is no reason you should have to do this and it will cause problems if you do
|
||||
|
||||
## Why are these guidelines so strict?
|
||||
|
||||
gulp aims to be simple for users. By providing strict guidelines we are able to provide a consistent and high-quality ecosystem for everyone. While this does add a little more work and thought for plugin authors, it removes a lot of problems later down the road.
|
||||
|
||||
### What happens if I don't follow them?
|
||||
|
||||
npm is open for everyone, and you are free to make whatever you want but these guidelines were prescribed for a reason. There are acceptances tests coming soon that will be integrated into the plugin search. If you fail to adhere to the plugin guidelines it will be publicly visible/sortable via a scoring system. People will always prefer to use plugins that match "the gulp way".
|
||||
|
||||
### What does a good plugin look like?
|
||||
|
||||
```js
|
||||
// through2 is a thin wrapper around node transform streams
|
||||
var through = require('through2');
|
||||
var gutil = require('gulp-util');
|
||||
var PluginError = gutil.PluginError;
|
||||
|
||||
// Consts
|
||||
const PLUGIN_NAME = 'gulp-prefixer';
|
||||
|
||||
function prefixStream(prefixText) {
|
||||
var stream = through();
|
||||
stream.write(prefixText);
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Plugin level function (dealing with files)
|
||||
function gulpPrefixer(prefixText) {
|
||||
|
||||
if (!prefixText) {
|
||||
throw PluginError(PLUGIN_NAME, "Missing prefix text!");
|
||||
}
|
||||
prefixText = new Buffer(prefixText); // allocate ahead of time
|
||||
|
||||
// Creating a stream through which each file will pass
|
||||
var stream = through.obj(function (file, enc, callback) {
|
||||
if (file.isNull()) {
|
||||
this.push(file); // Do nothing if no contents
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (file.isBuffer()) {
|
||||
file.contents = Buffer.concat([prefixText, file.contents]);
|
||||
this.push(file);
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (file.isStream()) {
|
||||
file.contents = file.contents.pipe(prefixStream(prefixText));
|
||||
this.push(file);
|
||||
return callback();
|
||||
}
|
||||
});
|
||||
|
||||
// returning the file stream
|
||||
return stream;
|
||||
};
|
||||
|
||||
// Exporting the plugin main function
|
||||
module.exports = gulpPrefixer;
|
||||
```
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
# README conventions
|
||||
|
||||
> Follow README conventions to increase your plugin readability and usability.
|
||||
|
||||
[Writing a Gulp Plugin](README.md) > README conventions
|
||||
|
||||
A plugin README should have the following parts at a minimum:
|
||||
|
||||
1. **Heading**: Give a short introduction to your plugin
|
||||
* Include the version of gulp your plugin was designed for
|
||||
* Include any badges on the same line as the heading
|
||||
1. **Usage**: Include a simple usage example
|
||||
* Show the plugin used on the context of a `gulpfile.js`
|
||||
* Cover the most common or simplest use case
|
||||
1. **API**: Document your plugin's API
|
||||
* For individual parameters, include:
|
||||
1. Parameter name
|
||||
1. Type
|
||||
1. Default value
|
||||
1. Description
|
||||
1. Optional example for complex options
|
||||
* If a parameter accepts an Object, do the above for each property
|
||||
* If your plugin accepts overloaded arguments, document each style individually
|
||||
|
||||
|
||||
# Example: Options object
|
||||
|
||||
The following is an example of a plugin that takes a single options object (from [gulp-handlebars](https://github.com/lazd/gulp-handlebars)).
|
||||
|
||||
|
||||
***
|
||||
|
||||
# gulp-handlebars [![NPM version][handlebars-npm-image]][handlebars-npm-url] [![Build status][handlebars-travis-image]][handlebars-travis-url]
|
||||
> Handlebars plugin for gulp 3
|
||||
|
||||
## Usage
|
||||
|
||||
First, install `gulp-handlebars` as a development dependency:
|
||||
|
||||
```shell
|
||||
npm install --save-dev gulp-handlebars
|
||||
```
|
||||
|
||||
Then, add it to your `gulpfile.js`:
|
||||
|
||||
```js
|
||||
var handlebars = require('gulp-handlebars');
|
||||
|
||||
gulp.task('templates', function(){
|
||||
gulp.src(['client/templates/*.hbs'])
|
||||
.pipe(handlebars({
|
||||
namespace: 'MyApp.templates',
|
||||
outputType: 'hybrid'
|
||||
}))
|
||||
.pipe(concat('templates.js'))
|
||||
.pipe(gulp.dest('build/js/'));
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### handlebars(options)
|
||||
|
||||
#### options.namespace
|
||||
Type: `String`
|
||||
Default: `templates`
|
||||
|
||||
The namespace in which the precompiled templates will be assigned. Use dot notation (e.g. `App.Templates`) for nested namespaces or false to declare templates in the global namespace.
|
||||
|
||||
#### options.outputType
|
||||
Type: `String`
|
||||
Default: `browser`
|
||||
|
||||
The desired output type. One of the following:
|
||||
|
||||
* `browser` - Produce plain JavaScript files for the browser
|
||||
* `hybrid` - Produce Node modules that can optionally be used on the frontend
|
||||
* `node` - Produce Node modules
|
||||
* `amd` - Produce AMD modules
|
||||
* `commonjs` - Produce CommonJS modules
|
||||
* `bare` - Return an unmolested function definition
|
||||
|
||||
#### options.declareNamespace
|
||||
Type: `Boolean`
|
||||
Default: `true`
|
||||
|
||||
If true, non-destructively declare all parts of the namespace. This option is only necessary when `options.type` is `browser` or `hybrid`.
|
||||
|
||||
For example, if the namespace is `MyApp.Templates` and a template is named `App.Header.hbs`, the following declaration will be present in the output file for that template:
|
||||
|
||||
```js
|
||||
this["MyApp"] = this["MyApp"] || {};
|
||||
this["MyApp"]["templates"] = this["MyApp"]["templates"] || {};
|
||||
this["MyApp"]["templates"]["App"] = this["MyApp"]["templates"]["App"] || {};
|
||||
this["MyApp"]["templates"]["App"]["Header"] = function () {};
|
||||
```
|
||||
|
||||
When processing multiple templates under a given namespace, this will result in duplicate declarations. That is, the non-destructive declaration of the namespace will be repeated for each template compiled.
|
||||
|
||||
#### options.processName
|
||||
Type: `Function`
|
||||
Default: Strip file extension
|
||||
|
||||
This option accepts a function which takes one argument (the template filepath) and returns a string which will be used as the key for the precompiled template object. By default, the filename minus the extension is used.
|
||||
|
||||
If this function returns a string containing periods (not including the file extension), they will be represented as a sub-namespace. See `options.declareNamespace` for an example of the effect.
|
||||
|
||||
#### options.compilerOptions
|
||||
Type: `Object`
|
||||
|
||||
Compiler options to pass to `Handlebars.precompile()`.
|
||||
|
||||
|
||||
[handlebars-travis-url]: http://travis-ci.org/lazd/gulp-handlebars
|
||||
[handlebars-travis-image]: https://secure.travis-ci.org/lazd/gulp-handlebars.png?branch=master
|
||||
[handlebars-npm-url]: https://npmjs.org/package/gulp-handlebars
|
||||
[handlebars-npm-image]: https://badge.fury.io/js/gulp-handlebars.png
|
||||
***
|
||||
|
||||
|
||||
# Example: Overloaded API
|
||||
|
||||
The following is an example of a plugin that has an overloaded API (from [gulp-csslint](https://github.com/lazd/gulp-csslint)).
|
||||
|
||||
|
||||
***
|
||||
# gulp-csslint [![NPM version][csslint-npm-image]][csslint-npm-url] [![Build status][csslint-travis-image]][csslint-travis-url]
|
||||
> CSSLint plugin for gulp 3
|
||||
|
||||
## Usage
|
||||
|
||||
First, install `gulp-csslint` as a development dependency:
|
||||
|
||||
```shell
|
||||
npm install --save-dev gulp-csslint
|
||||
```
|
||||
|
||||
Then, add it to your `gulpfile.js`:
|
||||
|
||||
```javascript
|
||||
var csslint = require('gulp-csslint');
|
||||
|
||||
gulp.task('css', function() {
|
||||
gulp.src('./client/css/*.css')
|
||||
.pipe(csslint())
|
||||
.pipe(csslint.reporter());
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### csslint(ruleConfiguration)
|
||||
|
||||
#### ruleConfiguration
|
||||
Type: `Object`
|
||||
|
||||
You can pass rule configuration as an object. See the [list of rules by ID on the CSSLint wiki](https://github.com/stubbornella/csslint/wiki/Rules-by-ID) for valid rule IDs.
|
||||
|
||||
```javascript
|
||||
gulp.src('./client/css/*.css')
|
||||
.pipe(csslint({
|
||||
'shorthand': false
|
||||
}))
|
||||
.pipe(csslint.reporter());
|
||||
```
|
||||
|
||||
### csslint(csslintrc)
|
||||
|
||||
#### csslintrc
|
||||
Type: `String`
|
||||
|
||||
You can also pass the path to your csslintrc file instead of a rule configuration object.
|
||||
|
||||
```javascript
|
||||
gulp.src('./client/css/*.css')
|
||||
.pipe(csslint('csslintrc.json'))
|
||||
.pipe(csslint.reporter());
|
||||
```
|
||||
|
||||
## Results
|
||||
|
||||
Adds the following properties to the file object:
|
||||
|
||||
```javascript
|
||||
file.csslint.success = true; // or false
|
||||
file.csslint.errorCount = 0; // number of errors returned by CSSLint
|
||||
file.csslint.results = []; // CSSLint errors
|
||||
file.csslint.opt = {}; // The options you passed to CSSLint
|
||||
```
|
||||
|
||||
## Custom Reporters
|
||||
|
||||
Custom reporter functions can be passed as `cssline.reporter(reporterFunc)`. The reporter function will be called for each linted file and passed the file object as described above.
|
||||
|
||||
```javascript
|
||||
var csslint = require('gulp-csslint');
|
||||
var gutil = require('gulp-util');
|
||||
|
||||
var customReporter = function(file) {
|
||||
gutil.log(gutil.colors.cyan(file.csslint.errorCount)+' errors in '+gutil.colors.magenta(file.path));
|
||||
|
||||
file.csslint.results.forEach(function(result) {
|
||||
gutil.log(result.error.message+' on line '+result.error.line);
|
||||
});
|
||||
};
|
||||
|
||||
gulp.task('lint', function() {
|
||||
gulp.files('./lib/*.js')
|
||||
.pipe(csslint())
|
||||
.pipe(csslint.reporter(customReporter));
|
||||
});
|
||||
```
|
||||
|
||||
[csslint-travis-url]: http://travis-ci.org/lazd/gulp-csslint
|
||||
[csslint-travis-image]: https://secure.travis-ci.org/lazd/gulp-csslint.png?branch=master
|
||||
[csslint-npm-url]: https://npmjs.org/package/gulp-csslint
|
||||
[csslint-npm-image]: https://badge.fury.io/js/gulp-csslint.png
|
||||
***
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
# Testing
|
||||
|
||||
> Testing your plugin is the only way to ensure quality. It brings confidence to your users and makes your life easier.
|
||||
|
||||
[Writing a Plugin](README.md) > Testing
|
||||
|
||||
## Tooling
|
||||
|
||||
Most plugins use [mocha](https://github.com/visionmedia/mocha) and [event-stream](https://github.com/dominictarr/event-stream) to help them test. The following examples will use these tools.
|
||||
|
||||
## Testing plugins for streaming mode
|
||||
|
||||
```js
|
||||
var assert = require('assert');
|
||||
var es = require('event-stream');
|
||||
var gutil = require('gulp-util');
|
||||
var prefixer = require('../index');
|
||||
|
||||
describe('gulp-prefixer', function () {
|
||||
describe('in streaming mode', function () {
|
||||
|
||||
it('should prepend text', function (done) {
|
||||
|
||||
// create the fake file
|
||||
var fakeFile = new gutil.File({
|
||||
contents: es.readArray(['stream', 'with', 'those', 'contents'])
|
||||
});
|
||||
|
||||
// Create a prefixer plugin stream
|
||||
var myPrefixer = prefixer('prependthis');
|
||||
|
||||
// write the fake file to it
|
||||
myPrefixer.write(fakeFile);
|
||||
|
||||
// wait for the file to come back out
|
||||
myPrefixer.once('data', function (file) {
|
||||
// make sure it came out the same way it went in
|
||||
assert(file.isStream());
|
||||
|
||||
// buffer the contents to make sure it got prepended to
|
||||
file.contents.pipe(es.wait(function (err, data) {
|
||||
// check the contents
|
||||
assert.equal(data, 'prependthistostreamwiththosecontents');
|
||||
done();
|
||||
}));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Testing plugins for buffer mode
|
||||
|
||||
```js
|
||||
var assert = require('assert');
|
||||
var es = require('event-stream');
|
||||
var gutil = require('gulp-util');
|
||||
var prefixer = require('../index');
|
||||
|
||||
describe('gulp-prefixer', function () {
|
||||
describe('in buffer mode', function () {
|
||||
|
||||
it('should prepend text', function (done) {
|
||||
|
||||
// create the fake file
|
||||
var fakeFile = new gutil.File({
|
||||
contents: new Buffer('abufferwiththiscontent')
|
||||
});
|
||||
|
||||
// Create a prefixer plugin stream
|
||||
var myPrefixer = prefixer('prependthis');
|
||||
|
||||
// write the fake file to it
|
||||
myPrefixer.write(fakeFile);
|
||||
|
||||
// wait for the file to come back out
|
||||
myPrefixer.once('data', function (file) {
|
||||
// make sure it came out the same way it went in
|
||||
assert(file.isBuffer());
|
||||
|
||||
// check the contents
|
||||
assert.equal(file.contents.toString('utf8'), 'prependthisabufferwiththiscontent');
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Sample tests
|
||||
* [gulp-cat](https://github.com/ben-eb/gulp-cat/blob/master/test.js)
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
# Using buffers
|
||||
|
||||
> Here is some information on creating gulp plugin that manipulates buffers.
|
||||
|
||||
[Writing a Plugin](README.md) > Using buffers
|
||||
|
||||
## Using buffers
|
||||
If your plugin is relying on a buffer based library, you will probably choose to base your plugin around file.contents as a buffer. Let's implement a plugin prepending some text to files:
|
||||
|
||||
```js
|
||||
var through = require('through2');
|
||||
var gutil = require('gulp-util');
|
||||
var PluginError = gutil.PluginError;
|
||||
|
||||
// Consts
|
||||
const PLUGIN_NAME = 'gulp-prefixer';
|
||||
|
||||
// Plugin level function (dealing with files)
|
||||
function gulpPrefixer(prefixText) {
|
||||
|
||||
if (!prefixText) {
|
||||
throw new PluginError(PLUGIN_NAME, "Missing prefix text!");
|
||||
}
|
||||
prefixText = new Buffer(prefixText); // allocate ahead of time
|
||||
|
||||
// Creating a stream through which each file will pass
|
||||
var stream = through.obj(function (file, enc, callback) {
|
||||
if (file.isNull()) {
|
||||
this.push(file); // Do nothing if no contents
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (file.isBuffer()) {
|
||||
file.contents = Buffer.concat([prefixText, file.contents]);
|
||||
this.push(file);
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (file.isStream()) {
|
||||
this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
|
||||
return callback();
|
||||
}
|
||||
});
|
||||
|
||||
// returning the file stream
|
||||
return stream;
|
||||
};
|
||||
|
||||
// Exporting the plugin main function
|
||||
module.exports = gulpPrefixer;
|
||||
```
|
||||
The above plugin can be used like this:
|
||||
|
||||
```js
|
||||
var gulp = require('gulp');
|
||||
var gulpPrefixer = require('gulp-prefixer');
|
||||
|
||||
gulp.src('files/**/*.js')
|
||||
.pipe(gulpPrefixer('prepended string'))
|
||||
.pipe(gulp.dest('/modified-files/'));
|
||||
```
|
||||
|
||||
## Handling streams
|
||||
|
||||
Unfortunately, the above plugin will error when using gulp.src in non-buffered (streaming) mode. You should support streams too if possible. See [Dealing with streams](dealing-with-streams.md) for more information.
|
||||
|
||||
## Some plugins based on buffers
|
||||
|
||||
* [gulp-coffee](https://github.com/wearefractal/gulp-coffee)
|
||||
* [gulp-svgmin](https://github.com/ben-eb/gulp-svgmin)
|
||||
* [gulp-marked](https://github.com/lmtm/gulp-marked)
|
||||
* [gulp-svg2ttf](https://github.com/nfroidure/gulp-svg2ttf)
|
||||
Reference in new issue
Block a user