plyr/gulpfile.js
2017-10-02 14:18:44 +11:00

338 lines
10 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())
.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");
});