/** * build-examples.js * -------- * Searches for each example's `js/app.es6` file. * Creates a new watchify instance for each `app.es6`. * Changes to Uppy's source will trigger rebundling. * * Run as: * * build-examples.js # to build all examples one-off * build-examples.js watch # to keep rebuilding examples with an internal watchify * build-examples.js # to build just one example app.es6 * build-examples.js # to build just one example app.es6 to a specific location * * Note: * Since each example is dependent on Uppy's source, * changing one source file causes the 'file changed' * notification to fire multiple times. To stop this, * files are added to a 'muted' array that is checked * before announcing a changed file. It's removed from * the array when it has been bundled. */ var createStream = require('fs').createWriteStream var glob = require('multi-glob').glob var chalk = require('chalk') var path = require('path') var mkdirp = require('mkdirp') var notifier = require('node-notifier') var babelify = require('babelify') var aliasify = require('aliasify') var browserify = require('browserify') var watchify = require('watchify') var webRoot = __dirname // var uppyRoot = path.dirname(webRoot) var srcPattern = webRoot + '/src/examples/**/app.es6' var dstPattern = webRoot + '/public/examples/**/app.js' var watchifyEnabled = process.argv[2] === 'watch' var browserifyPlugins = [] if (watchifyEnabled) { browserifyPlugins.push(watchify) } // Instead of 'watch', build-examples.js can also take a path as cli argument. // In this case we'll only bundle the specified path/pattern if (!watchifyEnabled && process.argv[2]) { srcPattern = process.argv[2] if (process.argv[3]) { dstPattern = process.argv[3] } } // Find each app.es6 file with glob. glob(srcPattern, function (err, files) { if (err) throw new Error(err) if (watchifyEnabled) { console.log('--> Watching examples..') } var muted = [] // Create a new watchify instance for each file. files.forEach(function (file) { var browseFy = browserify(file, { cache: {}, packageCache: {}, debug: true, plugin: browserifyPlugins }) // Aliasing for using `require('uppy')`, etc. browseFy .transform(babelify) .transform(aliasify, { replacements: { '^uppy/lib/(.*?)$': path.join(__dirname, '../src/$1') } }) // Listeners for changes, errors, and completion. browseFy .on('update', bundle) .on('error', onError) .on('file', function (file, id, parent) { // When file completes, unmute it. muted = muted.filter(function (mutedId) { return id !== mutedId }) }) // Call bundle() manually to start watch processes. bundle() /** * Creates bundle and writes it to static and public folders. * Changes to * @param {[type]} ids [description] * @return {[type]} [description] */ function bundle (ids) { ids = ids || [] ids.forEach(function (id) { if (!isMuted(id, muted)) { console.info(chalk.cyan('change:'), id) muted.push(id) } }) var exampleName = path.basename(path.dirname(file)) var output = dstPattern.replace('**', exampleName) var parentDir = path.dirname(output) mkdirp.sync(parentDir) console.info(chalk.green('✓ building:'), chalk.green(path.relative(process.cwd(), file))) browseFy .bundle() .on('error', onError) .pipe(createStream(output)) } }) }) /** * Logs to console and shows desktop notification on error. * Calls `this.emit(end)` to stop bundling. * @param {object} err Error object */ function onError (err) { console.error(chalk.red('✗ error:'), chalk.red(err.message)) notifier.notify({ 'title': 'Build failed:', 'message': err.message }) this.emit('end') // When running without watch, process.exit(1) on error if (!watchifyEnabled) { process.exit(1) } } /** * Checks if a file has been added to muted list. * This stops single changes from logging multiple times. * @param {string} id Name of changed file * @param {Array} list Muted files array * @return {Boolean} True if file is muted */ function isMuted (id, list) { return list.reduce(function (prev, curr) { return prev || (curr === id) }, false) }