Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the "sections" alternate source map structure #16

Closed
fitzgen opened this issue Aug 16, 2012 · 25 comments
Closed

Support the "sections" alternate source map structure #16

fitzgen opened this issue Aug 16, 2012 · 25 comments

Comments

@fitzgen
Copy link
Contributor

fitzgen commented Aug 16, 2012

https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#heading=h.535es3xeprgt

@DavidMikeSimon
Copy link

Seconding this, this feature would be very handy for the grunt-coffee-redux tool.

@fitzgen
Copy link
Contributor Author

fitzgen commented Jul 3, 2013

Proposed API

Goals:

  • Not depend on any specific web, node, or Firefox APIs for fetching the sub source maps
  • Not force developers using the existing API to change their code. Aside: It's ok if we throw an error when they haven't loaded a sub-source map we need because they wouldn't have been able to consume an indexed source map before and it would have failed anyways.

Notes:

  • I'm using Constructor#method instead of Constructor.prototype.method because the latter is too long and is messing up github's formatting.

SourceMapConsumer#fetchSubSourceMaps(fetcher, callback)

  • fetcher(subSourceMapURL, onSuccess, onFailure): Performs HTTP GET requests to fetch sub source map URLs and passes the information on via onSuccess(httpResponseBody) or onFailure(error) callbacks
  • callback(sourceMapConsumer, errors): A function called once all of the sub source maps have been loaded. The errors argument should be null in the case of no errors, or a list of error objects if there were errors fetching any of the sub source maps.

If this is not an indexed source map, or every section of this indexed source map is an inline map (not a pointer to a URL) we should call callback immediately.

Note that each sub source map could also be an indexed source map, so we will need to make sure to load each sub source map as well before calling callback.

Changes to the SourceMapConsumer constructor

Add two optional arguments, fetcher and callback (the same as above) so that the function's signature is SourceMapConsumer(sourceMap[, fetcher, callback]).

Changes to SourceMapConsumer#originalPositionFor(generatedPosition)

If we are not consuming an indexed source map, proceed normally.

If we are in an indexed source map:

Look up which sub source map the location falls into

If the sub source map is still fetching, throw a "not yet loaded" error

If fetching the sub source map failed, throw a "fetching sub source map for section failed" error

If fetching the sub source map completed successfully:

Determine the relative location into that sub source map by substracting the section's offsets

Query the sub source map for the original position of the relative location and return that.

Changes to SourceMapConsumer#generatedPositionFor(originalPosition)

Note: Because we can't be sure which sub source map contains the mapping with the original position we are being given until we parse each of them, we have to throw an error if any section is not available.

If any of the sub source maps are still loading, throw a "not yet loaded" error

If any of the sub source maps failed to load, throw a "fetching sub source map for section(s) [, , ...]" error

If all the sub source maps have been loaded successfully:

Iterate over each sub source map and ask for the generated position we are looking for

Return the first non-{ line: null, column: null } position we find

If we find none, return { line: null, column: null }

@sokra
Copy link
Contributor

sokra commented Jul 4, 2013

  • A callback parameter in a constructor seems weird to me
  • I would prefer node.js callback style for the fetcher function(err, rawSourceMap), but it's ok.
  • The behaivior for the getters seem weird: They "randomly" throw errors if the map is not fully loaded. There is no chance to get notified if this mapping is ready (only the full map).
  • Extending SourceMapConsumer with this stuff make the code bigger for everyone.
  • Staying environement independend is good.

I would like to propose an alternative API for discussion:

It

  • doesn't extend the current SourceMapConsumer
  • introduce a AsyncSourceMapConsumer for nice on demand loading. The SourceMapConsumer API, but async.
var map = new AsyncSourceMapConsumer(rawSourceMap, fetcher); // doesn't fetch anything
map.originalPositionFor(genPos, function(err, orgPos) {}); // fetch parts on demand
map.generatedPositionFor(orgPos, function(err, genPos) {}); // need to fetch everything
map.toSourceMapConsumer(function(sourceMapConsumer, errors) {
  // gives a sourceMapConsumer in every case. failed mappings are missing.
  // the errors array summarize all fetch errors.
  var genPos = sourceMapConsumer.generatedPositionFor(orgPos); // may throw if fetch failed
  // sourceMapConsumer is a instance of `SourceMapConsumer` or `IndexSourceMapConsumer`
});

The class IndexSourceMapConsumer has the same API as SourceMapConsumer but work with index maps. It is used by AsyncSourceMapConsumer#toSourceMapConsumer.

var indexMap = new IndexSourceMapConsumer(rawSourceMap);
var subMaps = indexMap.getSubMapUrls(); // String[]
indexMap.setSubMap(url, sourceMapConsumer);
indexMap.setSubMapError(url, error); // accessing this sub map will throw that error
// same API as SourceMapConsumer

For API users:

  • The existing SourceMapConsumer doesn't change and cannot consume index maps.
  • A simple change of the existing code can consume index maps (AsyncSourceMapConsumer#toSourceMapConsumer)
  • A complex change of the existing code can consume index maps with on demand loading of source maps (AsyncSourceMapConsumer#originalPositionFor etc.)

Alternative: Merge the IndexSourceMapConsumer with the SourceMapConsumer...

  • Existing code can comsume index maps, if they don't reference other SourceMaps by url.
  • But it would increase code size for SourceMapConsumer.

Alernative 2: Rename SourceMapConsumer to NormalSourceMapConsumer. Make a new SourceMapConsumer constructor, which automatically decide between NormalSourceMapConsumer and IndexSourceMapConsumer. They are subclasses of the new SourceMapConsumer interface.

  • Existing code can comsume index maps, if they don't reference other SourceMaps by url.
  • Existing code which subclasses SourceMapConsumer will break.

@tivac
Copy link

tivac commented Jul 5, 2013

  • Definitely agree on preferring node-style callbacks.
  • I'd prefer to not introduce another object type for index maps if possible, they're part of the spec & I feel like the SourceMapConsumer object should support the entirety of the spec.
  • I'm not convinced that it will be such a massive amount of code that adding support to the existing SourceMapConsumer is a problem. That being said, I don't use this code on a client so as long as it's well-tested & well-written code size isn't a pressing concern for me.

@tivac
Copy link

tivac commented Jul 5, 2013

Hmm, starting to look into this but the testing code doesn't seem to support async tests. I don't really want to rewrite the test framework, any suggestions @fitzgen? I could wrap the test calls into something like caolan/async but I dunno how kosher that is for @mozilla code.

@fitzgen
Copy link
Contributor Author

fitzgen commented Jul 5, 2013

(Aside: @tivac, @firass just told me that you are also a veteran of ResTek, nice 👍)


  • Regarding testing and async: it should be easy to mock a fetcher that is not async and just returns hard coded maps depending on the url you give it
  • Ok, let's do node style callbacks
  • I don't see any reason to expose getting a list of the sections or setting a sub source map for a given section in the public API
  • Strongly prefer to fetch sections greedily (or at minimum have a switch for this): developers using a debugger don't want to wait around for a subsection of a source map to load because they stepped into a new section of code
  • Regarding @tivac's second bullet point: I agree that the public API of a SourceMapConsumer should support the entirety of the spec, however we should be able to implement that support however we want and if the user gets back an IndexSourceMapConsumer instance that is still valid. What we shouldn't do is force users to check what kind of source map they have and choose the right consumer, or alternatively check which kind of consumer they get in the end. The user should have just one branch of logic / code path regardless what kind of source map they get.
    • The existing code path (new SourceMapConsumer(map)) obviously doesn't support async-ness that we will need when we support fetching sub source maps. I'm ok with maintaining this code path and saying it will only work when nothing is remote.
    • But we need a new one that supports async fetching and gives us the One Code Path to Rule Them All (works for source maps that don't need remote fetching and source maps that do)
  • We haven't really discussed generating index maps yet. I think we could just create an IndexSourceMapGenerator or even just have a SourceMapGenerator.createIndexMap class method. The single code path arguments don't apply here because they are two different use cases.
  • I like @sokra's alternative 2.
    • I think that the new SourceMapConsumer should provide and interface of methods that NormalSourceMapConsumer (aside/nit: I really don't like "Normal", any better name ideas?) and IndexSourceMapConsumer can implement and they should inherit from the interface so that way let smc = new SourceMapConsumer(map); smc instanceof SourceMapConsumer // true;
    • How do we pass in fetcher to the IndexSourceMapConsumer? As I mention above, I want to avoid having to explicitly check whether I get an IndexSourceMapConsumer or a NormalSourceMapConsumer from the SourceMapConsumer constructor; I should only need one branch of logic.
    • Regarding sub classing breaking, there are a few options:
      • Break sub classing and increment the version to 0.2.0 to indicate a backwards incompatible change. Composition still works fine either way.
      • Instead of making SourceMapConsumer an interface which NormalSourceMapConsumer and IndexSourceMapConsumer implement, we could just modify the SourceMapConsumer constructor to return an IndexSourceMapConsumer instance when needed. This is moving back towards my original proposal.
      • SourceMapConsumer's constructor can look at which kind of source map it has, and create the proper "SourceMapConsumerImplementation" object for the right type of source map it has and then in each of its methods just pass the arguments to this._implementation.originalPositionFor or whatever. This should maintain subclassing, but at the cost of some misdirection and a little bit of code bloat.

@tivac
Copy link

tivac commented Jul 5, 2013

Async Tests

I was hoping to test it being actually async, to ensure we were properly handling cases where that is diffcult (out-of-order responses, mostly). If you're cool with it a sync fetcher is ok-but-not-great by me.

Naming

I really prefer something like SimpleSourceMapConsumer over NormalSourceMapConsumer, "Normal" implies that index maps are "abnormal". Maybe they are, maybe they aren't. Seems unfair to brand them as such though.

SourceMapGenerator support

I'd like to get consuming Index source maps working with an API we're happy with first, generating is also important but at least for me it's definitely secondary. Feeling like we have enough discussion about just consuming that we should focus there first!

Inheritance/API

So long as you're ok with API calls randomly breaking in the async case if they are used before the callback has happened I still see no real strong case for splitting the functionality. If you broke them out SimpleSourceMapConsumer would still contain about 80% of the code & I don't know that using inheritance to build an IndexSourceMapConsumer for the last 20% is really worth it.

SourceMapConsumer() could throw an error if it's passed a raw source map that has section elements referencing URLs but not given a fetcher/callback. Is that too obtuse?

RE: ResTek: If Answerline was still using YUI2.x when you were there that was totally my fault, sorry! 😳

@fitzgen
Copy link
Contributor Author

fitzgen commented Jul 5, 2013

I was hoping to test it being actually async, to ensure we were properly handling cases where that is diffcult (out-of-order responses, mostly). If you're cool with it a sync fetcher is ok-but-not-great by me.

I agree that it would be best, but I think we can push this back to a follow up issue, or at least start implementing support for index maps now and then merge the async testing in before merging the full feature.

SimpleSourceMapConsumer

👍

SourceMapConsumer() could throw an error if it's passed a raw source map that has section elements referencing URLs but not given a fetcher/callback. Is that too obtuse?

👍

Inheritance

I think they should be separate. Having if (this.sections) as the first thing in every method of SourceMapConsumer would not be nice.

@tivac
Copy link

tivac commented Jul 5, 2013

I think they should be separate. Having if (this.sections) as the first thing in every method of SourceMapConsumer would not be nice.

Oof, ok. I can still try to work on it but I don't think I'll have enough time for a refactor that large. We'll see what I can accomplish.

@tivac tivac mentioned this issue Jul 6, 2013
@sokra
Copy link
Contributor

sokra commented Jul 6, 2013

Just another idea: We could give methods like originalPositionFor an optional callback. In the sync version they throw not-yet-loaded Error. With callback they return, when the required part is loaded. This would keep the API backward compatible, but give new code the opportunity to react to the fetching process.

New methods include: fetchSubMaps([fetcher], [callback]) (greedily) and setSubMapFetcher(fetcher) (on demand) with fetcher be a function(url, callback(err, rawSourceMapObject))

@fitzgen
Copy link
Contributor Author

fitzgen commented Jul 6, 2013

I really like that idea, but it doesn't work with SourceMapConsumer.prototype.sources because it's a getter.

_sigh_

What would be the prefect API if we didn't worry about backwards compatibility? Maybe its time...

@sokra
Copy link
Contributor

sokra commented Jul 7, 2013

That's a good question... Maybe something like this:

interface SourceMap { // Personally I would rename it^^
  // callback is "function(err, result: X)" for "X abc([callback])"
  {source,line,column,name} orginalPositionFor(line, column, [callback])
  {line,column} generatedPositionFor(source, line, column, [callback])
  String[] allSources([callback])
  {source: sourceContent} allSourceContents([callback])
  // Mapping is {original:{source,line,column,name},generated:{line,column}}
  Mapping[] allMappings([order], [callback])
  Mapping[] mappingsFor(source, [order], [callback])
  Mapping[] mappingsFor(startLine, startColumn, endLine, endColumn, [order], [callback])
}
class SimpleSourceMap : SourceMap {
  new SimpleSourceMap(sourceMap: Object)
}
class IndexSourceMap : SourceMap {
  new IndexSourceMap(sourceMap: Object, [fetcher])
  fetch([callback])
}
class FutureSourceMap : SourceMap {
  new FutureSourceMap(url: String, fetcher)
  fetch([callback])
}
module "source-map" {
  // callback is "function(error, sourceMap: SourceMap)"
  static SourceMap create(sourceMap: Object, [fetcher, [callback]])
  static SourceMap create(sourceMap: Object, [fetcher, fetchLazily: true])
  static FutureSourceMap create(url: String, fetcher, [callback])
  static FutureSourceMap create(url: String, fetcher, fetchLazily: true)
}

@fitzgen
Copy link
Contributor Author

fitzgen commented Jul 8, 2013

Just another idea: We could give methods like originalPositionFor an optional callback. In the sync version they throw not-yet-loaded Error. With callback they return, when the required part is loaded. This would keep the API backward compatible, but give new code the opportunity to react to the fetching process.

New methods include: fetchSubMaps([fetcher], [callback]) (greedily) and setSubMapFetcher(fetcher) (on demand) with fetcher be a function(url, callback(err, rawSourceMapObject))

Let's combine this proposal and the this._implementation.originalPositionFor so that inheritance doesn't break.

We can change sources to be a method with an optional callback and bump the version number.

@jlfwong
Copy link

jlfwong commented Jul 1, 2014

What's the current status of this?

It looks like #69 is in limbo at the moment.

A lot of this discussion seems to revolve around asynchronicity, but having a subset of this functionality synchronously would be really useful to me.

For my current project, I need to be able to consume indexed source maps, but each of the sections has a map instead of a url in it (i.e. once the map is loaded, no more fetching is required).

For example:

                   {"version": 3,
                    "file": "foo.out",
                    "sections": [
                        {'offset': {'line': 0, 'column': 0},
                         'map': {"version": 3,
                                 "file": "i1",
                                 "sourceRoot": "/",
                                 "sources": ["i1"],
                                 "names": [],
                                 "mappings": "AAAA"},
                         },
                        {'offset': {'line': 1, 'column': 0},
                         'map': {"version": 3,
                                 "file": "i2",
                                 "sourceRoot": "/",
                                 "sources": ["i2"],
                                 "names": [],
                                 "mappings": "AAAA"},
                        }
                        ]}
  1. Would you be open to accepting a patch that provides that functionality without adding asynchronicity?
  2. After all the discussion about potential APIs, I'm unsure what the final proposal is.

@fitzgen
Copy link
Contributor Author

fitzgen commented Jul 2, 2014

Would you be open to accepting a patch that provides that functionality without adding asynchronicity?

Yes.

After all the discussion about potential APIs, I'm unsure what the final proposal is.

Add a method for setting the source map fetcher. It should take (urlString, callback) and call the callback with (error, null) on a fetch failure, or (null, data) on fetch success.

Add a method to greedily fetch all sub source maps that takes a callback which gets passed (error) on failure or (null) on success.

All methods that access source mapped data should take an optional callback. If no callback is provided and the data is available, return it. If no callback is provided and the data is not available, throw an error. If a callback is provided and the data is available, call the callback with the arguments (null, data). If a callback is provided and the data is not available, attempt to load it. If it fails to load, call the callback with (error, null). If loading succeeds, call the callback with (null, data).

Make sources a function (taking an optional callback, as above), not a getter.

@DavidSouther
Copy link

Pushing two years on this... what's that hard part about recursively iterating a sourcemap?

@fitzgen
Copy link
Contributor Author

fitzgen commented Sep 9, 2014

Pushing two years on this... what's that hard part about recursively iterating a sourcemap?

Sounds like you're volunteering your time! Great! When should we expect your contributions?

@DavidSouther
Copy link

After I've had time to fully parse and understand the commentary in this thread, as well as source-map-consumer.js. So... indefinite.

@jlfwong
Copy link

jlfwong commented Jan 26, 2015

A subset of this now works since #127 has been merged :)

@amasad
Copy link

amasad commented Apr 28, 2015

@jlfwong what does #127 leave unimplemented from this?

etnlbck referenced this issue in etnlbck/postcss-playground Jul 20, 2015
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..88b9339
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# Postcss play
diff --git a/build/stylesheets/test.css b/build/stylesheets/test.css
new file mode 100644
index 0000000..60f97a4
--- /dev/null
+++ b/build/stylesheets/test.css
@@ -0,0 +1,71 @@
+.foo {
+    content: 'foo';
+}
+
+.bar {
+    content: 'bar';
+    background: #056ef0;
+}
+
+.baz {
+    content: 'baz';
+}
+
+.col-xs-1 {
+    width: calc(1/768);
+}
+
+.col-xs-2 {
+    width: calc(2/768);
+}
+
+.col-xs-3 {
+    width: calc(3/768);
+}
+
+.col-xs-4 {
+    width: calc(4/768);
+}
+
+.col-xs-5 {
+    width: calc(5/768);
+}
+
+.col-xs-6 {
+    width: calc(6/768);
+}
+
+.col-xs-7 {
+    width: calc(7/768);
+}
+
+.col-xs-8 {
+    width: calc(8/768);
+}
+
+.col-xs-9 {
+    width: calc(9/768);
+}
+
+.col-xs-10 {
+    width: calc(10/768);
+}
+
+.col-xs-11 {
+    width: calc(11/768);
+}
+
+.col-xs-12 {
+    width: calc(12/768);
+}
+
+.menu {
+    width: calc(4 * 400px);
+}
+
+.menu_link {
+    background: #056ef0;
+    width: 400px;
+}
+
+/*# sourceMappingURL=test.css.map */
\ No newline at end of file
diff --git a/build/stylesheets/test.css.map b/build/stylesheets/test.css.map
new file mode 100644
index 0000000..c19e0ba
--- /dev/null
+++ b/build/stylesheets/test.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["test.css"],"names":[],"mappings":"AAIE;IACE,eAAc;CAIf;;AALD;IACE,eAAc;IAEZ,oBAAkB;CAErB;;AALD;IACE,eAAc;CAIf;;AAMG;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,oBAAuB;CACxB;;AAFD;IACE,oBAAuB;CACxB;;AAFD;IACE,oBAAuB;CACxB;;AAMP;IACI,uBAAyB;CAC5B;;AAED;IACI,oBAAkB;IAClB,aAAe;CAClB","file":"test.css","sourcesContent":["@import \"partials/_variables.css\";\n\n$array: (foo, bar, baz);\n@each $i in $array {\n  .$i {\n    content: '$i';\n    @if $i == bar {\n      background: $blue;\n    }\n  }\n}\n\n@define-mixin grid $size, $width, $columns {\n\n    @for $i from 1 to 12 {\n      .col-$(size)-$(i) {\n        width: calc($i/$width);\n      }\n    }\n}\n\n@mixin grid xs,768,18;\n\n.menu {\n    width: calc(4 * $column);\n}\n\n.menu_link {\n    background: $blue;\n    width: $column;\n}\n"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..c6079df
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,23 @@
+var
+  gulp = require('gulp'),
+  g = require('gulp-load-plugins')(),
+  postcss = require('gulp-postcss'),
+  plugins = require('postcss-load-plugins')(),
+  precss = require('precss');
+
+gulp.task('styles', function (cb){
+  var processors = [
+    precss
+  ];
+  return gulp.src(['*.css'], {cwd: 'src/css'})
+    .pipe(g.sourcemaps.init())
+    .pipe(postcss(processors))
+    .pipe(g.sourcemaps.write('.'))
+    .pipe(gulp.dest('build/stylesheets/'));
+});
+
+gulp.watch(['src/css/*.css', 'src/css/partials/*.css'], ['styles']);
+
+gulp.task('default', ['styles']);
+
+module.exports = gulp;
diff --git a/node_modules/.bin/gulp b/node_modules/.bin/gulp
new file mode 120000
index 0000000..5de7332
--- /dev/null
+++ b/node_modules/.bin/gulp
@@ -0,0 +1 @@
+../gulp/bin/gulp.js
\ No newline at end of file
diff --git a/node_modules/gulp-load-plugins/README.md b/node_modules/gulp-load-plugins/README.md
new file mode 100644
index 0000000..e164c0e
--- /dev/null
+++ b/node_modules/gulp-load-plugins/README.md
@@ -0,0 +1,175 @@
+# gulp-load-plugins
+
+[![npm](https://nodei.co/npm/gulp-load-plugins.svg?downloads=true)](https://nodei.co/npm/gulp-load-plugins/)
+
+> Loads in any gulp plugins and attaches them to the global scope, or an object of your choice.
+
+[![Build Status](https://travis-ci.org/jackfranklin/gulp-load-plugins.svg?branch=master)](https://travis-ci.org/jackfranklin/gulp-load-plugins)
+
+
+## Install
+
+```sh
+$ npm install --save-dev gulp-load-plugins
+```
+
+
+## Usage
+
+Given a `package.json` file that has some dependencies within:
+
+```json
+{
+    "dependencies": {
+        "gulp-jshint": "*",
+        "gulp-concat": "*"
+    }
+}
+```
+
+Adding this into your `Gulpfile.js`:
+
+```js
+var gulp = require('gulp');
+var gulpLoadPlugins = require('gulp-load-plugins');
+var plugins = gulpLoadPlugins();
+```
+
+Or, even shorter:
+
+```js
+var plugins = require('gulp-load-plugins')();
+```
+
+Will result in the following happening (roughly, plugins are lazy loaded but in practice you won't notice any difference):
+
+```js
+plugins.jshint = require('gulp-jshint');
+plugins.concat = require('gulp-concat');
+```
+
+You can then use the plugins just like you would if you'd manually required them, but referring to them as `plugins.name()`, rather than just `name()`.
+
+This frees you up from having to manually require each gulp plugin.
+
+## Options
+
+You can pass in an object of options that are shown below: (the values for the keys are the defaults):
+
+```js
+gulpLoadPlugins({
+    pattern: ['gulp-*', 'gulp.*'], // the glob(s) to search for
+    config: 'package.json', // where to find the plugins, by default searched up from process.cwd()
+    scope: ['dependencies', 'devDependencies', 'peerDependencies'], // which keys in the config to look within
+    replaceString: /^gulp(-|\.)/, // what to remove from the name of the module when adding it to the context
+    camelize: true, // if true, transforms hyphenated plugins names to camel case
+    lazy: true, // whether the plugins should be lazy loaded on demand
+    rename: {} // a mapping of plugins to rename
+});
+```
+
+## Renaming
+
+From 0.8.0, you can pass in an object of mappings for renaming plugins. For example, imagine you want to load the `gulp-ruby-sass` plugin, but want to refer to it as just `sass`:
+
+```js
+gulpLoadPlugins({
+  rename: {
+    'gulp-ruby-sass': 'sass'
+  }
+});
+```
+
+## npm Scopes
+
+`gulp-load-plugins` comes with [npm scope](https://docs.npmjs.com/misc/scope) support. The major difference is that scoped plugins are accessible through an object on `plugins` that represents the scope. For example, if the plugin is `@myco/gulp-test-plugin` then you can access the plugin as shown in the following example:
+
+```js
+var plugins = require('gulp-load-plugins')();
+
+plugins.myco.testPlugin();
+```
+
+## Lazy Loading
+
+In 0.4.0 and prior, lazy loading used to only work with plugins that return a function. In newer versions though, lazy loading should work for any plugin. If you have a problem related to this please try disabling lazy loading and see if that fixes it. Feel free to open an issue on this repo too.
+
+
+## Credit
+
+Credit largely goes to @sindresorhus for his [load-grunt-plugins](https://github.com/sindresorhus/load-grunt-tasks) plugin. This plugin is almost identical, just tweaked slightly to work with Gulp and to expose the required plugins.
+
+
+## Changelog
+
+##### 1.0.0-rc.1
+- This is the first release candidate for what will become version 1 of gulp-load-plugins. Once a fix for [#70](https://github.com/jackfranklin/gulp-load-plugins/issues/70) is landed, I plan to release V1.
+- **Breaking Change** support for `NODE_PATH` is no longer supported. It was causing complexities and in [the PR that droppped support](https://github.com/jackfranklin/gulp-load-plugins/pull/75) no one shouted that they required `NODE_PATH` support.
+
+##### 0.10.0
+- throw a more informative error if a plugin is loaded that gulp-load-plugins can't find. [PR](https://github.com/jackfranklin/gulp-load-plugins/pull/68) - thanks @connor4312
+- allow `require` to look on the `NODE_PATH` if it can't find the module in the working directory. [PR](https://github.com/jackfranklin/gulp-load-plugins/pull/69) - thanks @chmanie
+
+##### 0.9.0
+- add support for npm-scoped plugins. [PR](https://github.com/jackfranklin/gulp-load-plugins/pull/63) - thanks @hbetts
+
+##### 0.8.1
+- fixed a bug where gulp-load-plugins would use the right `package.json` file but the wrong `node_modules` directory - thanks @callumacrae
+
+##### 0.8.0
+- add the ability to rename plugins that gulp-load-plugins loads in.
+
+##### 0.7.1
+- add `files` property to package.json so only required files are downloaded when installed - thanks @shinnn
+
+
+##### 0.7.0
+- support loading plugins with a dot in the name, such as `gulp.spritesmith` - thanks to @MRuy
+- upgrade multimatch to 1.0.0
+
+
+##### 0.6.0
+- Fix issues around plugin picking wrong package.json file - thanks @iliakan (see [issue](https://github.com/jackfranklin/gulp-load-plugins/issues/35)).
+
+##### 0.5.3
+- Show a nicer error if the plugin is unable to load any configuration and hence can't find any dependencies to load
+
+##### 0.5.2
+- Swap out globule for multimatch, thanks @sindresorhus.
+
+##### 0.5.1
+- Updated some internal dependencies which should see some small improvements - thanks @shinnn for this contribution.
+
+##### 0.5.0
+- improved lazy loading so it should work with plugins that don't just return a function. Thanks to @nfroidure for help with this.
+
+##### 0.4.0
+- plugins are lazy loaded for performance benefit. Thanks @julien-f for this.
+
+##### 0.3.0
+- turn the `camelize` option on by default
+
+##### 0.2.0
+- added `camelize` option, thanks @kombucha.
+- renamed to `gulp-load-plugins`.
+
+##### 0.1.1
+- add link to this repository into `package.json` (thanks @ben-eb).
+
+##### 0.1.0
+- move to `gulpLoadplugins` returning an object with the tasks define.
+
+##### 0.0.5
+- added `replaceString` option to configure exactly what gets replace when the plugin adds the module to the context
+
+##### 0.0.4
+- fixed keyword typo so plugin appears in search for gulp plugins
+
+##### 0.0.3
+- removed accidental console.log I'd left in
+
+##### 0.0.2
+- fixed accidentally missing a dependency out of package.json
+
+##### 0.0.1
+- initial release
diff --git a/node_modules/gulp-load-plugins/index.js b/node_modules/gulp-load-plugins/index.js
new file mode 100644
index 0000000..64c16a5
--- /dev/null
+++ b/node_modules/gulp-load-plugins/index.js
@@ -0,0 +1,105 @@
+'use strict';
+var multimatch = require('multimatch');
+var findup = require('findup-sync');
+var path = require('path');
+var resolve = require('resolve');
+
+function arrayify(el) {
+  return Array.isArray(el) ? el : [el];
+}
+
+function camelize(str) {
+  return str.replace(/-(\w)/g, function(m, p1) {
+    return p1.toUpperCase();
+  });
+}
+
+module.exports = function(options) {
+  var finalObject = {};
+  var configObject;
+  var requireFn;
+  options = options || {};
+
+  var pattern = arrayify(options.pattern || ['gulp-*', 'gulp.*', '@*/gulp{-,.}*']);
+  var config = options.config || findup('package.json', {cwd: parentDir});
+  var scope = arrayify(options.scope || ['dependencies', 'devDependencies', 'peerDependencies']);
+  var replaceString = options.replaceString || /^gulp(-|\.)/;
+  var camelizePluginName = options.camelize === false ? false : true;
+  var lazy = 'lazy' in options ? !!options.lazy : true;
+  var renameObj = options.rename || {};
+
+  if(typeof options.requireFn === 'function') {
+    requireFn = options.requireFn;
+  } else if(typeof config === 'string') {
+    requireFn = function (name) {
+      // This searches up from the specified package.json file, making sure
+      // the config option behaves as expected. See issue #56.
+      var src = resolve.sync(name, { basedir: path.dirname(config) });
+      return require(src);
+    };
+  } else {
+    requireFn = require;
+  }
+
+  configObject = (typeof config === 'string') ? require(config) : config;
+
+  if(!configObject) {
+    throw new Error('Could not find dependencies. Do you have a package.json file in your project?');
+  }
+
+  var names = scope.reduce(function(result, prop) {
+    return result.concat(Object.keys(configObject[prop] || {}));
+  }, []);
+
+  pattern.push('!gulp-load-plugins');
+
+  function defineProperty(object, requireName, name) {
+    if(lazy) {
+      Object.defineProperty(object, requireName, {
+        get: function() {
+          return requireFn(name);
+        }
+      });
+    } else {
+      object[requireName] = requireFn(name);
+    }
+  }
+
+  function getRequireName(name) {
+    var requireName;
+
+    if(renameObj[name]) {
+      requireName = options.rename[name];
+    } else {
+      requireName = name.replace(replaceString, '');
+      requireName = camelizePluginName ? camelize(requireName) : requireName;
+    }
+
+    return requireName;
+  }
+
+  var scopeTest = new RegExp('^@');
+  var scopeDecomposition = new RegExp('^@(.+)/(.+)');
+
+  multimatch(names, pattern).forEach(function(name) {
+    if(scopeTest.test(name)) {
+      var decomposition = scopeDecomposition.exec(name);
+
+      if(!finalObject.hasOwnProperty(decomposition[1])) {
+        finalObject[decomposition[1]] = {};
+      }
+
+      defineProperty(finalObject[decomposition[1]], getRequireName(decomposition[2]), name);
+    } else {
+      defineProperty(finalObject, getRequireName(name), name);
+    }
+
+  });
+
+  return finalObject;
+};
+
+var parentDir = path.dirname(module.parent.filename);
+
+// Necessary to get the current `module.parent` and resolve paths correctly.
+delete require.cache[__filename];
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/.npmignore b/node_modules/gulp-load-plugins/node_modules/findup-sync/.npmignore
new file mode 100644
index 0000000..84561e0
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/.npmignore
@@ -0,0 +1,4 @@
+test
+.travis.yml
+.jshintrc
+Gruntfile.js
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/LICENSE-MIT b/node_modules/gulp-load-plugins/node_modules/findup-sync/LICENSE-MIT
new file mode 100644
index 0000000..bb2aad6
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/LICENSE-MIT
@@ -0,0 +1,22 @@
+Copyright (c) 2013 "Cowboy" Ben Alman
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/README.md
new file mode 100644
index 0000000..da08371
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/README.md
@@ -0,0 +1,47 @@
+# findup-sync [![Build Status](https://secure.travis-ci.org/cowboy/node-findup-sync.png?branch=master)](http://travis-ci.org/cowboy/node-findup-sync)
+
+Find the first file matching a given pattern in the current directory or the nearest ancestor directory.
+
+## Getting Started
+Install the module with: `npm install findup-sync`
+
+```js
+var findup = require('findup-sync');
+
+// Start looking in the CWD.
+var filepath1 = findup('{a,b}*.txt');
+
+// Start looking somewhere else, and ignore case (probably a good idea).
+var filepath2 = findup('{a,b}*.txt', {cwd: '/some/path', nocase: true});
+```
+
+## Usage
+
+```js
+findup(patternOrPatterns [, minimatchOptions])
+```
+
+### patternOrPatterns
+Type: `String` or `Array`
+Default: none
+
+One or more wildcard glob patterns. Or just filenames.
+
+### minimatchOptions
+Type: `Object`
+Default: `{}`
+
+Options to be passed to [minimatch](https://github.com/isaacs/minimatch).
+
+Note that if you want to start in a different directory than the current working directory, specify a `cwd` property here.
+
+## Contributing
+In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
+
+## Release History
+2014-12-17 - v0.2.1 - updated to glob 4.3.
+2014-12-16 - v0.2.0 - Removed lodash, updated to glob 4.x.
+2014-03-14 - v0.1.3 - Updated dependencies.
+2013-03-08 - v0.1.2 - Updated dependencies. Fixed a Node 0.9.x bug. Updated unit tests to work cross-platform.
+2012-11-15 - v0.1.1 - Now works without an options object.
+2012-11-01 - v0.1.0 - Initial release.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/lib/findup-sync.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/lib/findup-sync.js
new file mode 100644
index 0000000..871a725
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/lib/findup-sync.js
@@ -0,0 +1,49 @@
+/*
+ * findup-sync
+ * https://github.com/cowboy/node-findup-sync
+ *
+ * Copyright (c) 2013 "Cowboy" Ben Alman
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+// Nodejs libs.
+var path = require('path');
+
+// External libs.
+var glob = require('glob');
+
+// Search for a filename in the given directory or all parent directories.
+module.exports = function(patterns, options) {
+  // Normalize patterns to an array.
+  if (!Array.isArray(patterns)) { patterns = [patterns]; }
+  // Create globOptions so that it can be modified without mutating the
+  // original object.
+  var globOptions = Object.create(options || {});
+  globOptions.maxDepth = 1;
+  globOptions.cwd = path.resolve(globOptions.cwd || '.');
+
+  var files, lastpath;
+  do {
+    // Search for files matching patterns.
+    files = patterns.map(function(pattern) {
+      return glob.sync(pattern, globOptions);
+    }).reduce(function(a, b) {
+      return a.concat(b);
+    }).filter(function(entry, index, arr) {
+      return index === arr.indexOf(entry);
+    });
+    // Return file if found.
+    if (files.length > 0) {
+      return path.resolve(path.join(globOptions.cwd, files[0]));
+    }
+    // Go up a directory.
+    lastpath = globOptions.cwd;
+    globOptions.cwd = path.resolve(globOptions.cwd, '..');
+  // If parentpath is the same as basedir, we can't go any higher.
+  } while (globOptions.cwd !== lastpath);
+
+  // No files were found!
+  return null;
+};
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/LICENSE b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/LICENSE
new file mode 100644
index 0000000..19129e3
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/README.md
new file mode 100644
index 0000000..e479ae2
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/README.md
@@ -0,0 +1,357 @@
+[![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Dependency Status](https://david-dm.org/isaacs/node-glob.svg)](https://david-dm.org/isaacs/node-glob) [![devDependency Status](https://david-dm.org/isaacs/node-glob/dev-status.svg)](https://david-dm.org/isaacs/node-glob#info=devDependencies) [![optionalDependency Status](https://david-dm.org/isaacs/node-glob/optional-status.svg)](https://david-dm.org/isaacs/node-glob#info=optionalDependencies)
+
+# Glob
+
+Match files using the patterns the shell uses, like stars and stuff.
+
+This is a glob implementation in JavaScript.  It uses the `minimatch`
+library to do its matching.
+
+![](oh-my-glob.gif)
+
+## Usage
+
+```javascript
+var glob = require("glob")
+
+// options is optional
+glob("**/*.js", options, function (er, files) {
+  // files is an array of filenames.
+  // If the `nonull` option is set, and nothing
+  // was found, then files is ["**/*.js"]
+  // er is an error object or null.
+})
+```
+
+## Glob Primer
+
+"Globs" are the patterns you type when you do stuff like `ls *.js` on
+the command line, or put `build/*` in a `.gitignore` file.
+
+Before parsing the path part patterns, braced sections are expanded
+into a set.  Braced sections start with `{` and end with `}`, with any
+number of comma-delimited sections within.  Braced sections may contain
+slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`.
+
+The following characters have special magic meaning when used in a
+path portion:
+
+* `*` Matches 0 or more characters in a single path portion
+* `?` Matches 1 character
+* `[...]` Matches a range of characters, similar to a RegExp range.
+  If the first character of the range is `!` or `^` then it matches
+  any character not in the range.
+* `!(pattern|pattern|pattern)` Matches anything that does not match
+  any of the patterns provided.
+* `?(pattern|pattern|pattern)` Matches zero or one occurrence of the
+  patterns provided.
+* `+(pattern|pattern|pattern)` Matches one or more occurrences of the
+  patterns provided.
+* `*(a|b|c)` Matches zero or more occurrences of the patterns provided
+* `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns
+  provided
+* `**` If a "globstar" is alone in a path portion, then it matches
+  zero or more directories and subdirectories searching for matches.
+  It does not crawl symlinked directories.
+
+### Dots
+
+If a file or directory path portion has a `.` as the first character,
+then it will not match any glob pattern unless that pattern's
+corresponding path part also has a `.` as its first character.
+
+For example, the pattern `a/.*/c` would match the file at `a/.b/c`.
+However the pattern `a/*/c` would not, because `*` does not start with
+a dot character.
+
+You can make glob treat dots as normal characters by setting
+`dot:true` in the options.
+
+### Basename Matching
+
+If you set `matchBase:true` in the options, and the pattern has no
+slashes in it, then it will seek for any file anywhere in the tree
+with a matching basename.  For example, `*.js` would match
+`test/simple/basic.js`.
+
+### Negation
+
+The intent for negation would be for a pattern starting with `!` to
+match everything that *doesn't* match the supplied pattern.  However,
+the implementation is weird, and for the time being, this should be
+avoided.  The behavior will change or be deprecated in version 5.
+
+### Empty Sets
+
+If no matching files are found, then an empty array is returned.  This
+differs from the shell, where the pattern itself is returned.  For
+example:
+
+    $ echo a*s*d*f
+    a*s*d*f
+
+To get the bash-style behavior, set the `nonull:true` in the options.
+
+### See Also:
+
+* `man sh`
+* `man bash` (Search for "Pattern Matching")
+* `man 3 fnmatch`
+* `man 5 gitignore`
+* [minimatch documentation](https://github.com/isaacs/minimatch)
+
+## glob.hasMagic(pattern, [options])
+
+Returns `true` if there are any special characters in the pattern, and
+`false` otherwise.
+
+Note that the options affect the results.  If `noext:true` is set in
+the options object, then `+(a|b)` will not be considered a magic
+pattern.  If the pattern has a brace expansion, like `a/{b/c,x/y}`
+then that is considered magical, unless `nobrace:true` is set in the
+options.
+
+## glob(pattern, [options], cb)
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* `cb` {Function}
+  * `err` {Error | null}
+  * `matches` {Array<String>} filenames found matching the pattern
+
+Perform an asynchronous glob search.
+
+## glob.sync(pattern, [options])
+
+* `pattern` {String} Pattern to be matched
+* `options` {Object}
+* return: {Array<String>} filenames found matching the pattern
+
+Perform a synchronous glob search.
+
+## Class: glob.Glob
+
+Create a Glob object by instantiating the `glob.Glob` class.
+
+```javascript
+var Glob = require("glob").Glob
+var mg = new Glob(pattern, options, cb)
+```
+
+It's an EventEmitter, and starts walking the filesystem to find matches
+immediately.
+
+### new glob.Glob(pattern, [options], [cb])
+
+* `pattern` {String} pattern to search for
+* `options` {Object}
+* `cb` {Function} Called when an error occurs, or matches are found
+  * `err` {Error | null}
+  * `matches` {Array<String>} filenames found matching the pattern
+
+Note that if the `sync` flag is set in the options, then matches will
+be immediately available on the `g.found` member.
+
+### Properties
+
+* `minimatch` The minimatch object that the glob uses.
+* `options` The options object passed in.
+* `aborted` Boolean which is set to true when calling `abort()`.  There
+  is no way at this time to continue a glob search after aborting, but
+  you can re-use the statCache to avoid having to duplicate syscalls.
+* `statCache` Collection of all the stat results the glob search
+  performed.
+* `cache` Convenience object.  Each field has the following possible
+  values:
+  * `false` - Path does not exist
+  * `true` - Path exists
+  * `'DIR'` - Path exists, and is not a directory
+  * `'FILE'` - Path exists, and is a directory
+  * `[file, entries, ...]` - Path exists, is a directory, and the
+    array value is the results of `fs.readdir`
+* `statCache` Cache of `fs.stat` results, to prevent statting the same
+  path multiple times.
+* `symlinks` A record of which paths are symbolic links, which is
+  relevant in resolving `**` patterns.
+
+### Events
+
+* `end` When the matching is finished, this is emitted with all the
+  matches found.  If the `nonull` option is set, and no match was found,
+  then the `matches` list contains the original pattern.  The matches
+  are sorted, unless the `nosort` flag is set.
+* `match` Every time a match is found, this is emitted with the matched.
+* `error` Emitted when an unexpected error is encountered, or whenever
+  any fs error occurs if `options.strict` is set.
+* `abort` When `abort()` is called, this event is raised.
+
+### Methods
+
+* `pause` Temporarily stop the search
+* `resume` Resume the search
+* `abort` Stop the search forever
+
+### Options
+
+All the options that can be passed to Minimatch can also be passed to
+Glob to change pattern matching behavior.  Also, some have been added,
+or have glob-specific ramifications.
+
+All options are false by default, unless otherwise noted.
+
+All options are added to the Glob object, as well.
+
+If you are running many `glob` operations, you can pass a Glob object
+as the `options` argument to a subsequent operation to shortcut some
+`stat` and `readdir` calls.  At the very least, you may pass in shared
+`symlinks`, `statCache`, and `cache` options, so that parallel glob
+operations will be sped up by sharing information about the
+filesystem.
+
+* `cwd` The current working directory in which to search.  Defaults
+  to `process.cwd()`.
+* `root` The place where patterns starting with `/` will be mounted
+  onto.  Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
+  systems, and `C:\` or some such on Windows.)
+* `dot` Include `.dot` files in normal matches and `globstar` matches.
+  Note that an explicit dot in a portion of the pattern will always
+  match dot files.
+* `nomount` By default, a pattern starting with a forward-slash will be
+  "mounted" onto the root setting, so that a valid filesystem path is
+  returned.  Set this flag to disable that behavior.
+* `mark` Add a `/` character to directory matches.  Note that this
+  requires additional stat calls.
+* `nosort` Don't sort the results.
+* `stat` Set to true to stat *all* results.  This reduces performance
+  somewhat, and is completely unnecessary, unless `readdir` is presumed
+  to be an untrustworthy indicator of file existence.
+* `silent` When an unusual error is encountered when attempting to
+  read a directory, a warning will be printed to stderr.  Set the
+  `silent` option to true to suppress these warnings.
+* `strict` When an unusual error is encountered when attempting to
+  read a directory, the process will just continue on in search of
+  other matches.  Set the `strict` option to raise an error in these
+  cases.
+* `cache` See `cache` property above.  Pass in a previously generated
+  cache object to save some fs calls.
+* `statCache` A cache of results of filesystem information, to prevent
+  unnecessary stat calls.  While it should not normally be necessary
+  to set this, you may pass the statCache from one glob() call to the
+  options object of another, if you know that the filesystem will not
+  change between calls.  (See "Race Conditions" below.)
+* `symlinks` A cache of known symbolic links.  You may pass in a
+  previously generated `symlinks` object to save `lstat` calls when
+  resolving `**` matches.
+* `sync` Perform a synchronous glob search.
+* `nounique` In some cases, brace-expanded patterns can result in the
+  same file showing up multiple times in the result set.  By default,
+  this implementation prevents duplicates in the result set.  Set this
+  flag to disable that behavior.
+* `nonull` Set to never return an empty set, instead returning a set
+  containing the pattern itself.  This is the default in glob(3).
+* `debug` Set to enable debug logging in minimatch and glob.
+* `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets.
+* `noglobstar` Do not match `**` against multiple filenames.  (Ie,
+  treat it as a normal `*` instead.)
+* `noext` Do not match `+(a|b)` "extglob" patterns.
+* `nocase` Perform a case-insensitive match.  Note: on
+  case-insensitive filesystems, non-magic patterns will match by
+  default, since `stat` and `readdir` will not raise errors.
+* `matchBase` Perform a basename-only match if the pattern does not
+  contain any slash characters.  That is, `*.js` would be treated as
+  equivalent to `**/*.js`, matching all js files in all directories.
+* `nonegate` Suppress `negate` behavior.  (See below.)
+* `nocomment` Suppress `comment` behavior.  (See below.)
+* `nonull` Return the pattern when no matches are found.
+* `nodir` Do not match directories, only files.
+
+## Comparisons to other fnmatch/glob implementations
+
+While strict compliance with the existing standards is a worthwhile
+goal, some discrepancies exist between node-glob and other
+implementations, and are intentional.
+
+If the pattern starts with a `!` character, then it is negated.  Set the
+`nonegate` flag to suppress this behavior, and treat leading `!`
+characters normally.  This is perhaps relevant if you wish to start the
+pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
+characters at the start of a pattern will negate the pattern multiple
+times.
+
+If a pattern starts with `#`, then it is treated as a comment, and
+will not match anything.  Use `\#` to match a literal `#` at the
+start of a line, or set the `nocomment` flag to suppress this behavior.
+
+The double-star character `**` is supported by default, unless the
+`noglobstar` flag is set.  This is supported in the manner of bsdglob
+and bash 4.3, where `**` only has special significance if it is the only
+thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
+`a/**b` will not.
+
+Note that symlinked directories are not crawled as part of a `**`,
+though their contents may match against subsequent portions of the
+pattern.  This prevents infinite loops and duplicates and the like.
+
+If an escaped pattern has no matches, and the `nonull` flag is set,
+then glob returns the pattern as-provided, rather than
+interpreting the character escapes.  For example,
+`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
+`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
+that it does not resolve escaped pattern characters.
+
+If brace expansion is not disabled, then it is performed before any
+other interpretation of the glob pattern.  Thus, a pattern like
+`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
+**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
+checked for validity.  Since those two are valid, matching proceeds.
+
+## Windows
+
+**Please only use forward-slashes in glob expressions.**
+
+Though windows uses either `/` or `\` as its path separator, only `/`
+characters are used by this glob implementation.  You must use
+forward-slashes **only** in glob expressions.  Back-slashes will always
+be interpreted as escape characters, not path separators.
+
+Results from absolute patterns such as `/foo/*` are mounted onto the
+root setting using `path.join`.  On windows, this will by default result
+in `/foo/*` matching `C:\foo\bar.txt`.
+
+## Race Conditions
+
+Glob searching, by its very nature, is susceptible to race conditions,
+since it relies on directory walking and such.
+
+As a result, it is possible that a file that exists when glob looks for
+it may have been deleted or modified by the time it returns the result.
+
+As part of its internal implementation, this program caches all stat
+and readdir calls that it makes, in order to cut down on system
+overhead.  However, this also makes it even more susceptible to races,
+especially if the cache or statCache objects are reused between glob
+calls.
+
+Users are thus advised not to use a glob result as a guarantee of
+filesystem state in the face of rapid changes.  For the vast majority
+of operations, this is never a problem.
+
+## Contributing
+
+Any change to behavior (including bugfixes) must come with a test.
+
+Patches that fail tests or reduce performance will be rejected.
+
+```
+# to run tests
+npm test
+
+# to re-generate test fixtures
+npm run test-regen
+
+# to benchmark against bash/zsh
+npm run bench
+
+# to profile javascript
+npm run prof
+```
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/common.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/common.js
new file mode 100644
index 0000000..610d124
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/common.js
@@ -0,0 +1,177 @@
+exports.alphasort = alphasort
+exports.alphasorti = alphasorti
+exports.isAbsolute = process.platform === "win32" ? absWin : absUnix
+exports.setopts = setopts
+exports.ownProp = ownProp
+exports.makeAbs = makeAbs
+exports.finish = finish
+exports.mark = mark
+
+function ownProp (obj, field) {
+  return Object.prototype.hasOwnProperty.call(obj, field)
+}
+
+var path = require("path")
+var minimatch = require("minimatch")
+var Minimatch = minimatch.Minimatch
+
+function absWin (p) {
+  if (absUnix(p)) return true
+  // pull off the device/UNC bit from a windows path.
+  // from node's lib/path.js
+  var splitDeviceRe =
+      /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/
+  var result = splitDeviceRe.exec(p)
+  var device = result[1] || ''
+  var isUnc = device && device.charAt(1) !== ':'
+  var isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
+
+  return isAbsolute
+}
+
+function absUnix (p) {
+  return p.charAt(0) === "/" || p === ""
+}
+
+function alphasorti (a, b) {
+  return a.toLowerCase().localeCompare(b.toLowerCase())
+}
+
+function alphasort (a, b) {
+  return a.localeCompare(b)
+}
+
+
+function setopts (self, pattern, options) {
+  if (!options)
+    options = {}
+
+  // base-matching: just use globstar for that.
+  if (options.matchBase && -1 === pattern.indexOf("/")) {
+    if (options.noglobstar) {
+      throw new Error("base matching requires globstar")
+    }
+    pattern = "**/" + pattern
+  }
+
+  self.pattern = pattern
+  self.strict = options.strict !== false
+  self.dot = !!options.dot
+  self.mark = !!options.mark
+  self.nodir = !!options.nodir
+  if (self.nodir)
+    self.mark = true
+  self.sync = !!options.sync
+  self.nounique = !!options.nounique
+  self.nonull = !!options.nonull
+  self.nosort = !!options.nosort
+  self.nocase = !!options.nocase
+  self.stat = !!options.stat
+  self.noprocess = !!options.noprocess
+
+  self.maxLength = options.maxLength || Infinity
+  self.cache = options.cache || Object.create(null)
+  self.statCache = options.statCache || Object.create(null)
+  self.symlinks = options.symlinks || Object.create(null)
+
+  self.changedCwd = false
+  var cwd = process.cwd()
+  if (!ownProp(options, "cwd"))
+    self.cwd = cwd
+  else {
+    self.cwd = options.cwd
+    self.changedCwd = path.resolve(options.cwd) !== cwd
+  }
+
+  self.root = options.root || path.resolve(self.cwd, "/")
+  self.root = path.resolve(self.root)
+  if (process.platform === "win32")
+    self.root = self.root.replace(/\\/g, "/")
+
+  self.nomount = !!options.nomount
+
+  self.minimatch = new Minimatch(pattern, options)
+  self.options = self.minimatch.options
+}
+
+function finish (self) {
+  var nou = self.nounique
+  var all = nou ? [] : Object.create(null)
+
+  for (var i = 0, l = self.matches.length; i < l; i ++) {
+    var matches = self.matches[i]
+    if (!matches) {
+      if (self.nonull) {
+        // do like the shell, and spit out the literal glob
+        var literal = self.minimatch.globSet[i]
+        if (nou)
+          all.push(literal)
+        else
+          all[literal] = true
+      }
+    } else {
+      // had matches
+      var m = Object.keys(matches)
+      if (nou)
+        all.push.apply(all, m)
+      else
+        m.forEach(function (m) {
+          all[m] = true
+        })
+    }
+  }
+
+  if (!nou)
+    all = Object.keys(all)
+
+  if (!self.nosort)
+    all = all.sort(self.nocase ? alphasorti : alphasort)
+
+  // at *some* point we statted all of these
+  if (self.mark) {
+    for (var i = 0; i < all.length; i++) {
+      all[i] = self._mark(all[i])
+    }
+    if (self.nodir) {
+      all = all.filter(function (e) {
+        return !(/\/$/.test(e))
+      })
+    }
+  }
+
+  self.found = all
+}
+
+function mark (self, p) {
+  var c = self.cache[p]
+  var m = p
+  if (c) {
+    var isDir = c === 'DIR' || Array.isArray(c)
+    var slash = p.slice(-1) === '/'
+
+    if (isDir && !slash)
+      m += '/'
+    else if (!isDir && slash)
+      m = m.slice(0, -1)
+
+    if (m !== p) {
+      self.statCache[m] = self.statCache[p]
+      self.cache[m] = self.cache[p]
+    }
+  }
+
+  return m
+}
+
+// lotta situps...
+function makeAbs (self, f) {
+  var abs = f
+  if (f.charAt(0) === "/") {
+    abs = path.join(self.root, f)
+  } else if (exports.isAbsolute(f)) {
+    abs = f
+  } else if (self.changedCwd) {
+    abs = path.resolve(self.cwd, f)
+  }
+  return abs
+}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/glob.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/glob.js
new file mode 100644
index 0000000..7401e0b
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/glob.js
@@ -0,0 +1,649 @@
+// Approach:
+//
+// 1. Get the minimatch set
+// 2. For each pattern in the set, PROCESS(pattern, false)
+// 3. Store matches per-set, then uniq them
+//
+// PROCESS(pattern, inGlobStar)
+// Get the first [n] items from pattern that are all strings
+// Join these together.  This is PREFIX.
+//   If there is no more remaining, then stat(PREFIX) and
+//   add to matches if it succeeds.  END.
+//
+// If inGlobStar and PREFIX is symlink and points to dir
+//   set ENTRIES = []
+// else readdir(PREFIX) as ENTRIES
+//   If fail, END
+//
+// with ENTRIES
+//   If pattern[n] is GLOBSTAR
+//     // handle the case where the globstar match is empty
+//     // by pruning it out, and testing the resulting pattern
+//     PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
+//     // handle other cases.
+//     for ENTRY in ENTRIES (not dotfiles)
+//       // attach globstar + tail onto the entry
+//       // Mark that this entry is a globstar match
+//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
+//
+//   else // not globstar
+//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
+//       Test ENTRY against pattern[n]
+//       If fails, continue
+//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
+//
+// Caveat:
+//   Cache all stats and readdirs results to minimize syscall.  Since all
+//   we ever care about is existence and directory-ness, we can just keep
+//   `true` for files, and [children,...] for directories, or `false` for
+//   things that don't exist.
+
+module.exports = glob
+
+var fs = require('fs')
+var minimatch = require('minimatch')
+var Minimatch = minimatch.Minimatch
+var inherits = require('inherits')
+var EE = require('events').EventEmitter
+var path = require('path')
+var assert = require('assert')
+var globSync = require('./sync.js')
+var common = require('./common.js')
+var alphasort = common.alphasort
+var alphasorti = common.alphasorti
+var isAbsolute = common.isAbsolute
+var setopts = common.setopts
+var ownProp = common.ownProp
+var inflight = require('inflight')
+var util = require('util')
+
+var once = require('once')
+
+function glob (pattern, options, cb) {
+  if (typeof options === 'function') cb = options, options = {}
+  if (!options) options = {}
+
+  if (options.sync) {
+    if (cb)
+      throw new TypeError('callback provided to sync glob')
+    return globSync(pattern, options)
+  }
+
+  return new Glob(pattern, options, cb)
+}
+
+glob.sync = globSync
+var GlobSync = glob.GlobSync = globSync.GlobSync
+
+// old api surface
+glob.glob = glob
+
+glob.hasMagic = function (pattern, options_) {
+  var options = util._extend({}, options_)
+  options.noprocess = true
+
+  var g = new Glob(pattern, options)
+  var set = g.minimatch.set
+  if (set.length > 1)
+    return true
+
+  for (var j = 0; j < set[0].length; j++) {
+    if (typeof set[0][j] !== 'string')
+      return true
+  }
+
+  return false
+}
+
+glob.Glob = Glob
+inherits(Glob, EE)
+function Glob (pattern, options, cb) {
+  if (typeof options === 'function') {
+    cb = options
+    options = null
+  }
+
+  if (options && options.sync) {
+    if (cb)
+      throw new TypeError('callback provided to sync glob')
+    return new GlobSync(pattern, options)
+  }
+
+  if (!(this instanceof Glob))
+    return new Glob(pattern, options, cb)
+
+  setopts(this, pattern, options)
+
+  // process each pattern in the minimatch set
+  var n = this.minimatch.set.length
+
+  // The matches are stored as {<filename>: true,...} so that
+  // duplicates are automagically pruned.
+  // Later, we do an Object.keys() on these.
+  // Keep them as a list so we can fill in when nonull is set.
+  this.matches = new Array(n)
+
+  if (typeof cb === 'function') {
+    cb = once(cb)
+    this.on('error', cb)
+    this.on('end', function (matches) {
+      cb(null, matches)
+    })
+  }
+
+  var self = this
+  var n = this.minimatch.set.length
+  this._processing = 0
+  this.matches = new Array(n)
+
+  this._emitQueue = []
+  this._processQueue = []
+  this.paused = false
+
+  if (this.noprocess)
+    return this
+
+  if (n === 0)
+    return done()
+
+  for (var i = 0; i < n; i ++) {
+    this._process(this.minimatch.set[i], i, false, done)
+  }
+
+  function done () {
+    --self._processing
+    if (self._processing <= 0)
+      self._finish()
+  }
+}
+
+Glob.prototype._finish = function () {
+  assert(this instanceof Glob)
+  if (this.aborted)
+    return
+
+  //console.error('FINISH', this.matches)
+  common.finish(this)
+  this.emit('end', this.found)
+}
+
+Glob.prototype._mark = function (p) {
+  return common.mark(this, p)
+}
+
+Glob.prototype._makeAbs = function (f) {
+  return common.makeAbs(this, f)
+}
+
+Glob.prototype.abort = function () {
+  this.aborted = true
+  this.emit('abort')
+}
+
+Glob.prototype.pause = function () {
+  if (!this.paused) {
+    this.paused = true
+    this.emit('pause')
+  }
+}
+
+Glob.prototype.resume = function () {
+  if (this.paused) {
+    this.emit('resume')
+    this.paused = false
+    if (this._emitQueue.length) {
+      var eq = this._emitQueue.slice(0)
+      this._emitQueue.length = 0
+      for (var i = 0; i < eq.length; i ++) {
+        var e = eq[i]
+        this._emitMatch(e[0], e[1])
+      }
+    }
+    if (this._processQueue.length) {
+      var pq = this._processQueue.slice(0)
+      this._processQueue.length = 0
+      for (var i = 0; i < pq.length; i ++) {
+        var p = pq[i]
+        this._processing--
+        this._process(p[0], p[1], p[2], p[3])
+      }
+    }
+  }
+}
+
+Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
+  assert(this instanceof Glob)
+  assert(typeof cb === 'function')
+
+  if (this.aborted)
+    return
+
+  this._processing++
+  if (this.paused) {
+    this._processQueue.push([pattern, index, inGlobStar, cb])
+    return
+  }
+
+  //console.error('PROCESS %d', this._processing, pattern)
+
+  // Get the first [n] parts of pattern that are all strings.
+  var n = 0
+  while (typeof pattern[n] === 'string') {
+    n ++
+  }
+  // now n is the index of the first one that is *not* a string.
+
+  // see if there's anything else
+  var prefix
+  switch (n) {
+    // if not, then this is rather simple
+    case pattern.length:
+      this._processSimple(pattern.join('/'), index, cb)
+      return
+
+    case 0:
+      // pattern *starts* with some non-trivial item.
+      // going to readdir(cwd), but not include the prefix in matches.
+      prefix = null
+      break
+
+    default:
+      // pattern has some string bits in the front.
+      // whatever it starts with, whether that's 'absolute' like /foo/bar,
+      // or 'relative' like '../baz'
+      prefix = pattern.slice(0, n).join('/')
+      break
+  }
+
+  var remain = pattern.slice(n)
+
+  // get the list of entries.
+  var read
+  if (prefix === null)
+    read = '.'
+  else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
+    if (!prefix || !isAbsolute(prefix))
+      prefix = '/' + prefix
+    read = prefix
+  } else
+    read = prefix
+
+  var abs = this._makeAbs(read)
+
+  var isGlobStar = remain[0] === minimatch.GLOBSTAR
+  if (isGlobStar)
+    this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
+  else
+    this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
+}
+
+
+Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
+  var self = this
+  this._readdir(abs, inGlobStar, function (er, entries) {
+    return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
+  })
+}
+
+Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
+
+  // if the abs isn't a dir, then nothing can match!
+  if (!entries)
+    return cb()
+
+  // It will only match dot entries if it starts with a dot, or if
+  // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
+  var pn = remain[0]
+  var negate = !!this.minimatch.negate
+  var rawGlob = pn._glob
+  var dotOk = this.dot || rawGlob.charAt(0) === '.'
+
+  var matchedEntries = []
+  for (var i = 0; i < entries.length; i++) {
+    var e = entries[i]
+    if (e.charAt(0) !== '.' || dotOk) {
+      var m
+      if (negate && !prefix) {
+        m = !e.match(pn)
+      } else {
+        m = e.match(pn)
+      }
+      if (m)
+        matchedEntries.push(e)
+    }
+  }
+
+  //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
+
+  var len = matchedEntries.length
+  // If there are no matched entries, then nothing matches.
+  if (len === 0)
+    return cb()
+
+  // if this is the last remaining pattern bit, then no need for
+  // an additional stat *unless* the user has specified mark or
+  // stat explicitly.  We know they exist, since readdir returned
+  // them.
+
+  if (remain.length === 1 && !this.mark && !this.stat) {
+    if (!this.matches[index])
+      this.matches[index] = Object.create(null)
+
+    for (var i = 0; i < len; i ++) {
+      var e = matchedEntries[i]
+      if (prefix) {
+        if (prefix !== '/')
+          e = prefix + '/' + e
+        else
+          e = prefix + e
+      }
+
+      if (e.charAt(0) === '/' && !this.nomount) {
+        e = path.join(this.root, e)
+      }
+      this._emitMatch(index, e)
+    }
+    // This was the last one, and no stats were needed
+    return cb()
+  }
+
+  // now test all matched entries as stand-ins for that part
+  // of the pattern.
+  remain.shift()
+  for (var i = 0; i < len; i ++) {
+    var e = matchedEntries[i]
+    var newPattern
+    if (prefix) {
+      if (prefix !== '/')
+        e = prefix + '/' + e
+      else
+        e = prefix + e
+    }
+    this._process([e].concat(remain), index, inGlobStar, cb)
+  }
+  cb()
+}
+
+Glob.prototype._emitMatch = function (index, e) {
+  if (this.aborted)
+    return
+
+  if (!this.matches[index][e]) {
+    if (this.paused) {
+      this._emitQueue.push([index, e])
+      return
+    }
+
+    if (this.nodir) {
+      var c = this.cache[this._makeAbs(e)]
+      if (c === 'DIR' || Array.isArray(c))
+        return
+    }
+
+    this.matches[index][e] = true
+    if (!this.stat && !this.mark)
+      return this.emit('match', e)
+
+    var self = this
+    this._stat(this._makeAbs(e), function (er, c, st) {
+      self.emit('stat', e, st)
+      self.emit('match', e)
+    })
+  }
+}
+
+Glob.prototype._readdirInGlobStar = function (abs, cb) {
+  if (this.aborted)
+    return
+
+  var lstatkey = 'lstat\0' + abs
+  var self = this
+  var lstatcb = inflight(lstatkey, lstatcb_)
+
+  if (lstatcb)
+    fs.lstat(abs, lstatcb)
+
+  function lstatcb_ (er, lstat) {
+    if (er)
+      return cb()
+
+    var isSym = lstat.isSymbolicLink()
+    self.symlinks[abs] = isSym
+
+    // If it's not a symlink or a dir, then it's definitely a regular file.
+    // don't bother doing a readdir in that case.
+    if (!isSym && !lstat.isDirectory()) {
+      self.cache[abs] = 'FILE'
+      cb()
+    } else
+      self._readdir(abs, false, cb)
+  }
+}
+
+Glob.prototype._readdir = function (abs, inGlobStar, cb) {
+  if (this.aborted)
+    return
+
+  cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
+  if (!cb)
+    return
+
+  //console.error('RD %j %j', +inGlobStar, abs)
+  if (inGlobStar && !ownProp(this.symlinks, abs))
+    return this._readdirInGlobStar(abs, cb)
+
+  if (ownProp(this.cache, abs)) {
+    var c = this.cache[abs]
+    if (!c || c === 'FILE')
+      return cb()
+
+    if (Array.isArray(c))
+      return cb(null, c)
+  }
+
+  var self = this
+  fs.readdir(abs, readdirCb(this, abs, cb))
+}
+
+function readdirCb (self, abs, cb) {
+  return function (er, entries) {
+    if (er)
+      self._readdirError(abs, er, cb)
+    else
+      self._readdirEntries(abs, entries, cb)
+  }
+}
+
+Glob.prototype._readdirEntries = function (abs, entries, cb) {
+  if (this.aborted)
+    return
+
+  // if we haven't asked to stat everything, then just
+  // assume that everything in there exists, so we can avoid
+  // having to stat it a second time.
+  if (!this.mark && !this.stat) {
+    for (var i = 0; i < entries.length; i ++) {
+      var e = entries[i]
+      if (abs === '/')
+        e = abs + e
+      else
+        e = abs + '/' + e
+      this.cache[e] = true
+    }
+  }
+
+  this.cache[abs] = entries
+  return cb(null, entries)
+}
+
+Glob.prototype._readdirError = function (f, er, cb) {
+  if (this.aborted)
+    return
+
+  // handle errors, and cache the information
+  switch (er.code) {
+    case 'ENOTDIR': // totally normal. means it *does* exist.
+      this.cache[f] = 'FILE'
+      break
+
+    case 'ENOENT': // not terribly unusual
+    case 'ELOOP':
+    case 'ENAMETOOLONG':
+    case 'UNKNOWN':
+      this.cache[f] = false
+      break
+
+    default: // some unusual error.  Treat as failure.
+      this.cache[f] = false
+      if (this.strict) return this.emit('error', er)
+      if (!this.silent) console.error('glob error', er)
+      break
+  }
+  return cb()
+}
+
+Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
+  var self = this
+  this._readdir(abs, inGlobStar, function (er, entries) {
+    self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
+  })
+}
+
+
+Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
+  //console.error('pgs2', prefix, remain[0], entries)
+
+  // no entries means not a dir, so it can never have matches
+  // foo.txt/** doesn't match foo.txt
+  if (!entries)
+    return cb()
+
+  // test without the globstar, and with every child both below
+  // and replacing the globstar.
+  var remainWithoutGlobStar = remain.slice(1)
+  var gspref = prefix ? [ prefix ] : []
+  var noGlobStar = gspref.concat(remainWithoutGlobStar)
+
+  // the noGlobStar pattern exits the inGlobStar state
+  this._process(noGlobStar, index, false, cb)
+
+  var isSym = this.symlinks[abs]
+  var len = entries.length
+
+  // If it's a symlink, and we're in a globstar, then stop
+  if (isSym && inGlobStar)
+    return cb()
+
+  for (var i = 0; i < len; i++) {
+    var e = entries[i]
+    if (e.charAt(0) === '.' && !this.dot)
+      continue
+
+    // these two cases enter the inGlobStar state
+    var instead = gspref.concat(entries[i], remainWithoutGlobStar)
+    this._process(instead, index, true, cb)
+
+    var below = gspref.concat(entries[i], remain)
+    this._process(below, index, true, cb)
+  }
+
+  cb()
+}
+
+Glob.prototype._processSimple = function (prefix, index, cb) {
+  // XXX review this.  Shouldn't it be doing the mounting etc
+  // before doing stat?  kinda weird?
+  var self = this
+  this._stat(prefix, function (er, exists) {
+    self._processSimple2(prefix, index, er, exists, cb)
+  })
+}
+Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
+
+  //console.error('ps2', prefix, exists)
+
+  if (!this.matches[index])
+    this.matches[index] = Object.create(null)
+
+  // If it doesn't exist, then just mark the lack of results
+  if (!exists)
+    return cb()
+
+  if (prefix && isAbsolute(prefix) && !this.nomount) {
+    var trail = /[\/\\]$/.test(prefix)
+    if (prefix.charAt(0) === '/') {
+      prefix = path.join(this.root, prefix)
+    } else {
+      prefix = path.resolve(this.root, prefix)
+      if (trail)
+        prefix += '/'
+    }
+  }
+
+  if (process.platform === 'win32')
+    prefix = prefix.replace(/\\/g, '/')
+
+  // Mark this as a match
+  this._emitMatch(index, prefix)
+  cb()
+}
+
+// Returns either 'DIR', 'FILE', or false
+Glob.prototype._stat = function (f, cb) {
+  var abs = f
+  if (f.charAt(0) === '/')
+    abs = path.join(this.root, f)
+  else if (this.changedCwd)
+    abs = path.resolve(this.cwd, f)
+
+
+  if (f.length > this.maxLength)
+    return cb()
+
+  if (!this.stat && ownProp(this.cache, f)) {
+    var c = this.cache[f]
+
+    if (Array.isArray(c))
+      c = 'DIR'
+
+    // It exists, but not how we need it
+    if (abs.slice(-1) === '/' && c !== 'DIR')
+      return cb()
+
+    return cb(null, c)
+  }
+
+  var exists
+  var stat = this.statCache[abs]
+  if (stat !== undefined) {
+    if (stat === false)
+      return cb(null, stat)
+    else
+      return cb(null, stat.isDirectory() ? 'DIR' : 'FILE', stat)
+  }
+
+  var self = this
+  var statcb = inflight('stat\0' + abs, statcb_)
+  if (statcb)
+    fs.stat(abs, statcb)
+
+  function statcb_ (er, stat) {
+    self._stat2(f, abs, er, stat, cb)
+  }
+}
+
+Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
+  if (er) {
+    this.statCache[abs] = false
+    return cb()
+  }
+
+  this.statCache[abs] = stat
+
+  if (abs.slice(-1) === '/' && !stat.isDirectory())
+    return cb(null, false, stat)
+
+  var c = stat.isDirectory() ? 'DIR' : 'FILE'
+  this.cache[f] = this.cache[f] || c
+  return cb(null, c, stat)
+}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/.eslintrc b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/.eslintrc
new file mode 100644
index 0000000..b7a1550
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/.eslintrc
@@ -0,0 +1,17 @@
+{
+  "env" : {
+    "node" : true
+  },
+  "rules" : {
+    "semi": [2, "never"],
+    "strict": 0,
+    "quotes": [1, "single", "avoid-escape"],
+    "no-use-before-define": 0,
+    "curly": 0,
+    "no-underscore-dangle": 0,
+    "no-lonely-if": 1,
+    "no-unused-vars": [2, {"vars" : "all", "args" : "after-used"}],
+    "no-mixed-requires": 0,
+    "space-infix-ops": 0
+  }
+}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/LICENSE b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/LICENSE
new file mode 100644
index 0000000..05eeeb8
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/README.md
new file mode 100644
index 0000000..6dc8929
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/README.md
@@ -0,0 +1,37 @@
+# inflight
+
+Add callbacks to requests in flight to avoid async duplication
+
+## USAGE
+
+```javascript
+var inflight = require('inflight')
+
+// some request that does some stuff
+function req(key, callback) {
+  // key is any random string.  like a url or filename or whatever.
+  //
+  // will return either a falsey value, indicating that the
+  // request for this key is already in flight, or a new callback
+  // which when called will call all callbacks passed to inflightk
+  // with the same key
+  callback = inflight(key, callback)
+
+  // If we got a falsey value back, then there's already a req going
+  if (!callback) return
+
+  // this is where you'd fetch the url or whatever
+  // callback is also once()-ified, so it can safely be assigned
+  // to multiple events etc.  First call wins.
+  setTimeout(function() {
+    callback(null, key)
+  }, 100)
+}
+
+// only assigns a single setTimeout
+// when it dings, all cbs get called
+req('foo', cb1)
+req('foo', cb2)
+req('foo', cb3)
+req('foo', cb4)
+```
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/inflight.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/inflight.js
new file mode 100644
index 0000000..8bc96cb
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/inflight.js
@@ -0,0 +1,44 @@
+var wrappy = require('wrappy')
+var reqs = Object.create(null)
+var once = require('once')
+
+module.exports = wrappy(inflight)
+
+function inflight (key, cb) {
+  if (reqs[key]) {
+    reqs[key].push(cb)
+    return null
+  } else {
+    reqs[key] = [cb]
+    return makeres(key)
+  }
+}
+
+function makeres (key) {
+  return once(function RES () {
+    var cbs = reqs[key]
+    var len = cbs.length
+    var args = slice(arguments)
+    for (var i = 0; i < len; i++) {
+      cbs[i].apply(null, args)
+    }
+    if (cbs.length > len) {
+      // added more in the interim.
+      // de-zalgo, just in case, but don't call again.
+      cbs.splice(0, len)
+      process.nextTick(function () {
+        RES.apply(null, args)
+      })
+    } else {
+      delete reqs[key]
+    }
+  })
+}
+
+function slice (args) {
+  var length = args.length
+  var array = []
+
+  for (var i = 0; i < length; i++) array[i] = args[i]
+  return array
+}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/LICENSE b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/LICENSE
new file mode 100644
index 0000000..19129e3
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/README.md
new file mode 100644
index 0000000..98eab25
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/README.md
@@ -0,0 +1,36 @@
+# wrappy
+
+Callback wrapping utility
+
+## USAGE
+
+```javascript
+var wrappy = require("wrappy")
+
+// var wrapper = wrappy(wrapperFunction)
+
+// make sure a cb is called only once
+// See also: http://npm.im/once for this specific use case
+var once = wrappy(function (cb) {
+  var called = false
+  return function () {
+    if (called) return
+    called = true
+    return cb.apply(this, arguments)
+  }
+})
+
+function printBoo () {
+  console.log('boo')
+}
+// has some rando property
+printBoo.iAmBooPrinter = true
+
+var onlyPrintOnce = once(printBoo)
+
+onlyPrintOnce() // prints 'boo'
+onlyPrintOnce() // does nothing
+
+// random property is retained!
+assert.equal(onlyPrintOnce.iAmBooPrinter, true)
+```
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/package.json b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/package.json
new file mode 100644
index 0000000..8145dc8
--- /dev/null
+++ b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/package.json
@@ -0,0 +1,52 @@
+{
+  "name": "wrappy",
+  "version": "1.0.1",
+  "description": "Callback wrapping utility",
+  "main": "wrappy.js",
+  "directories": {
+    "test": "test"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "tap": "^0.4.12"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/npm/wrappy"
+  },
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "[email protected]",
+    "url": "http://blog.izs.me/"
+  },
+  "license": "ISC",
+  "bugs": {
+    "url": "https://github.com/npm/wrappy/issues"
+  },
+  "homepage": "https://github.com/npm/wrappy",
+  "gitHead": "006a8cbac6b99988315834c207896eed71fd069a",
+  "_id": "[email protected]",
+  "_shasum": "1e65969965ccbc2db4548c6b84a6f2c5aedd4739",
+  "_from": "wrappy@>=1.0.0 <2.0.0",
+  "_npmVersion": "2.0.0",
+  "_nodeVersion": "0.10.31",
+  "_npmUser": {
+  …
etnlbck referenced this issue in etnlbck/postcss-playground Jul 20, 2015
diff --git a/README.md b/README.md
index 88b9339..848b726 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,12 @@
-# Postcss play
+# Postcss js.la
+postcss is not a postprocessor. The idea behind it is that CSS should be able to be written without a user having to learn some meta language and it's syntax (SASS, LESS). We should be future proofing.
+
+postcss is an ecosystem of plugins that transforms CSS.
+
+- Gulp: ``` npm install gulp-postcss ```
+- CLI: ``` npm install -g postcss-cli ```
+
+# Resources
+[postcss](https://github.com/postcss)
+[PostCSS Docs](https://github.com/postcss/postcss/blob/master/docs/api.md)
+[CodePen](https://blog.codepen.io/2015/07/14/postcss-now-supported-on-codepen/)
diff --git a/build/index.html b/build/index.html
new file mode 100644
index 0000000..09ab0ec
--- /dev/null
+++ b/build/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Test Page</title>
+    <link href="/stylesheets/test.css" rel="stylesheet" type="text/css"/>
+  </head>
+  <body>
+    <div class="col-xs-1">
+      <a href="#">Link Play</a>
+    </div>
+  </body>
+</html>
diff --git a/build/stylesheets/test.css b/build/stylesheets/test.css
index 60f97a4..bc770d8 100644
--- a/build/stylesheets/test.css
+++ b/build/stylesheets/test.css
@@ -1,66 +1,78 @@
+/* PreCSS - FTW */
+/* Yah! Partials */
+
+/* Arrays */
+
+/* Loops */
 .foo {
-    content: 'foo';
+  content: 'foo';
 }
-
 .bar {
-    content: 'bar';
-    background: #056ef0;
+  content: 'bar';
+  background: rgba(#056ef0, 0.5);
 }
-
 .baz {
-    content: 'baz';
-}
-
-.col-xs-1 {
-    width: calc(1/768);
-}
-
-.col-xs-2 {
-    width: calc(2/768);
-}
-
-.col-xs-3 {
-    width: calc(3/768);
-}
-
-.col-xs-4 {
-    width: calc(4/768);
-}
-
-.col-xs-5 {
-    width: calc(5/768);
-}
-
-.col-xs-6 {
-    width: calc(6/768);
-}
-
-.col-xs-7 {
-    width: calc(7/768);
-}
-
-.col-xs-8 {
-    width: calc(8/768);
+  content: 'baz';
+}
+
+/* Mixins
+TODO: convert variables to a numerical value. start, end, increment
+*/
+
+/* Generates a grid with .col-xs-* at min-width: 320px with 18 columns */
+
+@media only screen and (min-width: 320px) {
+  .col-xs-1 {
+    width: 0.313%;
+  }
+  .col-xs-2 {
+    width: 0.625%;
+  }
+  .col-xs-3 {
+    width: 0.938%;
+  }
+  .col-xs-4 {
+    width: 1.25%;
+  }
+  .col-xs-5 {
+    width: 1.563%;
+  }
+  .col-xs-6 {
+    width: 1.875%;
+  }
+  .col-xs-7 {
+    width: 2.188%;
+  }
+  .col-xs-8 {
+    width: 2.5%;
+  }
+  .col-xs-9 {
+    width: 2.813%;
+  }
+  .col-xs-10 {
+    width: 3.125%;
+  }
+  .col-xs-11 {
+    width: 3.438%;
+  }
+  .col-xs-12 {
+    width: 3.75%;
+  }
+}
+
+/* CSS4 */
+
+:any-link {
+  background: yellow;
+}
+
+header:has(h1) {
+  content: '';
 }

-.col-xs-9 {
-    width: calc(9/768);
-}
-
-.col-xs-10 {
-    width: calc(10/768);
-}
-
-.col-xs-11 {
-    width: calc(11/768);
-}
-
-.col-xs-12 {
-    width: calc(12/768);
-}

 .menu {
-    width: calc(4 * 400px);
+    width: 1600px;
 }

 .menu_link {
diff --git a/build/stylesheets/test.css.map b/build/stylesheets/test.css.map
index c19e0ba..bec68f5 100644
--- a/build/stylesheets/test.css.map
+++ b/build/stylesheets/test.css.map
@@ -1 +1 @@
-{"version":3,"sources":["test.css"],"names":[],"mappings":"AAIE;IACE,eAAc;CAIf;;AALD;IACE,eAAc;IAEZ,oBAAkB;CAErB;;AALD;IACE,eAAc;CAIf;;AAMG;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,mBAAuB;CACxB;;AAFD;IACE,oBAAuB;CACxB;;AAFD;IACE,oBAAuB;CACxB;;AAFD;IACE,oBAAuB;CACxB;;AAMP;IACI,uBAAyB;CAC5B;;AAED;IACI,oBAAkB;IAClB,aAAe;CAClB","file":"test.css","sourcesContent":["@import \"partials/_variables.css\";\n\n$array: (foo, bar, baz);\n@each $i in $array {\n  .$i {\n    content: '$i';\n    @if $i == bar {\n      background: $blue;\n    }\n  }\n}\n\n@define-mixin grid $size, $width, $columns {\n\n    @for $i from 1 to 12 {\n      .col-$(size)-$(i) {\n        width: calc($i/$width);\n      }\n    }\n}\n\n@mixin grid xs,768,18;\n\n.menu {\n    width: calc(4 * $column);\n}\n\n.menu_link {\n    background: $blue;\n    width: $column;\n}\n"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["test.css"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,mBAAmB;;AAGnB,YAAY;;AAGZ,WAAW;AAET;EACE,eAAc;CAIf;AALD;EACE,eAAc;EAEZ,+BAA6B;CAEhC;AALD;EACE,eAAc;CAIf;;AAGH;;EAEE;;AAYF,yEAAyE;;AATvE;EAEI;IACE,cAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,aAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,YAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,cAA8B;GAC/B;EAFD;IACE,aAA8B;GAC/B;CAEJ;;AAOH,UAAU;;AAEV;EACE,mBAAmB;CACpB;;AAED;EACE,YAAY;CACb;;;AAGD;IACI,cAAyB;CAC5B;;AAED;IACI,oBAAkB;IAClB,aAAe;CAClB","file":"test.css","sourcesContent":["/* PreCSS - FTW */\n/* Yah! Partials */\n@import \"partials/_variables.css\";\n\n/* Arrays */\n$array: (foo, bar, baz);\n\n/* Loops */\n@each $i in $array {\n  .$i {\n    content: '$i';\n    @if $i == bar {\n      background: rgba($blue, 0.5);\n    }\n  }\n}\n\n/* Mixins\nTODO: convert variables to a numerical value. start, end, increment\n*/\n\n@define-mixin grid $size, $width, $columns {\n  @media only screen and (min-width: $(width)px) {\n    @for $i from 1 to 12 {\n      .col-$(size)-$(i) {\n        width: calc(($i/$width)*100)%;\n      }\n    }\n  }\n}\n\n/* Generates a grid with .col-xs-* at min-width: 320px with 18 columns */\n\n@mixin grid xs,320,18;\n\n/* CSS4 */\n\n:any-link {\n  background: yellow;\n}\n\nheader:has(h1) {\n  content: '';\n}\n\n\n.menu {\n    width: calc(4 * $column);\n}\n\n.menu_link {\n    background: $blue;\n    width: $column;\n}\n"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
index c6079df..622d354 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -7,7 +7,9 @@ var

 gulp.task('styles', function (cb){
   var processors = [
-    precss
+    precss,
+    plugins.calc,
+    plugins.cssnext
   ];
   return gulp.src(['*.css'], {cwd: 'src/css'})
     .pipe(g.sourcemaps.init())
diff --git a/node_modules/.bin/gulp b/node_modules/.bin/gulp
deleted file mode 120000
index 5de7332..0000000
--- a/node_modules/.bin/gulp
+++ /dev/null
@@ -1 +0,0 @@
-../gulp/bin/gulp.js
\ No newline at end of file
diff --git a/node_modules/gulp-load-plugins/README.md b/node_modules/gulp-load-plugins/README.md
deleted file mode 100644
index e164c0e..0000000
--- a/node_modules/gulp-load-plugins/README.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# gulp-load-plugins
-
-[![npm](https://nodei.co/npm/gulp-load-plugins.svg?downloads=true)](https://nodei.co/npm/gulp-load-plugins/)
-
-> Loads in any gulp plugins and attaches them to the global scope, or an object of your choice.
-
-[![Build Status](https://travis-ci.org/jackfranklin/gulp-load-plugins.svg?branch=master)](https://travis-ci.org/jackfranklin/gulp-load-plugins)
-
-
-## Install
-
-```sh
-$ npm install --save-dev gulp-load-plugins
-```
-
-
-## Usage
-
-Given a `package.json` file that has some dependencies within:
-
-```json
-{
-    "dependencies": {
-        "gulp-jshint": "*",
-        "gulp-concat": "*"
-    }
-}
-```
-
-Adding this into your `Gulpfile.js`:
-
-```js
-var gulp = require('gulp');
-var gulpLoadPlugins = require('gulp-load-plugins');
-var plugins = gulpLoadPlugins();
-```
-
-Or, even shorter:
-
-```js
-var plugins = require('gulp-load-plugins')();
-```
-
-Will result in the following happening (roughly, plugins are lazy loaded but in practice you won't notice any difference):
-
-```js
-plugins.jshint = require('gulp-jshint');
-plugins.concat = require('gulp-concat');
-```
-
-You can then use the plugins just like you would if you'd manually required them, but referring to them as `plugins.name()`, rather than just `name()`.
-
-This frees you up from having to manually require each gulp plugin.
-
-## Options
-
-You can pass in an object of options that are shown below: (the values for the keys are the defaults):
-
-```js
-gulpLoadPlugins({
-    pattern: ['gulp-*', 'gulp.*'], // the glob(s) to search for
-    config: 'package.json', // where to find the plugins, by default searched up from process.cwd()
-    scope: ['dependencies', 'devDependencies', 'peerDependencies'], // which keys in the config to look within
-    replaceString: /^gulp(-|\.)/, // what to remove from the name of the module when adding it to the context
-    camelize: true, // if true, transforms hyphenated plugins names to camel case
-    lazy: true, // whether the plugins should be lazy loaded on demand
-    rename: {} // a mapping of plugins to rename
-});
-```
-
-## Renaming
-
-From 0.8.0, you can pass in an object of mappings for renaming plugins. For example, imagine you want to load the `gulp-ruby-sass` plugin, but want to refer to it as just `sass`:
-
-```js
-gulpLoadPlugins({
-  rename: {
-    'gulp-ruby-sass': 'sass'
-  }
-});
-```
-
-## npm Scopes
-
-`gulp-load-plugins` comes with [npm scope](https://docs.npmjs.com/misc/scope) support. The major difference is that scoped plugins are accessible through an object on `plugins` that represents the scope. For example, if the plugin is `@myco/gulp-test-plugin` then you can access the plugin as shown in the following example:
-
-```js
-var plugins = require('gulp-load-plugins')();
-
-plugins.myco.testPlugin();
-```
-
-## Lazy Loading
-
-In 0.4.0 and prior, lazy loading used to only work with plugins that return a function. In newer versions though, lazy loading should work for any plugin. If you have a problem related to this please try disabling lazy loading and see if that fixes it. Feel free to open an issue on this repo too.
-
-
-## Credit
-
-Credit largely goes to @sindresorhus for his [load-grunt-plugins](https://github.com/sindresorhus/load-grunt-tasks) plugin. This plugin is almost identical, just tweaked slightly to work with Gulp and to expose the required plugins.
-
-
-## Changelog
-
-##### 1.0.0-rc.1
-- This is the first release candidate for what will become version 1 of gulp-load-plugins. Once a fix for [#70](https://github.com/jackfranklin/gulp-load-plugins/issues/70) is landed, I plan to release V1.
-- **Breaking Change** support for `NODE_PATH` is no longer supported. It was causing complexities and in [the PR that droppped support](https://github.com/jackfranklin/gulp-load-plugins/pull/75) no one shouted that they required `NODE_PATH` support.
-
-##### 0.10.0
-- throw a more informative error if a plugin is loaded that gulp-load-plugins can't find. [PR](https://github.com/jackfranklin/gulp-load-plugins/pull/68) - thanks @connor4312
-- allow `require` to look on the `NODE_PATH` if it can't find the module in the working directory. [PR](https://github.com/jackfranklin/gulp-load-plugins/pull/69) - thanks @chmanie
-
-##### 0.9.0
-- add support for npm-scoped plugins. [PR](https://github.com/jackfranklin/gulp-load-plugins/pull/63) - thanks @hbetts
-
-##### 0.8.1
-- fixed a bug where gulp-load-plugins would use the right `package.json` file but the wrong `node_modules` directory - thanks @callumacrae
-
-##### 0.8.0
-- add the ability to rename plugins that gulp-load-plugins loads in.
-
-##### 0.7.1
-- add `files` property to package.json so only required files are downloaded when installed - thanks @shinnn
-
-
-##### 0.7.0
-- support loading plugins with a dot in the name, such as `gulp.spritesmith` - thanks to @MRuy
-- upgrade multimatch to 1.0.0
-
-
-##### 0.6.0
-- Fix issues around plugin picking wrong package.json file - thanks @iliakan (see [issue](https://github.com/jackfranklin/gulp-load-plugins/issues/35)).
-
-##### 0.5.3
-- Show a nicer error if the plugin is unable to load any configuration and hence can't find any dependencies to load
-
-##### 0.5.2
-- Swap out globule for multimatch, thanks @sindresorhus.
-
-##### 0.5.1
-- Updated some internal dependencies which should see some small improvements - thanks @shinnn for this contribution.
-
-##### 0.5.0
-- improved lazy loading so it should work with plugins that don't just return a function. Thanks to @nfroidure for help with this.
-
-##### 0.4.0
-- plugins are lazy loaded for performance benefit. Thanks @julien-f for this.
-
-##### 0.3.0
-- turn the `camelize` option on by default
-
-##### 0.2.0
-- added `camelize` option, thanks @kombucha.
-- renamed to `gulp-load-plugins`.
-
-##### 0.1.1
-- add link to this repository into `package.json` (thanks @ben-eb).
-
-##### 0.1.0
-- move to `gulpLoadplugins` returning an object with the tasks define.
-
-##### 0.0.5
-- added `replaceString` option to configure exactly what gets replace when the plugin adds the module to the context
-
-##### 0.0.4
-- fixed keyword typo so plugin appears in search for gulp plugins
-
-##### 0.0.3
-- removed accidental console.log I'd left in
-
-##### 0.0.2
-- fixed accidentally missing a dependency out of package.json
-
-##### 0.0.1
-- initial release
diff --git a/node_modules/gulp-load-plugins/index.js b/node_modules/gulp-load-plugins/index.js
deleted file mode 100644
index 64c16a5..0000000
--- a/node_modules/gulp-load-plugins/index.js
+++ /dev/null
@@ -1,105 +0,0 @@
-'use strict';
-var multimatch = require('multimatch');
-var findup = require('findup-sync');
-var path = require('path');
-var resolve = require('resolve');
-
-function arrayify(el) {
-  return Array.isArray(el) ? el : [el];
-}
-
-function camelize(str) {
-  return str.replace(/-(\w)/g, function(m, p1) {
-    return p1.toUpperCase();
-  });
-}
-
-module.exports = function(options) {
-  var finalObject = {};
-  var configObject;
-  var requireFn;
-  options = options || {};
-
-  var pattern = arrayify(options.pattern || ['gulp-*', 'gulp.*', '@*/gulp{-,.}*']);
-  var config = options.config || findup('package.json', {cwd: parentDir});
-  var scope = arrayify(options.scope || ['dependencies', 'devDependencies', 'peerDependencies']);
-  var replaceString = options.replaceString || /^gulp(-|\.)/;
-  var camelizePluginName = options.camelize === false ? false : true;
-  var lazy = 'lazy' in options ? !!options.lazy : true;
-  var renameObj = options.rename || {};
-
-  if(typeof options.requireFn === 'function') {
-    requireFn = options.requireFn;
-  } else if(typeof config === 'string') {
-    requireFn = function (name) {
-      // This searches up from the specified package.json file, making sure
-      // the config option behaves as expected. See issue #56.
-      var src = resolve.sync(name, { basedir: path.dirname(config) });
-      return require(src);
-    };
-  } else {
-    requireFn = require;
-  }
-
-  configObject = (typeof config === 'string') ? require(config) : config;
-
-  if(!configObject) {
-    throw new Error('Could not find dependencies. Do you have a package.json file in your project?');
-  }
-
-  var names = scope.reduce(function(result, prop) {
-    return result.concat(Object.keys(configObject[prop] || {}));
-  }, []);
-
-  pattern.push('!gulp-load-plugins');
-
-  function defineProperty(object, requireName, name) {
-    if(lazy) {
-      Object.defineProperty(object, requireName, {
-        get: function() {
-          return requireFn(name);
-        }
-      });
-    } else {
-      object[requireName] = requireFn(name);
-    }
-  }
-
-  function getRequireName(name) {
-    var requireName;
-
-    if(renameObj[name]) {
-      requireName = options.rename[name];
-    } else {
-      requireName = name.replace(replaceString, '');
-      requireName = camelizePluginName ? camelize(requireName) : requireName;
-    }
-
-    return requireName;
-  }
-
-  var scopeTest = new RegExp('^@');
-  var scopeDecomposition = new RegExp('^@(.+)/(.+)');
-
-  multimatch(names, pattern).forEach(function(name) {
-    if(scopeTest.test(name)) {
-      var decomposition = scopeDecomposition.exec(name);
-
-      if(!finalObject.hasOwnProperty(decomposition[1])) {
-        finalObject[decomposition[1]] = {};
-      }
-
-      defineProperty(finalObject[decomposition[1]], getRequireName(decomposition[2]), name);
-    } else {
-      defineProperty(finalObject, getRequireName(name), name);
-    }
-
-  });
-
-  return finalObject;
-};
-
-var parentDir = path.dirname(module.parent.filename);
-
-// Necessary to get the current `module.parent` and resolve paths correctly.
-delete require.cache[__filename];
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/.npmignore b/node_modules/gulp-load-plugins/node_modules/findup-sync/.npmignore
deleted file mode 100644
index 84561e0..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/.npmignore
+++ /dev/null
@@ -1,4 +0,0 @@
-test
-.travis.yml
-.jshintrc
-Gruntfile.js
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/LICENSE-MIT b/node_modules/gulp-load-plugins/node_modules/findup-sync/LICENSE-MIT
deleted file mode 100644
index bb2aad6..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/LICENSE-MIT
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (c) 2013 "Cowboy" Ben Alman
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/README.md
deleted file mode 100644
index da08371..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# findup-sync [![Build Status](https://secure.travis-ci.org/cowboy/node-findup-sync.png?branch=master)](http://travis-ci.org/cowboy/node-findup-sync)
-
-Find the first file matching a given pattern in the current directory or the nearest ancestor directory.
-
-## Getting Started
-Install the module with: `npm install findup-sync`
-
-```js
-var findup = require('findup-sync');
-
-// Start looking in the CWD.
-var filepath1 = findup('{a,b}*.txt');
-
-// Start looking somewhere else, and ignore case (probably a good idea).
-var filepath2 = findup('{a,b}*.txt', {cwd: '/some/path', nocase: true});
-```
-
-## Usage
-
-```js
-findup(patternOrPatterns [, minimatchOptions])
-```
-
-### patternOrPatterns
-Type: `String` or `Array`
-Default: none
-
-One or more wildcard glob patterns. Or just filenames.
-
-### minimatchOptions
-Type: `Object`
-Default: `{}`
-
-Options to be passed to [minimatch](https://github.com/isaacs/minimatch).
-
-Note that if you want to start in a different directory than the current working directory, specify a `cwd` property here.
-
-## Contributing
-In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
-
-## Release History
-2014-12-17 - v0.2.1 - updated to glob 4.3.
-2014-12-16 - v0.2.0 - Removed lodash, updated to glob 4.x.
-2014-03-14 - v0.1.3 - Updated dependencies.
-2013-03-08 - v0.1.2 - Updated dependencies. Fixed a Node 0.9.x bug. Updated unit tests to work cross-platform.
-2012-11-15 - v0.1.1 - Now works without an options object.
-2012-11-01 - v0.1.0 - Initial release.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/lib/findup-sync.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/lib/findup-sync.js
deleted file mode 100644
index 871a725..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/lib/findup-sync.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * findup-sync
- * https://github.com/cowboy/node-findup-sync
- *
- * Copyright (c) 2013 "Cowboy" Ben Alman
- * Licensed under the MIT license.
- */
-
-'use strict';
-
-// Nodejs libs.
-var path = require('path');
-
-// External libs.
-var glob = require('glob');
-
-// Search for a filename in the given directory or all parent directories.
-module.exports = function(patterns, options) {
-  // Normalize patterns to an array.
-  if (!Array.isArray(patterns)) { patterns = [patterns]; }
-  // Create globOptions so that it can be modified without mutating the
-  // original object.
-  var globOptions = Object.create(options || {});
-  globOptions.maxDepth = 1;
-  globOptions.cwd = path.resolve(globOptions.cwd || '.');
-
-  var files, lastpath;
-  do {
-    // Search for files matching patterns.
-    files = patterns.map(function(pattern) {
-      return glob.sync(pattern, globOptions);
-    }).reduce(function(a, b) {
-      return a.concat(b);
-    }).filter(function(entry, index, arr) {
-      return index === arr.indexOf(entry);
-    });
-    // Return file if found.
-    if (files.length > 0) {
-      return path.resolve(path.join(globOptions.cwd, files[0]));
-    }
-    // Go up a directory.
-    lastpath = globOptions.cwd;
-    globOptions.cwd = path.resolve(globOptions.cwd, '..');
-  // If parentpath is the same as basedir, we can't go any higher.
-  } while (globOptions.cwd !== lastpath);
-
-  // No files were found!
-  return null;
-};
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/LICENSE b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/LICENSE
deleted file mode 100644
index 19129e3..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/README.md
deleted file mode 100644
index e479ae2..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/README.md
+++ /dev/null
@@ -1,357 +0,0 @@
-[![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Dependency Status](https://david-dm.org/isaacs/node-glob.svg)](https://david-dm.org/isaacs/node-glob) [![devDependency Status](https://david-dm.org/isaacs/node-glob/dev-status.svg)](https://david-dm.org/isaacs/node-glob#info=devDependencies) [![optionalDependency Status](https://david-dm.org/isaacs/node-glob/optional-status.svg)](https://david-dm.org/isaacs/node-glob#info=optionalDependencies)
-
-# Glob
-
-Match files using the patterns the shell uses, like stars and stuff.
-
-This is a glob implementation in JavaScript.  It uses the `minimatch`
-library to do its matching.
-
-![](oh-my-glob.gif)
-
-## Usage
-
-```javascript
-var glob = require("glob")
-
-// options is optional
-glob("**/*.js", options, function (er, files) {
-  // files is an array of filenames.
-  // If the `nonull` option is set, and nothing
-  // was found, then files is ["**/*.js"]
-  // er is an error object or null.
-})
-```
-
-## Glob Primer
-
-"Globs" are the patterns you type when you do stuff like `ls *.js` on
-the command line, or put `build/*` in a `.gitignore` file.
-
-Before parsing the path part patterns, braced sections are expanded
-into a set.  Braced sections start with `{` and end with `}`, with any
-number of comma-delimited sections within.  Braced sections may contain
-slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`.
-
-The following characters have special magic meaning when used in a
-path portion:
-
-* `*` Matches 0 or more characters in a single path portion
-* `?` Matches 1 character
-* `[...]` Matches a range of characters, similar to a RegExp range.
-  If the first character of the range is `!` or `^` then it matches
-  any character not in the range.
-* `!(pattern|pattern|pattern)` Matches anything that does not match
-  any of the patterns provided.
-* `?(pattern|pattern|pattern)` Matches zero or one occurrence of the
-  patterns provided.
-* `+(pattern|pattern|pattern)` Matches one or more occurrences of the
-  patterns provided.
-* `*(a|b|c)` Matches zero or more occurrences of the patterns provided
-* `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns
-  provided
-* `**` If a "globstar" is alone in a path portion, then it matches
-  zero or more directories and subdirectories searching for matches.
-  It does not crawl symlinked directories.
-
-### Dots
-
-If a file or directory path portion has a `.` as the first character,
-then it will not match any glob pattern unless that pattern's
-corresponding path part also has a `.` as its first character.
-
-For example, the pattern `a/.*/c` would match the file at `a/.b/c`.
-However the pattern `a/*/c` would not, because `*` does not start with
-a dot character.
-
-You can make glob treat dots as normal characters by setting
-`dot:true` in the options.
-
-### Basename Matching
-
-If you set `matchBase:true` in the options, and the pattern has no
-slashes in it, then it will seek for any file anywhere in the tree
-with a matching basename.  For example, `*.js` would match
-`test/simple/basic.js`.
-
-### Negation
-
-The intent for negation would be for a pattern starting with `!` to
-match everything that *doesn't* match the supplied pattern.  However,
-the implementation is weird, and for the time being, this should be
-avoided.  The behavior will change or be deprecated in version 5.
-
-### Empty Sets
-
-If no matching files are found, then an empty array is returned.  This
-differs from the shell, where the pattern itself is returned.  For
-example:
-
-    $ echo a*s*d*f
-    a*s*d*f
-
-To get the bash-style behavior, set the `nonull:true` in the options.
-
-### See Also:
-
-* `man sh`
-* `man bash` (Search for "Pattern Matching")
-* `man 3 fnmatch`
-* `man 5 gitignore`
-* [minimatch documentation](https://github.com/isaacs/minimatch)
-
-## glob.hasMagic(pattern, [options])
-
-Returns `true` if there are any special characters in the pattern, and
-`false` otherwise.
-
-Note that the options affect the results.  If `noext:true` is set in
-the options object, then `+(a|b)` will not be considered a magic
-pattern.  If the pattern has a brace expansion, like `a/{b/c,x/y}`
-then that is considered magical, unless `nobrace:true` is set in the
-options.
-
-## glob(pattern, [options], cb)
-
-* `pattern` {String} Pattern to be matched
-* `options` {Object}
-* `cb` {Function}
-  * `err` {Error | null}
-  * `matches` {Array<String>} filenames found matching the pattern
-
-Perform an asynchronous glob search.
-
-## glob.sync(pattern, [options])
-
-* `pattern` {String} Pattern to be matched
-* `options` {Object}
-* return: {Array<String>} filenames found matching the pattern
-
-Perform a synchronous glob search.
-
-## Class: glob.Glob
-
-Create a Glob object by instantiating the `glob.Glob` class.
-
-```javascript
-var Glob = require("glob").Glob
-var mg = new Glob(pattern, options, cb)
-```
-
-It's an EventEmitter, and starts walking the filesystem to find matches
-immediately.
-
-### new glob.Glob(pattern, [options], [cb])
-
-* `pattern` {String} pattern to search for
-* `options` {Object}
-* `cb` {Function} Called when an error occurs, or matches are found
-  * `err` {Error | null}
-  * `matches` {Array<String>} filenames found matching the pattern
-
-Note that if the `sync` flag is set in the options, then matches will
-be immediately available on the `g.found` member.
-
-### Properties
-
-* `minimatch` The minimatch object that the glob uses.
-* `options` The options object passed in.
-* `aborted` Boolean which is set to true when calling `abort()`.  There
-  is no way at this time to continue a glob search after aborting, but
-  you can re-use the statCache to avoid having to duplicate syscalls.
-* `statCache` Collection of all the stat results the glob search
-  performed.
-* `cache` Convenience object.  Each field has the following possible
-  values:
-  * `false` - Path does not exist
-  * `true` - Path exists
-  * `'DIR'` - Path exists, and is not a directory
-  * `'FILE'` - Path exists, and is a directory
-  * `[file, entries, ...]` - Path exists, is a directory, and the
-    array value is the results of `fs.readdir`
-* `statCache` Cache of `fs.stat` results, to prevent statting the same
-  path multiple times.
-* `symlinks` A record of which paths are symbolic links, which is
-  relevant in resolving `**` patterns.
-
-### Events
-
-* `end` When the matching is finished, this is emitted with all the
-  matches found.  If the `nonull` option is set, and no match was found,
-  then the `matches` list contains the original pattern.  The matches
-  are sorted, unless the `nosort` flag is set.
-* `match` Every time a match is found, this is emitted with the matched.
-* `error` Emitted when an unexpected error is encountered, or whenever
-  any fs error occurs if `options.strict` is set.
-* `abort` When `abort()` is called, this event is raised.
-
-### Methods
-
-* `pause` Temporarily stop the search
-* `resume` Resume the search
-* `abort` Stop the search forever
-
-### Options
-
-All the options that can be passed to Minimatch can also be passed to
-Glob to change pattern matching behavior.  Also, some have been added,
-or have glob-specific ramifications.
-
-All options are false by default, unless otherwise noted.
-
-All options are added to the Glob object, as well.
-
-If you are running many `glob` operations, you can pass a Glob object
-as the `options` argument to a subsequent operation to shortcut some
-`stat` and `readdir` calls.  At the very least, you may pass in shared
-`symlinks`, `statCache`, and `cache` options, so that parallel glob
-operations will be sped up by sharing information about the
-filesystem.
-
-* `cwd` The current working directory in which to search.  Defaults
-  to `process.cwd()`.
-* `root` The place where patterns starting with `/` will be mounted
-  onto.  Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
-  systems, and `C:\` or some such on Windows.)
-* `dot` Include `.dot` files in normal matches and `globstar` matches.
-  Note that an explicit dot in a portion of the pattern will always
-  match dot files.
-* `nomount` By default, a pattern starting with a forward-slash will be
-  "mounted" onto the root setting, so that a valid filesystem path is
-  returned.  Set this flag to disable that behavior.
-* `mark` Add a `/` character to directory matches.  Note that this
-  requires additional stat calls.
-* `nosort` Don't sort the results.
-* `stat` Set to true to stat *all* results.  This reduces performance
-  somewhat, and is completely unnecessary, unless `readdir` is presumed
-  to be an untrustworthy indicator of file existence.
-* `silent` When an unusual error is encountered when attempting to
-  read a directory, a warning will be printed to stderr.  Set the
-  `silent` option to true to suppress these warnings.
-* `strict` When an unusual error is encountered when attempting to
-  read a directory, the process will just continue on in search of
-  other matches.  Set the `strict` option to raise an error in these
-  cases.
-* `cache` See `cache` property above.  Pass in a previously generated
-  cache object to save some fs calls.
-* `statCache` A cache of results of filesystem information, to prevent
-  unnecessary stat calls.  While it should not normally be necessary
-  to set this, you may pass the statCache from one glob() call to the
-  options object of another, if you know that the filesystem will not
-  change between calls.  (See "Race Conditions" below.)
-* `symlinks` A cache of known symbolic links.  You may pass in a
-  previously generated `symlinks` object to save `lstat` calls when
-  resolving `**` matches.
-* `sync` Perform a synchronous glob search.
-* `nounique` In some cases, brace-expanded patterns can result in the
-  same file showing up multiple times in the result set.  By default,
-  this implementation prevents duplicates in the result set.  Set this
-  flag to disable that behavior.
-* `nonull` Set to never return an empty set, instead returning a set
-  containing the pattern itself.  This is the default in glob(3).
-* `debug` Set to enable debug logging in minimatch and glob.
-* `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets.
-* `noglobstar` Do not match `**` against multiple filenames.  (Ie,
-  treat it as a normal `*` instead.)
-* `noext` Do not match `+(a|b)` "extglob" patterns.
-* `nocase` Perform a case-insensitive match.  Note: on
-  case-insensitive filesystems, non-magic patterns will match by
-  default, since `stat` and `readdir` will not raise errors.
-* `matchBase` Perform a basename-only match if the pattern does not
-  contain any slash characters.  That is, `*.js` would be treated as
-  equivalent to `**/*.js`, matching all js files in all directories.
-* `nonegate` Suppress `negate` behavior.  (See below.)
-* `nocomment` Suppress `comment` behavior.  (See below.)
-* `nonull` Return the pattern when no matches are found.
-* `nodir` Do not match directories, only files.
-
-## Comparisons to other fnmatch/glob implementations
-
-While strict compliance with the existing standards is a worthwhile
-goal, some discrepancies exist between node-glob and other
-implementations, and are intentional.
-
-If the pattern starts with a `!` character, then it is negated.  Set the
-`nonegate` flag to suppress this behavior, and treat leading `!`
-characters normally.  This is perhaps relevant if you wish to start the
-pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
-characters at the start of a pattern will negate the pattern multiple
-times.
-
-If a pattern starts with `#`, then it is treated as a comment, and
-will not match anything.  Use `\#` to match a literal `#` at the
-start of a line, or set the `nocomment` flag to suppress this behavior.
-
-The double-star character `**` is supported by default, unless the
-`noglobstar` flag is set.  This is supported in the manner of bsdglob
-and bash 4.3, where `**` only has special significance if it is the only
-thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
-`a/**b` will not.
-
-Note that symlinked directories are not crawled as part of a `**`,
-though their contents may match against subsequent portions of the
-pattern.  This prevents infinite loops and duplicates and the like.
-
-If an escaped pattern has no matches, and the `nonull` flag is set,
-then glob returns the pattern as-provided, rather than
-interpreting the character escapes.  For example,
-`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
-`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
-that it does not resolve escaped pattern characters.
-
-If brace expansion is not disabled, then it is performed before any
-other interpretation of the glob pattern.  Thus, a pattern like
-`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
-**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
-checked for validity.  Since those two are valid, matching proceeds.
-
-## Windows
-
-**Please only use forward-slashes in glob expressions.**
-
-Though windows uses either `/` or `\` as its path separator, only `/`
-characters are used by this glob implementation.  You must use
-forward-slashes **only** in glob expressions.  Back-slashes will always
-be interpreted as escape characters, not path separators.
-
-Results from absolute patterns such as `/foo/*` are mounted onto the
-root setting using `path.join`.  On windows, this will by default result
-in `/foo/*` matching `C:\foo\bar.txt`.
-
-## Race Conditions
-
-Glob searching, by its very nature, is susceptible to race conditions,
-since it relies on directory walking and such.
-
-As a result, it is possible that a file that exists when glob looks for
-it may have been deleted or modified by the time it returns the result.
-
-As part of its internal implementation, this program caches all stat
-and readdir calls that it makes, in order to cut down on system
-overhead.  However, this also makes it even more susceptible to races,
-especially if the cache or statCache objects are reused between glob
-calls.
-
-Users are thus advised not to use a glob result as a guarantee of
-filesystem state in the face of rapid changes.  For the vast majority
-of operations, this is never a problem.
-
-## Contributing
-
-Any change to behavior (including bugfixes) must come with a test.
-
-Patches that fail tests or reduce performance will be rejected.
-
-```
-# to run tests
-npm test
-
-# to re-generate test fixtures
-npm run test-regen
-
-# to benchmark against bash/zsh
-npm run bench
-
-# to profile javascript
-npm run prof
-```
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/common.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/common.js
deleted file mode 100644
index 610d124..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/common.js
+++ /dev/null
@@ -1,177 +0,0 @@
-exports.alphasort = alphasort
-exports.alphasorti = alphasorti
-exports.isAbsolute = process.platform === "win32" ? absWin : absUnix
-exports.setopts = setopts
-exports.ownProp = ownProp
-exports.makeAbs = makeAbs
-exports.finish = finish
-exports.mark = mark
-
-function ownProp (obj, field) {
-  return Object.prototype.hasOwnProperty.call(obj, field)
-}
-
-var path = require("path")
-var minimatch = require("minimatch")
-var Minimatch = minimatch.Minimatch
-
-function absWin (p) {
-  if (absUnix(p)) return true
-  // pull off the device/UNC bit from a windows path.
-  // from node's lib/path.js
-  var splitDeviceRe =
-      /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/
-  var result = splitDeviceRe.exec(p)
-  var device = result[1] || ''
-  var isUnc = device && device.charAt(1) !== ':'
-  var isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
-
-  return isAbsolute
-}
-
-function absUnix (p) {
-  return p.charAt(0) === "/" || p === ""
-}
-
-function alphasorti (a, b) {
-  return a.toLowerCase().localeCompare(b.toLowerCase())
-}
-
-function alphasort (a, b) {
-  return a.localeCompare(b)
-}
-
-
-function setopts (self, pattern, options) {
-  if (!options)
-    options = {}
-
-  // base-matching: just use globstar for that.
-  if (options.matchBase && -1 === pattern.indexOf("/")) {
-    if (options.noglobstar) {
-      throw new Error("base matching requires globstar")
-    }
-    pattern = "**/" + pattern
-  }
-
-  self.pattern = pattern
-  self.strict = options.strict !== false
-  self.dot = !!options.dot
-  self.mark = !!options.mark
-  self.nodir = !!options.nodir
-  if (self.nodir)
-    self.mark = true
-  self.sync = !!options.sync
-  self.nounique = !!options.nounique
-  self.nonull = !!options.nonull
-  self.nosort = !!options.nosort
-  self.nocase = !!options.nocase
-  self.stat = !!options.stat
-  self.noprocess = !!options.noprocess
-
-  self.maxLength = options.maxLength || Infinity
-  self.cache = options.cache || Object.create(null)
-  self.statCache = options.statCache || Object.create(null)
-  self.symlinks = options.symlinks || Object.create(null)
-
-  self.changedCwd = false
-  var cwd = process.cwd()
-  if (!ownProp(options, "cwd"))
-    self.cwd = cwd
-  else {
-    self.cwd = options.cwd
-    self.changedCwd = path.resolve(options.cwd) !== cwd
-  }
-
-  self.root = options.root || path.resolve(self.cwd, "/")
-  self.root = path.resolve(self.root)
-  if (process.platform === "win32")
-    self.root = self.root.replace(/\\/g, "/")
-
-  self.nomount = !!options.nomount
-
-  self.minimatch = new Minimatch(pattern, options)
-  self.options = self.minimatch.options
-}
-
-function finish (self) {
-  var nou = self.nounique
-  var all = nou ? [] : Object.create(null)
-
-  for (var i = 0, l = self.matches.length; i < l; i ++) {
-    var matches = self.matches[i]
-    if (!matches) {
-      if (self.nonull) {
-        // do like the shell, and spit out the literal glob
-        var literal = self.minimatch.globSet[i]
-        if (nou)
-          all.push(literal)
-        else
-          all[literal] = true
-      }
-    } else {
-      // had matches
-      var m = Object.keys(matches)
-      if (nou)
-        all.push.apply(all, m)
-      else
-        m.forEach(function (m) {
-          all[m] = true
-        })
-    }
-  }
-
-  if (!nou)
-    all = Object.keys(all)
-
-  if (!self.nosort)
-    all = all.sort(self.nocase ? alphasorti : alphasort)
-
-  // at *some* point we statted all of these
-  if (self.mark) {
-    for (var i = 0; i < all.length; i++) {
-      all[i] = self._mark(all[i])
-    }
-    if (self.nodir) {
-      all = all.filter(function (e) {
-        return !(/\/$/.test(e))
-      })
-    }
-  }
-
-  self.found = all
-}
-
-function mark (self, p) {
-  var c = self.cache[p]
-  var m = p
-  if (c) {
-    var isDir = c === 'DIR' || Array.isArray(c)
-    var slash = p.slice(-1) === '/'
-
-    if (isDir && !slash)
-      m += '/'
-    else if (!isDir && slash)
-      m = m.slice(0, -1)
-
-    if (m !== p) {
-      self.statCache[m] = self.statCache[p]
-      self.cache[m] = self.cache[p]
-    }
-  }
-
-  return m
-}
-
-// lotta situps...
-function makeAbs (self, f) {
-  var abs = f
-  if (f.charAt(0) === "/") {
-    abs = path.join(self.root, f)
-  } else if (exports.isAbsolute(f)) {
-    abs = f
-  } else if (self.changedCwd) {
-    abs = path.resolve(self.cwd, f)
-  }
-  return abs
-}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/glob.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/glob.js
deleted file mode 100644
index 7401e0b..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/glob.js
+++ /dev/null
@@ -1,649 +0,0 @@
-// Approach:
-//
-// 1. Get the minimatch set
-// 2. For each pattern in the set, PROCESS(pattern, false)
-// 3. Store matches per-set, then uniq them
-//
-// PROCESS(pattern, inGlobStar)
-// Get the first [n] items from pattern that are all strings
-// Join these together.  This is PREFIX.
-//   If there is no more remaining, then stat(PREFIX) and
-//   add to matches if it succeeds.  END.
-//
-// If inGlobStar and PREFIX is symlink and points to dir
-//   set ENTRIES = []
-// else readdir(PREFIX) as ENTRIES
-//   If fail, END
-//
-// with ENTRIES
-//   If pattern[n] is GLOBSTAR
-//     // handle the case where the globstar match is empty
-//     // by pruning it out, and testing the resulting pattern
-//     PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
-//     // handle other cases.
-//     for ENTRY in ENTRIES (not dotfiles)
-//       // attach globstar + tail onto the entry
-//       // Mark that this entry is a globstar match
-//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
-//
-//   else // not globstar
-//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
-//       Test ENTRY against pattern[n]
-//       If fails, continue
-//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
-//
-// Caveat:
-//   Cache all stats and readdirs results to minimize syscall.  Since all
-//   we ever care about is existence and directory-ness, we can just keep
-//   `true` for files, and [children,...] for directories, or `false` for
-//   things that don't exist.
-
-module.exports = glob
-
-var fs = require('fs')
-var minimatch = require('minimatch')
-var Minimatch = minimatch.Minimatch
-var inherits = require('inherits')
-var EE = require('events').EventEmitter
-var path = require('path')
-var assert = require('assert')
-var globSync = require('./sync.js')
-var common = require('./common.js')
-var alphasort = common.alphasort
-var alphasorti = common.alphasorti
-var isAbsolute = common.isAbsolute
-var setopts = common.setopts
-var ownProp = common.ownProp
-var inflight = require('inflight')
-var util = require('util')
-
-var once = require('once')
-
-function glob (pattern, options, cb) {
-  if (typeof options === 'function') cb = options, options = {}
-  if (!options) options = {}
-
-  if (options.sync) {
-    if (cb)
-      throw new TypeError('callback provided to sync glob')
-    return globSync(pattern, options)
-  }
-
-  return new Glob(pattern, options, cb)
-}
-
-glob.sync = globSync
-var GlobSync = glob.GlobSync = globSync.GlobSync
-
-// old api surface
-glob.glob = glob
-
-glob.hasMagic = function (pattern, options_) {
-  var options = util._extend({}, options_)
-  options.noprocess = true
-
-  var g = new Glob(pattern, options)
-  var set = g.minimatch.set
-  if (set.length > 1)
-    return true
-
-  for (var j = 0; j < set[0].length; j++) {
-    if (typeof set[0][j] !== 'string')
-      return true
-  }
-
-  return false
-}
-
-glob.Glob = Glob
-inherits(Glob, EE)
-function Glob (pattern, options, cb) {
-  if (typeof options === 'function') {
-    cb = options
-    options = null
-  }
-
-  if (options && options.sync) {
-    if (cb)
-      throw new TypeError('callback provided to sync glob')
-    return new GlobSync(pattern, options)
-  }
-
-  if (!(this instanceof Glob))
-    return new Glob(pattern, options, cb)
-
-  setopts(this, pattern, options)
-
-  // process each pattern in the minimatch set
-  var n = this.minimatch.set.length
-
-  // The matches are stored as {<filename>: true,...} so that
-  // duplicates are automagically pruned.
-  // Later, we do an Object.keys() on these.
-  // Keep them as a list so we can fill in when nonull is set.
-  this.matches = new Array(n)
-
-  if (typeof cb === 'function') {
-    cb = once(cb)
-    this.on('error', cb)
-    this.on('end', function (matches) {
-      cb(null, matches)
-    })
-  }
-
-  var self = this
-  var n = this.minimatch.set.length
-  this._processing = 0
-  this.matches = new Array(n)
-
-  this._emitQueue = []
-  this._processQueue = []
-  this.paused = false
-
-  if (this.noprocess)
-    return this
-
-  if (n === 0)
-    return done()
-
-  for (var i = 0; i < n; i ++) {
-    this._process(this.minimatch.set[i], i, false, done)
-  }
-
-  function done () {
-    --self._processing
-    if (self._processing <= 0)
-      self._finish()
-  }
-}
-
-Glob.prototype._finish = function () {
-  assert(this instanceof Glob)
-  if (this.aborted)
-    return
-
-  //console.error('FINISH', this.matches)
-  common.finish(this)
-  this.emit('end', this.found)
-}
-
-Glob.prototype._mark = function (p) {
-  return common.mark(this, p)
-}
-
-Glob.prototype._makeAbs = function (f) {
-  return common.makeAbs(this, f)
-}
-
-Glob.prototype.abort = function () {
-  this.aborted = true
-  this.emit('abort')
-}
-
-Glob.prototype.pause = function () {
-  if (!this.paused) {
-    this.paused = true
-    this.emit('pause')
-  }
-}
-
-Glob.prototype.resume = function () {
-  if (this.paused) {
-    this.emit('resume')
-    this.paused = false
-    if (this._emitQueue.length) {
-      var eq = this._emitQueue.slice(0)
-      this._emitQueue.length = 0
-      for (var i = 0; i < eq.length; i ++) {
-        var e = eq[i]
-        this._emitMatch(e[0], e[1])
-      }
-    }
-    if (this._processQueue.length) {
-      var pq = this._processQueue.slice(0)
-      this._processQueue.length = 0
-      for (var i = 0; i < pq.length; i ++) {
-        var p = pq[i]
-        this._processing--
-        this._process(p[0], p[1], p[2], p[3])
-      }
-    }
-  }
-}
-
-Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
-  assert(this instanceof Glob)
-  assert(typeof cb === 'function')
-
-  if (this.aborted)
-    return
-
-  this._processing++
-  if (this.paused) {
-    this._processQueue.push([pattern, index, inGlobStar, cb])
-    return
-  }
-
-  //console.error('PROCESS %d', this._processing, pattern)
-
-  // Get the first [n] parts of pattern that are all strings.
-  var n = 0
-  while (typeof pattern[n] === 'string') {
-    n ++
-  }
-  // now n is the index of the first one that is *not* a string.
-
-  // see if there's anything else
-  var prefix
-  switch (n) {
-    // if not, then this is rather simple
-    case pattern.length:
-      this._processSimple(pattern.join('/'), index, cb)
-      return
-
-    case 0:
-      // pattern *starts* with some non-trivial item.
-      // going to readdir(cwd), but not include the prefix in matches.
-      prefix = null
-      break
-
-    default:
-      // pattern has some string bits in the front.
-      // whatever it starts with, whether that's 'absolute' like /foo/bar,
-      // or 'relative' like '../baz'
-      prefix = pattern.slice(0, n).join('/')
-      break
-  }
-
-  var remain = pattern.slice(n)
-
-  // get the list of entries.
-  var read
-  if (prefix === null)
-    read = '.'
-  else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
-    if (!prefix || !isAbsolute(prefix))
-      prefix = '/' + prefix
-    read = prefix
-  } else
-    read = prefix
-
-  var abs = this._makeAbs(read)
-
-  var isGlobStar = remain[0] === minimatch.GLOBSTAR
-  if (isGlobStar)
-    this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
-  else
-    this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
-}
-
-
-Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
-  var self = this
-  this._readdir(abs, inGlobStar, function (er, entries) {
-    return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
-  })
-}
-
-Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-
-  // if the abs isn't a dir, then nothing can match!
-  if (!entries)
-    return cb()
-
-  // It will only match dot entries if it starts with a dot, or if
-  // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
-  var pn = remain[0]
-  var negate = !!this.minimatch.negate
-  var rawGlob = pn._glob
-  var dotOk = this.dot || rawGlob.charAt(0) === '.'
-
-  var matchedEntries = []
-  for (var i = 0; i < entries.length; i++) {
-    var e = entries[i]
-    if (e.charAt(0) !== '.' || dotOk) {
-      var m
-      if (negate && !prefix) {
-        m = !e.match(pn)
-      } else {
-        m = e.match(pn)
-      }
-      if (m)
-        matchedEntries.push(e)
-    }
-  }
-
-  //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
-
-  var len = matchedEntries.length
-  // If there are no matched entries, then nothing matches.
-  if (len === 0)
-    return cb()
-
-  // if this is the last remaining pattern bit, then no need for
-  // an additional stat *unless* the user has specified mark or
-  // stat explicitly.  We know they exist, since readdir returned
-  // them.
-
-  if (remain.length === 1 && !this.mark && !this.stat) {
-    if (!this.matches[index])
-      this.matches[index] = Object.create(null)
-
-    for (var i = 0; i < len; i ++) {
-      var e = matchedEntries[i]
-      if (prefix) {
-        if (prefix !== '/')
-          e = prefix + '/' + e
-        else
-          e = prefix + e
-      }
-
-      if (e.charAt(0) === '/' && !this.nomount) {
-        e = path.join(this.root, e)
-      }
-      this._emitMatch(index, e)
-    }
-    // This was the last one, and no stats were needed
-    return cb()
-  }
-
-  // now test all matched entries as stand-ins for that part
-  // of the pattern.
-  remain.shift()
-  for (var i = 0; i < len; i ++) {
-    var e = matchedEntries[i]
-    var newPattern
-    if (prefix) {
-      if (prefix !== '/')
-        e = prefix + '/' + e
-      else
-        e = prefix + e
-    }
-    this._process([e].concat(remain), index, inGlobStar, cb)
-  }
-  cb()
-}
-
-Glob.prototype._emitMatch = function (index, e) {
-  if (this.aborted)
-    return
-
-  if (!this.matches[index][e]) {
-    if (this.paused) {
-      this._emitQueue.push([index, e])
-      return
-    }
-
-    if (this.nodir) {
-      var c = this.cache[this._makeAbs(e)]
-      if (c === 'DIR' || Array.isArray(c))
-        return
-    }
-
-    this.matches[index][e] = true
-    if (!this.stat && !this.mark)
-      return this.emit('match', e)
-
-    var self = this
-    this._stat(this._makeAbs(e), function (er, c, st) {
-      self.emit('stat', e, st)
-      self.emit('match', e)
-    })
-  }
-}
-
-Glob.prototype._readdirInGlobStar = function (abs, cb) {
-  if (this.aborted)
-    return
-
-  var lstatkey = 'lstat\0' + abs
-  var self = this
-  var lstatcb = inflight(lstatkey, lstatcb_)
-
-  if (lstatcb)
-    fs.lstat(abs, lstatcb)
-
-  function lstatcb_ (er, lstat) {
-    if (er)
-      return cb()
-
-    var isSym = lstat.isSymbolicLink()
-    self.symlinks[abs] = isSym
-
-    // If it's not a symlink or a dir, then it's definitely a regular file.
-    // don't bother doing a readdir in that case.
-    if (!isSym && !lstat.isDirectory()) {
-      self.cache[abs] = 'FILE'
-      cb()
-    } else
-      self._readdir(abs, false, cb)
-  }
-}
-
-Glob.prototype._readdir = function (abs, inGlobStar, cb) {
-  if (this.aborted)
-    return
-
-  cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
-  if (!cb)
-    return
-
-  //console.error('RD %j %j', +inGlobStar, abs)
-  if (inGlobStar && !ownProp(this.symlinks, abs))
-    return this._readdirInGlobStar(abs, cb)
-
-  if (ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-    if (!c || c === 'FILE')
-      return cb()
-
-    if (Array.isArray(c))
-      return cb(null, c)
-  }
-
-  var self = this
-  fs.readdir(abs, readdirCb(this, abs, cb))
-}
-
-function readdirCb (self, abs, cb) {
-  return function (er, entries) {
-    if (er)
-      self._readdirError(abs, er, cb)
-    else
-      self._readdirEntries(abs, entries, cb)
-  }
-}
-
-Glob.prototype._readdirEntries = function (abs, entries, cb) {
-  if (this.aborted)
-    return
-
-  // if we haven't asked to stat everything, then just
-  // assume that everything in there exists, so we can avoid
-  // having to stat it a second time.
-  if (!this.mark && !this.stat) {
-    for (var i = 0; i < entries.length; i ++) {
-      var e = entries[i]
-      if (abs === '/')
-        e = abs + e
-      else
-        e = abs + '/' + e
-      this.cache[e] = true
-    }
-  }
-
-  this.cache[abs] = entries
-  return cb(null, entries)
-}
-
-Glob.prototype._readdirError = function (f, er, cb) {
-  if (this.aborted)
-    return
-
-  // handle errors, and cache the information
-  switch (er.code) {
-    case 'ENOTDIR': // totally normal. means it *does* exist.
-      this.cache[f] = 'FILE'
-      break
-
-    case 'ENOENT': // not terribly unusual
-    case 'ELOOP':
-    case 'ENAMETOOLONG':
-    case 'UNKNOWN':
-      this.cache[f] = false
-      break
-
-    default: // some unusual error.  Treat as failure.
-      this.cache[f] = false
-      if (this.strict) return this.emit('error', er)
-      if (!this.silent) console.error('glob error', er)
-      break
-  }
-  return cb()
-}
-
-Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
-  var self = this
-  this._readdir(abs, inGlobStar, function (er, entries) {
-    self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
-  })
-}
-
-
-Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-  //console.error('pgs2', prefix, remain[0], entries)
-
-  // no entries means not a dir, so it can never have matches
-  // foo.txt/** doesn't match foo.txt
-  if (!entries)
-    return cb()
-
-  // test without the globstar, and with every child both below
-  // and replacing the globstar.
-  var remainWithoutGlobStar = remain.slice(1)
-  var gspref = prefix ? [ prefix ] : []
-  var noGlobStar = gspref.concat(remainWithoutGlobStar)
-
-  // the noGlobStar pattern exits the inGlobStar state
-  this._process(noGlobStar, index, false, cb)
-
-  var isSym = this.symlinks[abs]
-  var len = entries.length
-
-  // If it's a symlink, and we're in a globstar, then stop
-  if (isSym && inGlobStar)
-    return cb()
-
-  for (var i = 0; i < len; i++) {
-    var e = entries[i]
-    if (e.charAt(0) === '.' && !this.dot)
-      continue
-
-    // these two cases enter the inGlobStar state
-    var instead = gspref.concat(entries[i], remainWithoutGlobStar)
-    this._process(instead, index, true, cb)
-
-    var below = gspref.concat(entries[i], remain)
-    this._process(below, index, true, cb)
-  }
-
-  cb()
-}
-
-Glob.prototype._processSimple = function (prefix, index, cb) {
-  // XXX review this.  Shouldn't it be doing the mounting etc
-  // before doing stat?  kinda weird?
-  var self = this
-  this._stat(prefix, function (er, exists) {
-    self._processSimple2(prefix, index, er, exists, cb)
-  })
-}
-Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
-
-  //console.error('ps2', prefix, exists)
-
-  if (!this.matches[index])
-    this.matches[index] = Object.create(null)
-
-  // If it doesn't exist, then just mark the lack of results
-  if (!exists)
-    return cb()
-
-  if (prefix && isAbsolute(prefix) && !this.nomount) {
-    var trail = /[\/\\]$/.test(prefix)
-    if (prefix.charAt(0) === '/') {
-      prefix = path.join(this.root, prefix)
-    } else {
-      prefix = path.resolve(this.root, prefix)
-      if (trail)
-        prefix += '/'
-    }
-  }
-
-  if (process.platform === 'win32')
-    prefix = prefix.replace(/\\/g, '/')
-
-  // Mark this as a match
-  this._emitMatch(index, prefix)
-  cb()
-}
-
-// Returns either 'DIR', 'FILE', or false
-Glob.prototype._stat = function (f, cb) {
-  var abs = f
-  if (f.charAt(0) === '/')
-    abs = path.join(this.root, f)
-  else if (this.changedCwd)
-    abs = path.resolve(this.cwd, f)
-
-
-  if (f.length > this.maxLength)
-    return cb()
-
-  if (!this.stat && ownProp(this.cache, f)) {
-    var c = this.cache[f]
-
-    if (Array.isArray(c))
-      c = 'DIR'
-
-    // It exists, but not how we need it
-    if (abs.slice(-1) === '/' && c !== 'DIR')
-      return cb()
-
-    return cb(null, c)
-  }
-
-  var exists
-  var stat = this.statCache[abs]
-  if (stat !== undefined) {
-    if (stat === false)
-      return cb(null, stat)
-    else
-      return cb(null, stat.isDirectory() ? 'DIR' : 'FILE', stat)
-  }
-
-  var self = this
-  var statcb = inflight('stat\0' + abs, statcb_)
-  if (statcb)
-    fs.stat(abs, statcb)
-
-  function statcb_ (er, stat) {
-    self._stat2(f, abs, er, stat, cb)
-  }
-}
-
-Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
-  if (er) {
-    this.statCache[abs] = false
-    return cb()
-  }
-
-  this.statCache[abs] = stat
-
-  if (abs.slice(-1) === '/' && !stat.isDirectory())
-    return cb(null, false, stat)
-
-  var c = stat.isDirectory() ? 'DIR' : 'FILE'
-  this.cache[f] = this.cache[f] || c
-  return cb(null, c, stat)
-}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/.eslintrc b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/.eslintrc
deleted file mode 100644
index b7a1550..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/.eslintrc
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "env" : {
-    "node" : true
-  },
-  "rules" : {
-    "semi": [2, "never"],
-    "strict": 0,
-    "quotes": [1, "single", "avoid-escape"],
-    "no-use-before-define": 0,
-    "curly": 0,
-    "no-underscore-dangle": 0,
-    "no-lonely-if": 1,
-    "no-unused-vars": [2, {"vars" : "all", "args" : "after-used"}],
-    "no-mixed-requires": 0,
-    "space-infix-ops": 0
-  }
-}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/LICENSE b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/LICENSE
deleted file mode 100644
index 05eeeb8..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/README.md b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/README.md
deleted file mode 100644
index 6dc8929..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# inflight
-
-Add callbacks to requests in flight to avoid async duplication
-
-## USAGE
-
-```javascript
-var inflight = require('inflight')
-
-// some request that does some stuff
-function req(key, callback) {
-  // key is any random string.  like a url or filename or whatever.
-  //
-  // will return either a falsey value, indicating that the
-  // request for this key is already in flight, or a new callback
-  // which when called will call all callbacks passed to inflightk
-  // with the same key
-  callback = inflight(key, callback)
-
-  // If we got a falsey value back, then there's already a req going
-  if (!callback) return
-
-  // this is where you'd fetch the url or whatever
-  // callback is also once()-ified, so it can safely be assigned
-  // to multiple events etc.  First call wins.
-  setTimeout(function() {
-    callback(null, key)
-  }, 100)
-}
-
-// only assigns a single setTimeout
-// when it dings, all cbs get called
-req('foo', cb1)
-req('foo', cb2)
-req('foo', cb3)
-req('foo', cb4)
-```
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/inflight.js b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/inflight.js
deleted file mode 100644
index 8bc96cb..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/inflight.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var wrappy = require('wrappy')
-var reqs = Object.create(null)
-var once = require('once')
-
-module.exports = wrappy(inflight)
-
-function inflight (key, cb) {
-  if (reqs[key]) {
-    reqs[key].push(cb)
-    return null
-  } else {
-    reqs[key] = [cb]
-    return makeres(key)
-  }
-}
-
-function makeres (key) {
-  return once(function RES () {
-    var cbs = reqs[key]
-    var len = cbs.length
-    var args = slice(arguments)
-    for (var i = 0; i < len; i++) {
-      cbs[i].apply(null, args)
-    }
-    if (cbs.length > len) {
-      // added more in the interim.
-      // de-zalgo, just in case, but don't call again.
-      cbs.splice(0, len)
-      process.nextTick(function () {
-        RES.apply(null, args)
-      })
-    } else {
-      delete reqs[key]
-    }
-  })
-}
-
-function slice (args) {
-  var length = args.length
-  var array = []
-
-  for (var i = 0; i < length; i++) array[i] = args[i]
-  return array
-}
diff --git a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/LICENSE b/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/LICENSE
deleted file mode 100644
index 19129e3..0000000
--- a/node_modules/gulp-load-plugins/node_modules/findup-sync/node_modules/glob/node_modules/inflight/node_modules/wrappy/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyr…
@zanona
Copy link

zanona commented Oct 15, 2017

Wow, it would be really awesome to have this so we could have source maps for HTML files with inline scripts on different parts of a document, especially web components. Can I please just confirm if the spec proposes this but it has not been used or implemented yet?
Thanks guys

zanona pushed a commit to zanona/pakku that referenced this issue Oct 15, 2017
After hours researching and trying to implement source maps, it seems
currently it's not possible to have multiple sections of a document
pointing to different mappings due to the nature of mappings always
using the base reference on the minified document starting with the
column index, meaning it would always be a single line.
```
[mincol,sources_index,rawline,rawcol,names_index]
```
considering this, mincol will not accept muliple lines.
The v3 spec for source maps has a proposal for the `sections` see
https://sourcemaps.info/spec.html where a user would be able to declare
multiple sections for different parts of a document, however this hasn't
been implemented yet and I am not sure it ever will be.

There's a current discussion about this at
mozilla/source-map#16, but it's unlikely there
will be progress on it since it's open since 2012 and last activity on
2015.

Anyway, I will be leaving this on hold until we have a solid solution to
work with this sort of section or when I need to provide source maps for
pure js files, which I am not been using too much lately :)
@tromey
Copy link
Contributor

tromey commented Oct 17, 2017

Wow, it would be really awesome to have this so we could have source maps for HTML files with inline scripts on different parts of a document, especially web components. Can I please just confirm if the spec proposes this but it has not been used or implemented yet?

Inline <script> can set the source map URL (and the sourceURL if desired). This can work fine without needing the sections approach. However, there are still some bugs in this area in Firefox at least. I'm not totally sure this answers your question...?

@zanona
Copy link

zanona commented Oct 17, 2017

Thanks, @tromey!
I actually meant when you have multiple <script> tags in a single HTML file since only one sourceMappingURL declaration is accepted per file. I actually did some tests yesterday and could get it working well in Chrome with sections defined, which was great 😄
Perhaps that's already good enough because when I first saw this issue opened I wondered if the section feature was actually implemented or just a proposal.

@tromey
Copy link
Contributor

tromey commented Oct 18, 2017

I actually meant when you have multiple <script> tags in a single HTML file since only one sourceMappingURL declaration is accepted per file.

I think the intent is that each separate <script> can have its own sourceMappingURL; but like I mentioned, there are some bugs in the Firefox devtools in this area. I don't think source-mapping the entire HTML document is supported (if it is, that must be some browser's own extension).

I wondered if the section feature was actually implemented or just a proposal.

I think it is implemented; however, in this library, there's no support for a sectioned source map where the sections are not inlined. Nobody ever implemented the proposed fetching API.

zanona pushed a commit to zanona/pakku that referenced this issue Oct 19, 2017
After hours researching and trying to implement source maps, it seems
currently it's not possible to have multiple sections of a document
pointing to different mappings due to the nature of mappings always
using the base reference on the minified document starting with the
column index, meaning it would always be a single line.
```
[mincol,sources_index,rawline,rawcol,names_index]
```
considering this, mincol will not accept muliple lines.
The v3 spec for source maps has a proposal for the `sections` see
https://sourcemaps.info/spec.html where a user would be able to declare
multiple sections for different parts of a document, however this hasn't
been implemented yet and I am not sure it ever will be.

There's a current discussion about this at
mozilla/source-map#16, but it's unlikely there
will be progress on it since it's open since 2012 and last activity on
2015.

Anyway, I will be leaving this on hold until we have a solid solution to
work with this sort of section or when I need to provide source maps for
pure js files, which I am not been using too much lately :)
@jkrems
Copy link
Collaborator

jkrems commented Apr 13, 2021

The basic feature (support for indexed source maps) has been implemented in its most commonly used form (embedded map, not external url reference). I created #437 to track support for external URLs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
10 participants