plyr/gulpfile.js
2017-11-04 23:18:47 +11:00

354 lines
11 KiB
JavaScript

// ==========================================================================
// Gulp build script
// ==========================================================================
/*global require, __dirname,Buffer*/
/*jshint -W079 */
var fs = require('fs'),
path = require('path'),
gulp = require('gulp'),
gutil = require('gulp-util'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
less = require('gulp-less'),
sass = require('gulp-sass'),
cleanCSS = require('gulp-clean-css'),
run = require('run-sequence'),
prefix = require('gulp-autoprefixer'),
svgstore = require('gulp-svgstore'),
svgmin = require('gulp-svgmin'),
rename = require('gulp-rename'),
s3 = require('gulp-s3'),
replace = require('gulp-replace'),
open = require('gulp-open'),
size = require('gulp-size'),
through = require('through2');
var root = __dirname,
paths = {
plyr: {
// Source paths
src: {
less: path.join(root, 'src/less/**/*'),
scss: path.join(root, 'src/scss/**/*'),
js: path.join(root, 'src/js/**/*'),
sprite: path.join(root, 'src/sprite/*.svg'),
},
// Output paths
output: path.join(root, 'dist/'),
},
demo: {
// Source paths
src: {
less: path.join(root, 'demo/src/less/**/*'),
js: path.join(root, 'demo/src/js/**/*'),
sprite: path.join(root, 'demo/src/sprite/**/*'),
},
// Output paths
output: path.join(root, 'demo/dist/'),
// Demo
root: path.join(root, 'demo/'),
},
upload: [path.join(root, 'dist/**'), path.join(root, 'demo/dist/**')],
},
// Task arrays
tasks = {
less: [],
scss: [],
js: [],
sprite: [],
},
// Fetch bundles from JSON
bundles = loadJSON(path.join(root, 'bundles.json')),
package = loadJSON(path.join(root, 'package.json'));
// Load json
function loadJSON(path) {
try {
return JSON.parse(fs.readFileSync(path));
} catch (err) {
return {};
}
}
// Create a file from a string
// http://stackoverflow.com/questions/23230569/how-do-you-create-a-file-from-a-string-in-gulp
function createFile(filename, string) {
var src = require('stream').Readable({
objectMode: true,
});
src._read = function() {
this.push(
new gutil.File({
cwd: '',
base: '',
path: filename,
contents: new Buffer(string),
// stats also required for some functions
// https://nodejs.org/api/fs.html#fs_class_fs_stats
stat: {
size: string.length,
},
}),
);
this.push(null);
};
return src;
}
var build = {
js: function(files, bundle) {
for (var key in files) {
(function(key) {
var name = 'js-' + key;
tasks.js.push(name);
gulp.task(name, function() {
return gulp
.src(bundles[bundle].js[key])
.pipe(concat(key))
.pipe(uglify().on('error', gutil.log))
.pipe(gulp.dest(paths[bundle].output));
});
})(key);
}
},
less: function(files, bundle) {
for (var key in files) {
(function(key) {
var name = 'less-' + key;
tasks.less.push(name);
gulp.task(name, function() {
return gulp
.src(bundles[bundle].less[key])
.pipe(less())
.on('error', gutil.log)
.pipe(concat(key))
.pipe(prefix(['last 2 versions'], { cascade: true }))
.pipe(cleanCSS())
.pipe(gulp.dest(paths[bundle].output));
});
})(key);
}
},
scss: function(files, bundle) {
for (var key in files) {
(function(key) {
var name = 'scss-' + key;
tasks.scss.push(name);
gulp.task(name, function() {
return gulp
.src(bundles[bundle].scss[key])
.pipe(sass())
.on('error', gutil.log)
.pipe(concat(key))
.pipe(prefix(['last 2 versions'], { cascade: true }))
.pipe(cleanCSS())
.pipe(gulp.dest(paths[bundle].output));
});
})(key);
}
},
sprite: function(bundle) {
var name = 'sprite-' + bundle;
tasks.sprite.push(name);
// Process Icons
gulp.task(name, function() {
return gulp
.src(paths[bundle].src.sprite)
.pipe(
svgmin({
plugins: [
{
removeDesc: true,
},
],
}),
)
.pipe(svgstore())
.pipe(rename({ basename: bundle }))
.pipe(gulp.dest(paths[bundle].output));
});
},
};
// Plyr core files
build.js(bundles.plyr.js, 'plyr');
build.less(bundles.plyr.less, 'plyr');
build.scss(bundles.plyr.scss, 'plyr');
build.sprite('plyr');
// Demo files
build.less(bundles.demo.less, 'demo');
build.js(bundles.demo.js, 'demo');
build.sprite('demo');
// Build all JS
gulp.task('js', function() {
run(tasks.js);
});
// Build SCSS (for testing, default is LESS)
gulp.task('scss', function() {
run(tasks.scss);
});
// Watch for file changes
gulp.task('watch', function() {
// Plyr core
gulp.watch(paths.plyr.src.js, tasks.js);
gulp.watch(paths.plyr.src.less, tasks.less);
gulp.watch(paths.plyr.src.sprite, tasks.sprite);
// Demo
gulp.watch(paths.demo.src.js, tasks.js);
gulp.watch(paths.demo.src.less, tasks.less);
gulp.watch(paths.demo.src.sprite, tasks.sprite);
});
// Default gulp task
gulp.task('default', function() {
run(tasks.js, tasks.less, tasks.sprite, 'watch');
});
// Publish a version to CDN and demo
// --------------------------------------------
// Some options
var aws = loadJSON(path.join(root, 'aws.json')),
version = package.version,
maxAge = 31536000, // seconds 1 year
options = {
cdn: {
headers: {
'Cache-Control': 'max-age=' + maxAge,
Vary: 'Accept-Encoding',
},
},
demo: {
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
Vary: 'Accept-Encoding',
},
},
symlinks: function(version, filename) {
return {
headers: {
// http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect
'x-amz-website-redirect-location': '/' + version + '/' + filename,
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
},
};
},
};
// If aws is setup
if ('cdn' in aws) {
var regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?',
cdnpath = new RegExp(aws.cdn.domain + '/' + regex, 'gi'),
semver = new RegExp('v' + regex, 'gi'),
localPath = new RegExp('(../)?dist', 'gi'),
versionPath = 'https://' + aws.cdn.domain + '/' + version;
}
// Publish version to CDN bucket
gulp.task('cdn', function() {
console.log('Uploading ' + version + ' to ' + aws.cdn.domain + '...');
// Upload to CDN
return gulp
.src(paths.upload)
.pipe(
size({
showFiles: true,
gzip: true,
}),
)
.pipe(
rename(function(path) {
path.dirname = path.dirname.replace('.', version);
}),
)
.pipe(replace(localPath, versionPath))
.pipe(s3(aws.cdn, options.cdn));
});
// Publish to demo bucket
gulp.task('demo', function() {
console.log('Uploading ' + version + ' demo to ' + aws.demo.domain + '...');
// Replace versioned files in readme.md
gulp
.src([root + '/readme.md'])
.pipe(replace(cdnpath, aws.cdn.domain + '/' + version))
.pipe(gulp.dest(root));
// Replace versioned files in plyr.js
gulp
.src(path.join(root, 'src/js/plyr.js'))
.pipe(replace(semver, 'v' + version))
.pipe(replace(cdnpath, aws.cdn.domain + '/' + version))
.pipe(gulp.dest(path.join(root, 'src/js/')));
// Replace local file paths with remote paths in demo HTML
// e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js"
gulp
.src([paths.demo.root + '*.html'])
.pipe(replace(localPath, versionPath))
.pipe(s3(aws.demo, options.demo));
// Upload error.html to cdn (as well as demo site)
return gulp
.src([paths.demo.root + 'error.html'])
.pipe(replace(localPath, versionPath))
.pipe(s3(aws.cdn, options.demo));
});
// Open the demo site to check it's sweet
gulp.task('symlinks', function() {
console.log('Updating symlinks...');
return gulp.src(paths.upload).pipe(
through.obj(function(chunk, enc, callback) {
if (chunk.stat.isFile()) {
// Get the filename
var filename = chunk.path.split('/').reverse()[0];
// Create the 0 byte redirect files to upload
createFile(filename, '')
.pipe(
rename(function(path) {
path.dirname = path.dirname.replace('.', 'latest');
}),
)
// Upload to S3 with correct headers
.pipe(s3(aws.cdn, options.symlinks(version, filename)));
}
callback(null, chunk);
}),
);
});
// Open the demo site to check it's sweet
gulp.task('open', function() {
console.log('Opening ' + aws.demo.domain + '...');
// A file must be specified or gulp will skip the task
// Doesn't matter which file since we set the URL above
// Weird, I know...
return gulp.src([paths.demo.root + 'index.html']).pipe(
open('', {
url: 'http://' + aws.demo.domain,
}),
);
});
// Do everything
gulp.task('publish', function() {
run(tasks.js, tasks.less, tasks.sprite, 'cdn', 'demo', 'symlinks');
});