diff --git a/examples/full/bundle.config.js b/examples/full/bundle.config.js
index a1fc7125..9a28903d 100644
--- a/examples/full/bundle.config.js
+++ b/examples/full/bundle.config.js
@@ -135,7 +135,11 @@ module.exports = {
copy: [
{
src: './bower_components/bootstrap/dist/fonts/**/*.*',
- base: './bower_components/bootstrap/dist/'
+ base: './bower_components/bootstrap/dist/',
+ watch: false
+ },
+ {
+ src: './partials/**/*.*'
},
'./images/**/*.*'
]
diff --git a/examples/full/partials/a-partial-file.html b/examples/full/partials/a-partial-file.html
new file mode 100644
index 00000000..750a2ff4
--- /dev/null
+++ b/examples/full/partials/a-partial-file.html
@@ -0,0 +1,3 @@
+
+ yo
+
\ No newline at end of file
diff --git a/examples/full/public/partials/a-partial-file.html b/examples/full/public/partials/a-partial-file.html
new file mode 100644
index 00000000..750a2ff4
--- /dev/null
+++ b/examples/full/public/partials/a-partial-file.html
@@ -0,0 +1,3 @@
+
+ yo
+
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
index 6744a282..160446af 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -57,7 +57,7 @@ gulp.task('test-cover', 'Unit tests and coverage', function (cb) {
thresholds : {
statements : 95,
branches : 92,
- functions : 95,
+ functions : 94,
lines : 95
},
coverageDirectory : 'coverage',
diff --git a/lib/service/logger.js b/lib/service/logger.js
index e87adc21..ad3f107d 100644
--- a/lib/service/logger.js
+++ b/lib/service/logger.js
@@ -7,6 +7,7 @@ function Logger() {
Logger.prototype.log = function () {
var config = cache.get('config');
if (!config || !config.options || config.options.quietMode !== true) {
+ // replace with gulp logger once it's done? https://github.com/gulpjs/gulp-util/issues/33
gutil.log.apply(gutil.log, arguments);
}
};
diff --git a/lib/stream-bundles-util.js b/lib/stream-bundles-util.js
new file mode 100644
index 00000000..1004a2a1
--- /dev/null
+++ b/lib/stream-bundles-util.js
@@ -0,0 +1,16 @@
+var logger = require('./service/logger'),
+ gutil = require('gulp-util'),
+ warnPrefix = gutil.colors.bgYellow.black('WARN');
+
+function StreamBundlesUtil() {
+}
+
+StreamBundlesUtil.prototype.warnIfNoBundleProperty = function (config) {
+ if (config && !config.bundle && config.file && config.file.relative) { // can guarantee !!file b/c (config instanceof Config)
+ logger.log(warnPrefix, "No '" + gutil.colors.cyan('bundle') +
+ "' property found in " + gutil.colors.magenta(config.file.relative) + ". Did you mean to define one?");
+ }
+};
+
+// naturally a singleton because node's require caches the value assigned to module.exports
+module.exports = new StreamBundlesUtil();
\ No newline at end of file
diff --git a/lib/stream-bundles-watch.js b/lib/stream-bundles-watch.js
index c9939105..c885fdbd 100644
--- a/lib/stream-bundles-watch.js
+++ b/lib/stream-bundles-watch.js
@@ -14,7 +14,9 @@ var through = require('through2'),
bundleDone = require('./watch/bundle-done'),
initOptionDefaults = require('./init-option-defaults'),
results = require('./results').incremental,
- streamFiles = require('./stream-files');
+ streamFiles = require('./stream-files'),
+ streamCopy = require('./stream-copy'),
+ streamBundlesUtil = require('./stream-bundles-util');
function _bundle(config, env) {
var bundles = config.bundle,
@@ -126,15 +128,61 @@ function _bundle(config, env) {
}
+function watchStringCopyStream(config, item, base) {
+ gulp.watch(item)
+ .on('change', function (file) { // log changed file?
+ streamCopy.getStringCopyStream(item, base)
+ .pipe(gulp.dest(config.options.dest));
+ });
+}
+
+function watchObjectCopyStream(config, item, base) {
+ var watchPath = pathifySrc(item.src, base);
+ gulp.watch(watchPath)
+ .on('change', function (file) { // log changed file?
+ streamCopy.getObjectCopyStream(item, base)
+ .pipe(gulp.dest(config.options.dest));
+ });
+}
+
+function _copy(config) {
+ var base = (config.options) ? config.options.base : '.'; // can guarantee !!options b/c (config instanceof Config)
+
+ logger.log("Starting '" + gutil.colors.cyan("watch") + "' for files to copy...");
+
+ if (typeof config.copy === 'string') {
+ watchStringCopyStream(config, config.copy, base);
+ } else if (util.isArray(config.copy)) {
+ _.forEach(config.copy, function (item) {
+ if (typeof item === 'string') {
+ return watchStringCopyStream(config, item, base);
+ } else if (typeof item === 'object' && !util.isArray(item) &&
+ config.copy.watch !== false) {
+ return watchObjectCopyStream(config, item, base);
+ }
+ streamCopy.throwUnsupportedSyntaxError();
+ });
+ } else if (typeof config.copy === 'object' && config.copy.watch !== false) {
+ watchObjectCopyStream(config, config.copy, base);
+ } else {
+ streamCopy.throwUnsupportedSyntaxError();
+ }
+}
+
function bundle(config) {
+
if (config.bundle) {
if (config.options && config.options.bundleAllEnvironments) { // can guarantee !!options b/c (config instanceof Config)
bundleAllEnvironments(config, _bundle);
} else {
_bundle(config, process.env.NODE_ENV);
}
- } else {
- throw new gutil.PluginError('gulp-bundle-assets', 'Missing required config property "bundle"');
+ }
+
+ streamBundlesUtil.warnIfNoBundleProperty(config);
+
+ if (config.copy) {
+ _copy(config);
}
}
diff --git a/lib/stream-bundles.js b/lib/stream-bundles.js
index 13b4c906..d1b23cb1 100644
--- a/lib/stream-bundles.js
+++ b/lib/stream-bundles.js
@@ -1,8 +1,5 @@
-var path = require('path'),
- util = require('util'),
+var util = require('util'),
BundleKeys = require('./model/bundle-keys'),
- gulp = require('gulp'),
- using = require('./using'),
gutil = require('gulp-util'),
logger = require('./service/logger'),
_ = require('lodash'),
@@ -11,46 +8,8 @@ var path = require('path'),
bundleAllEnvironments = require('./bundle-all-environments'),
initOptionDefaults = require('./init-option-defaults'),
streamFiles = require('./stream-files'),
- warnPrefix = gutil.colors.bgYellow.black('WARN');
-
-// assume configBase will ALWAYS be defined (and defaulted to '.')
-function getCustomBase(configBase, relativeBase) {
- if (!relativeBase) {
- return configBase;
- }
- return path.join(configBase, relativeBase);
-}
-
-/**
- *
- * @param {String} item
- * @param base
- * @returns {*}
- */
-function getStringCopyStream(item, base) {
- return gulp.src(pathifySrc(item, base), { base: base })
- .pipe(using.copy(base));
-}
-
-/**
- * @param {Object} item
- * @param base
- * @returns {*}
- */
-function getObjectCopyStream(item, base) {
- return gulp.src(pathifySrc(item.src, base), { base: getCustomBase(base, item.base) })
- .pipe(using.copy(base));
-}
-
-function getCopyStream(item, base) {
- if (typeof item === 'string') {
- return getStringCopyStream(item, base);
- } else if (typeof item === 'object' && !util.isArray(item)) {
- return getObjectCopyStream(item, base);
- }
- throw new gutil.PluginError('gulp-bundle-assets', 'Unsupported syntax for copy. See here for supported variations: ' +
- 'https://github.com/chmontgomery/gulp-bundle-assets/blob/master/examples/copy/bundle.config.js');
-}
+ streamCopy = require('./stream-copy'),
+ streamBundlesUtil = require('./stream-bundles-util');
function _bundle(config, env) {
var streams = [],
@@ -98,38 +57,42 @@ function _bundle(config, env) {
return streams;
}
-
-function bundle(config) {
+function _copy(config) {
var streams = [],
copy = config.copy,
base = (config.options) ? config.options.base : '.'; // can guarantee !!options b/c (config instanceof Config)
+ if (typeof copy === 'string') {
+ streams.push(streamCopy.getStringCopyStream(copy, base));
+ } else if (util.isArray(copy)) {
+ _.forEach(copy, function (item) {
+ streams.push(streamCopy.getCopyStream(item, base));
+ });
+ } else if (typeof copy === 'object') {
+ streams.push(streamCopy.getObjectCopyStream(copy, base));
+ } else {
+ streamCopy.throwUnsupportedSyntaxError();
+ }
+
+ return streams;
+}
+
+
+function bundle(config) {
+ var streams = [];
+
if (config.bundle) {
if (config.options && config.options.bundleAllEnvironments) { // can guarantee !!options b/c (config instanceof Config)
streams = streams.concat(bundleAllEnvironments(config, _bundle));
} else {
streams = streams.concat(_bundle(config, process.env.NODE_ENV));
}
- } else if (config && config.file && config.file.relative) { // can guarantee !!file b/c (config instanceof Config)
- // replace with gulp logger once they're done with it https://github.com/gulpjs/gulp-util/issues/33
- logger.log(warnPrefix, "No '" + gutil.colors.cyan('bundle') +
- "' property found in " + gutil.colors.magenta(config.file.relative) + ". Did you mean to define one?");
}
- if (copy) {
-
- if (typeof copy === 'string') {
- streams.push(getStringCopyStream(copy, base));
- } else if (util.isArray(copy)) {
- _.forEach(copy, function (item) {
- streams.push(getCopyStream(item, base));
- });
- } else if (typeof copy === 'object') {
- streams.push(getObjectCopyStream(copy, base));
- } else {
- throw new gutil.PluginError('gulp-bundle-assets', 'Unsupported syntax for copy. Should be a string, array or object.');
- }
+ streamBundlesUtil.warnIfNoBundleProperty(config);
+ if (config.copy) {
+ streams = streams.concat(_copy(config));
}
return streams;
diff --git a/lib/stream-copy.js b/lib/stream-copy.js
new file mode 100644
index 00000000..9c22fe5a
--- /dev/null
+++ b/lib/stream-copy.js
@@ -0,0 +1,54 @@
+var gulp = require('gulp'),
+ gutil = require('gulp-util'),
+ util = require('util'),
+ path = require('path'),
+ using = require('./using'),
+ pathifySrc = require('./pathify-config-src');
+
+function StreamCopy() {
+}
+
+// assume configBase will ALWAYS be defined (and defaulted to '.')
+StreamCopy.prototype.getCustomBase = function (configBase, relativeBase) {
+ if (!relativeBase) {
+ return configBase;
+ }
+ return path.join(configBase, relativeBase);
+};
+
+/**
+ * @param {String} item
+ * @param base
+ * @returns {*}
+ */
+StreamCopy.prototype.getStringCopyStream = function (item, base) {
+ return gulp.src(pathifySrc(item, base), { base: base })
+ .pipe(using.copy(base));
+};
+
+/**
+ * @param {Object} item
+ * @param base
+ * @returns {*}
+ */
+StreamCopy.prototype.getObjectCopyStream = function (item, base) {
+ return gulp.src(pathifySrc(item.src, base), { base: this.getCustomBase(base, item.base) })
+ .pipe(using.copy(base));
+};
+
+StreamCopy.prototype.getCopyStream = function (item, base) {
+ if (typeof item === 'string') {
+ return this.getStringCopyStream(item, base);
+ } else if (typeof item === 'object' && !util.isArray(item)) {
+ return this.getObjectCopyStream(item, base);
+ }
+ this.throwUnsupportedSyntaxError();
+};
+
+StreamCopy.prototype.throwUnsupportedSyntaxError = function () {
+ throw new gutil.PluginError('gulp-bundle-assets', 'Unsupported syntax for copy. See here for supported variations: ' +
+ 'https://github.com/chmontgomery/gulp-bundle-assets/blob/master/examples/copy/bundle.config.js');
+};
+
+// naturally a singleton because node's require caches the value assigned to module.exports
+module.exports = new StreamCopy();
\ No newline at end of file
diff --git a/test/integ/index-test.js b/test/integ/index-test.js
index b49f9f2d..6b24aa6b 100644
--- a/test/integ/index-test.js
+++ b/test/integ/index-test.js
@@ -427,15 +427,16 @@ describe('integration tests', function () {
file.relative === 'fonts/glyphicons-halflings-regular.ttf' ||
file.relative === 'fonts/glyphicons-halflings-regular.woff' ||
file.relative === 'images/empire_icon.png' ||
- file.relative === 'images/rebel_icon.png') {
+ file.relative === 'images/rebel_icon.png' ||
+ file.relative === 'partials/a-partial-file.html' ) {
staticFileCount++;
} else {
helpers.errorUnexpectedFileInStream(file);
}
fileCount++;
}, function () {
- (fileCount).should.eql(22);
- (staticFileCount).should.eql(14);
+ (fileCount).should.eql(23);
+ (staticFileCount).should.eql(15);
});
});
diff --git a/test/unit/stream-bundles-watch-test.js b/test/unit/stream-bundles-watch-test.js
index 24cd7b2f..8e688a2b 100644
--- a/test/unit/stream-bundles-watch-test.js
+++ b/test/unit/stream-bundles-watch-test.js
@@ -78,4 +78,159 @@ describe('stream-bundles-watch', function () {
});
+ it('should start watch for copy files string', function (done) {
+
+ watchReturn.on = function (eventName, fn) {
+ eventName.should.eql('change');
+ fn.should.be.type('function');
+ };
+ sinon.spy(watchReturn, 'on');
+ gulpStub.watch = sinon.stub().returns(watchReturn);
+ streamBundlesWatch = proxyquire(libPath + '/stream-bundles-watch',
+ { 'gulp': gulpStub });
+
+ var config = new ConfigModel({
+ copy: 'some/file'
+ }, {});
+
+ streamBundlesWatch(config);
+
+ gulpStub.watch.calledOnce.should.be.ok;
+ watchReturn.on.calledOnce.should.be.ok;
+
+ done();
+
+ });
+
+ it('should start watch for copy files array', function (done) {
+
+ watchReturn.on = function (eventName, fn) {
+ eventName.should.eql('change');
+ fn.should.be.type('function');
+ };
+ sinon.spy(watchReturn, 'on');
+ gulpStub.watch = sinon.stub().returns(watchReturn);
+ streamBundlesWatch = proxyquire(libPath + '/stream-bundles-watch',
+ { 'gulp': gulpStub });
+
+ var config = new ConfigModel({
+ copy: [
+ 'some/file',
+ 'some/file2'
+ ]
+ }, {});
+
+ streamBundlesWatch(config);
+
+ gulpStub.watch.calledTwice.should.be.ok;
+ watchReturn.on.calledTwice.should.be.ok;
+
+ done();
+
+ });
+
+ it('should start watch for copy files object', function (done) {
+
+ watchReturn.on = function (eventName, fn) {
+ eventName.should.eql('change');
+ fn.should.be.type('function');
+ };
+ sinon.spy(watchReturn, 'on');
+ gulpStub.watch = sinon.stub().returns(watchReturn);
+ streamBundlesWatch = proxyquire(libPath + '/stream-bundles-watch',
+ { 'gulp': gulpStub });
+
+ var config = new ConfigModel({
+ copy: {
+ src: 'some/file',
+ base: 'some'
+ }
+ }, {});
+
+ streamBundlesWatch(config);
+
+ gulpStub.watch.calledOnce.should.be.ok;
+ watchReturn.on.calledOnce.should.be.ok;
+
+ done();
+
+ });
+
+ it('should start watch for copy files object in array', function (done) {
+
+ watchReturn.on = function (eventName, fn) {
+ eventName.should.eql('change');
+ fn.should.be.type('function');
+ };
+ sinon.spy(watchReturn, 'on');
+ gulpStub.watch = sinon.stub().returns(watchReturn);
+ streamBundlesWatch = proxyquire(libPath + '/stream-bundles-watch',
+ { 'gulp': gulpStub });
+
+ var config = new ConfigModel({
+ copy: [
+ {
+ src: 'some/file',
+ base: 'some'
+ }
+ ]
+ }, {});
+
+ streamBundlesWatch(config);
+
+ gulpStub.watch.calledOnce.should.be.ok;
+ watchReturn.on.calledOnce.should.be.ok;
+
+ done();
+
+ });
+
+ it('should throw error for invalid copy property value type', function (done) {
+
+ watchReturn.on = function (eventName, fn) {
+ eventName.should.eql('change');
+ fn.should.be.type('function');
+ };
+ sinon.spy(watchReturn, 'on');
+ gulpStub.watch = sinon.stub().returns(watchReturn);
+ streamBundlesWatch = proxyquire(libPath + '/stream-bundles-watch',
+ { 'gulp': gulpStub });
+
+ var config = new ConfigModel({
+ copy: true
+ }, {});
+
+ (function () {
+ streamBundlesWatch(config);
+ }).should.throw(/^Unsupported syntax for copy./);
+
+ done();
+
+ });
+
+ it('should throw error for invalid nested copy property value type', function (done) {
+
+ watchReturn.on = function (eventName, fn) {
+ eventName.should.eql('change');
+ fn.should.be.type('function');
+ };
+ sinon.spy(watchReturn, 'on');
+ gulpStub.watch = sinon.stub().returns(watchReturn);
+ streamBundlesWatch = proxyquire(libPath + '/stream-bundles-watch',
+ { 'gulp': gulpStub });
+
+ var config = new ConfigModel({
+ copy: [
+ true
+ ]
+ }, {});
+
+ (function () {
+ streamBundlesWatch(config);
+ }).should.throw(/^Unsupported syntax for copy./);
+
+ done();
+
+ });
+
});