// ========================================================================== // Gulp build script // ========================================================================== /* global require, __dirname */ /* eslint no-console: "off" */ var fs = require('fs'); var path = require('path'); var gulp = require('gulp'); var gutil = require('gulp-util'); var concat = require('gulp-concat'); var uglify = require('gulp-uglify'); var less = require('gulp-less'); var sass = require('gulp-sass'); var cleanCSS = require('gulp-clean-css'); var run = require('run-sequence'); var prefix = require('gulp-autoprefixer'); var svgstore = require('gulp-svgstore'); var svgmin = require('gulp-svgmin'); var rename = require('gulp-rename'); var s3 = require('gulp-s3'); var replace = require('gulp-replace'); var open = require('gulp-open'); var size = require('gulp-size'); var root = __dirname; var 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 var tasks = { less: [], scss: [], js: [], sprite: [], }; // Fetch bundles from JSON var bundles = loadJSON(path.join(root, 'bundles.json')); var package = loadJSON(path.join(root, 'package.json')); // Load json function loadJSON(path) { try { return JSON.parse(fs.readFileSync(path)); } catch (err) { return {}; } } var build = { js: function(files, bundle) { Object.keys(files).forEach(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)); }); }); }, less: function(files, bundle) { Object.keys(files).forEach(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: false })) .pipe(cleanCSS()) .pipe(gulp.dest(paths[bundle].output)); }); }); }, scss: function(files, bundle) { Object.keys(files).forEach(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: false })) .pipe(cleanCSS()) .pipe(gulp.dest(paths[bundle].output)); }); }); }, 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')); var version = package.version; var maxAge = 31536000; // 1 year var 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\\-]+)*)?'; var cdnpath = new RegExp(aws.cdn.domain + '/' + regex, 'gi'); var semver = new RegExp('v' + regex, 'gi'); var localPath = new RegExp('(../)?dist', 'gi'); var 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'); });