UNPKG

shr-buttons

Version:

Simple, customizable sharing buttons

392 lines (348 loc) 11.4 kB
// ========================================================================== // Gulp build script // ========================================================================== const path = require('path'); const gulp = require('gulp'); // ------------------------------------ // CSS // ------------------------------------ const less = require('gulp-less'); const sass = require('gulp-sass'); const clean = require('gulp-clean-css'); const prefix = require('gulp-autoprefixer'); // ------------------------------------ // JavaScript // ------------------------------------ const terser = require('gulp-terser'); const rollup = require('gulp-better-rollup'); const babel = require('rollup-plugin-babel'); const commonjs = require('rollup-plugin-commonjs'); const resolve = require('rollup-plugin-node-resolve'); const sourcemaps = require('gulp-sourcemaps'); // ------------------------------------ // Images // ------------------------------------ const svgstore = require('gulp-svgstore'); const imagemin = require('gulp-imagemin'); // ------------------------------------ // Utils // ------------------------------------ const plumber = require('gulp-plumber'); const rename = require('gulp-rename'); const replace = require('gulp-replace'); const size = require('gulp-size'); const ansi = require('ansi-colors'); const log = require('fancy-log'); const del = require('del'); const through = require('through2'); // ------------------------------------ // Deployment // ------------------------------------ const aws = require('aws-sdk'); const publish = require('gulp-awspublish'); const FastlyPurge = require('fastly-purge'); // ------------------------------------ // Configs // ------------------------------------ const pkg = require('./package.json'); const build = require('./build.json'); const deploy = require('./deploy.json'); // ------------------------------------ // Get info from package // ------------------------------------ const { browserslist, version } = pkg; // Get AWS config Object.values(deploy).forEach(target => { Object.assign(target, { publisher: publish.create({ region: target.region, params: { Bucket: target.bucket, }, credentials: new aws.SharedIniFileCredentials({ profile: 'shr' }), }), }); }); const root = __dirname; const paths = { shr: { // Source paths src: { sass: path.join(root, 'src/sass/**/*'), js: path.join(root, 'src/js/**/*'), sprite: path.join(root, 'src/sprite/*.svg'), }, }, 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/**/*'), }, // Docs root: path.join(root, 'demo/'), }, upload: [path.join(root, 'dist/**')], }; // Task arrays const tasks = { css: [], js: [], sprite: [], }; // Babel config const babelrc = { babelrc: false, presets: [ '@babel/env', [ 'minify', { builtIns: false, // Temporary fix for https://github.com/babel/minify/issues/904 }, ], ], }; // Size plugin const sizeOptions = { showFiles: true, gzip: true }; // Clean out /dist gulp.task('clean', done => { del(paths.upload.map(dir => path.join(dir, '*'))); done(); }); // JavaScript const namespace = 'Shr'; Object.entries(build.js).forEach(([filename, entry]) => { entry.formats.forEach(format => { const name = `js:${filename}:${format}`; tasks.js.push(name); gulp.task(name, () => gulp .src(entry.src) .pipe(plumber()) .pipe(sourcemaps.init()) .pipe( rollup( { plugins: [resolve(), commonjs(), babel(babelrc)], }, { name: namespace, format, }, ), ) .pipe(terser()) .pipe( rename({ extname: `.${format === 'es' ? 'mjs' : 'js'}`, }), ) .pipe(size(sizeOptions)) .pipe(sourcemaps.write('')) .pipe(gulp.dest(entry.dist)), ); }); }); // CSS Object.entries(build.css).forEach(([filename, entry]) => { const name = `css:${filename}`; tasks.css.push(name); gulp.task(name, () => gulp .src(entry.src) .pipe(plumber()) .pipe(path.extname(entry.src) === '.less' ? less() : sass()) .pipe( prefix(browserslist, { cascade: false, }), ) .pipe(clean()) .pipe(size(sizeOptions)) .pipe(gulp.dest(entry.dist)), ); }); // SVG Sprite Object.entries(build.sprite).forEach(([filename, entry]) => { const name = `sprite:${filename}`; tasks.sprite.push(name); gulp.task(name, () => gulp .src(entry.src) .pipe(plumber()) .pipe( imagemin([ imagemin.svgo({ plugins: [{ removeViewBox: false }], }), ]), ) .pipe(svgstore()) .pipe(rename({ basename: path.parse(filename).name })) .pipe(size(sizeOptions)) .pipe(gulp.dest(entry.dist)), ); }); // Watch for file changes gulp.task('watch', () => { // Core gulp.watch(paths.shr.src.js, gulp.parallel(...tasks.js)); gulp.watch(paths.shr.src.sass, gulp.parallel(...tasks.css)); gulp.watch(paths.shr.src.sprite, gulp.parallel(...tasks.sprite)); // Demo gulp.watch(paths.demo.src.js, gulp.parallel(...tasks.js)); gulp.watch(paths.demo.src.less, gulp.parallel(...tasks.css)); }); // Default gulp task gulp.task('default', gulp.series('clean', gulp.parallel(...tasks.js, ...tasks.css, ...tasks.sprite), 'watch')); // Publish a version to CDN and demo // -------------------------------------------- // Get deployment config let credentials = {}; try { credentials = require('./credentials.json'); //eslint-disable-line } catch (e) { // Do nothing } // Some options const maxAge = 31536000; // seconds 1 year const headers = { cdn: { 'Cache-Control': `max-age=${maxAge}`, }, demo: { 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', }, }; const regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?'; const semver = new RegExp(`v${regex}`, 'gi'); const cdnpath = new RegExp(`${deploy.cdn.domain}/${regex}`, 'gi'); const versionPath = `https://${deploy.cdn.domain}/${version}`; const localpath = new RegExp('(../)?dist', 'gi'); // Publish version to CDN bucket gulp.task('cdn', () => { const { domain, publisher } = deploy.cdn; if (!publisher) { throw new Error('No publisher instance. Check AWS configuration.'); } log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`); // Upload to CDN return gulp .src(paths.upload) .pipe( size({ showFiles: true, gzip: true, }), ) .pipe( rename(p => { // eslint-disable-next-line no-param-reassign p.dirname = p.dirname.replace('.', version); }), ) .pipe(publisher.publish(headers.cdn)) .pipe(publish.reporter()); }); // Replace versioned files in readme.md gulp.task('demo:readme', () => { const { domain } = deploy.cdn; return gulp .src([`${root}/readme.md`]) .pipe(replace(cdnpath, `${domain}/${version}`)) .pipe(gulp.dest(root)); }); // Replace versions in shr.js gulp.task('demo:src', () => gulp .src(path.join(root, 'src/js/shr.js')) .pipe(replace(semver, `v${version}`)) .pipe(gulp.dest(path.join(root, 'src/js/'))), ); // Replace versions in shr.js gulp.task('demo:svg', () => { const { domain, publisher } = deploy.cdn; if (!publisher) { throw new Error('No publisher instance. Check AWS configuration.'); } return gulp .src(path.join(root, 'dist/app.js')) .pipe(replace(localpath, `https://${domain}/${version}`)) .pipe( rename(p => { // eslint-disable-next-line no-param-reassign p.dirname = p.dirname.replace('.', version); }), ) .pipe(publisher.publish(headers.cdn)) .pipe(publish.reporter()); }); // Replace local file paths with remote paths in demo // e.g. "../dist/shr.js" to "https://cdn.shr.one/x.x.x/shr.js" gulp.task('demo:paths', () => { const { publisher } = deploy.demo; const { domain } = deploy.cdn; if (!publisher) { throw new Error('No publisher instance. Check AWS configuration.'); } return gulp .src([`*.html`, `src/js/app.js`].map(p => path.join(paths.demo.root, p))) .pipe(replace(localpath, `https://${domain}/${version}`)) .pipe(publisher.publish(headers.demo)) .pipe(publish.reporter()); }); // Upload error.html to cdn (as well as demo site) gulp.task('demo:error', () => { const { publisher } = deploy.demo; const { domain } = deploy.cdn; if (!publisher) { throw new Error('No publisher instance. Check AWS configuration.'); } return gulp .src([`${paths.demo.root}error.html`]) .pipe(replace(localpath, `https://${domain}/${version}`)) .pipe(publisher.publish(headers.demo)) .pipe(publish.reporter()); }); // Purge the fastly cache incase any 403/404 are cached gulp.task('purge', () => { if (!Object.keys(credentials).includes('fastly')) { throw new Error('Fastly credentials required to purge cache.'); } const { fastly } = credentials; const list = []; return gulp .src(paths.upload) .pipe( through.obj((file, enc, cb) => { if (file.stat.isFile()) { const filename = file.path.split('/').pop(); list.push(`${versionPath}/${filename}`); } cb(null); }), ) .on('end', () => { const purge = new FastlyPurge(fastly.token); list.forEach(url => { log(`Purging ${ansi.cyan(url)}...`); purge.url(url, (error, result) => { if (error) { log.error(error); } else if (result) { log(result); } }); }); }); }); // Publish to Demo bucket gulp.task('demo', gulp.parallel('demo:readme', 'demo:src', 'demo:svg', 'demo:paths', 'demo:error')); // Do everything gulp.task( 'deploy', gulp.series('clean', gulp.parallel(...tasks.js, ...tasks.css, ...tasks.sprite), 'cdn', 'demo', 'purge'), );