<commit_before>var gulp = require('gulp');
var filter = require('gulp-filter');
var less = require('gulp-less');
var uglify = require('gulp-uglify');
var minify_css = require('gulp-minify-css');
var rename = require('gulp-rename');
var jshint = require('gulp-jshint');
var jshint_stylish = require('jshint-stylish');
var bower = require('gulp-bower');
var browserify = require('gulp-browserify');
var ng_template_cache = require('gulp-angular-templatecache');
var nodemon = require('gulp-nodemon');
var es = require('event-stream');
var gconcat = require('gulp-concat');

var paths = {
	css: './src/css/**/*',
	views_ng: './src/views_ng/**/*',
	scripts: ['./src/server/**/*', './src/client/**/*'],
	server_main: './src/server/server.js',
	client_main: './src/client/main.js',
	client_externals: [
		'./bower_components/alertify.js/lib/alertify.min.js',
	]
};

gulp.task('bower', function() {
	return bower();
});

gulp.task('css', function() {
	return gulp.src(paths.css)
		.pipe(less())
		.pipe(rename('styles.css'))
		.pipe(gulp.dest('build/public/css'))
		.pipe(minify_css())
		.pipe(rename('styles.min.css'))
		.pipe(gulp.dest('build/public/css'));
});

gulp.task('jshint', function() {
	return gulp.src(paths.scripts)
		.pipe(jshint())
		.pipe(jshint.reporter(jshint_stylish))
		.pipe(jshint.reporter('fail'));
});

gulp.task('ng', function() {
	return gulp.src(paths.views_ng)
		.pipe(ng_template_cache())
		.pipe(gulp.dest('build/'));
});

gulp.task('js', ['bower', 'jshint'], function() {
	// single entry point to browserify
	return es.merge(
		gulp.src(paths.client_main)
		.pipe(browserify({
			insertGlobals: true,
			debug: true
		})),
		gulp.src(paths.client_externals)
	).pipe(gconcat('bundle.js'))
		.pipe(gulp.dest('build/public/js'))
		.pipe(uglify())
		.pipe(rename('bundle.min.js'))
		.pipe(gulp.dest('build/public/js'));
});

gulp.task('install', ['css', 'js']);

var nodemon_instance;

gulp.task('serve', ['install'], function() {
	if (!nodemon_instance) {
		nodemon_instance = nodemon({
			script: paths.server_main,
			watch: 'src/__manual_watch__/',
			ext: '__manual_watch__',
			verbose: true,
		}).on('restart', function() {
			console.log('~~~ restart server ~~~');
		});
	} else {
		nodemon_instance.emit('restart');
	}
});

gulp.task('start_dev', ['serve'], function() {
	return gulp.watch('src/**/*', ['serve']);
});

gulp.task('start_prod', function() {
	console.log('~~~ START PROD ~~~');
	require(paths.server_main);
});

if (process.env.DEV_MODE === 'dev') {
	gulp.task('start', ['start_dev']);
} else {
	gulp.task('start', ['start_prod']);
}

gulp.task('default', ['start']);
<commit_msg>add gulpfile to jshint scripts<commit_after>var gulp = require('gulp');
var filter = require('gulp-filter');
var less = require('gulp-less');
var uglify = require('gulp-uglify');
var minify_css = require('gulp-minify-css');
var rename = require('gulp-rename');
var jshint = require('gulp-jshint');
var jshint_stylish = require('jshint-stylish');
var bower = require('gulp-bower');
var browserify = require('gulp-browserify');
var ng_template_cache = require('gulp-angular-templatecache');
var nodemon = require('gulp-nodemon');
var es = require('event-stream');
var gconcat = require('gulp-concat');

var paths = {
	css: './src/css/**/*',
	views_ng: './src/views_ng/**/*',
	scripts: ['./src/server/**/*', './src/client/**/*', './gulpfile.js'],
	server_main: './src/server/server.js',
	client_main: './src/client/main.js',
	client_externals: [
		'./bower_components/alertify.js/lib/alertify.min.js',
	]
};

gulp.task('bower', function() {
	return bower();
});

gulp.task('css', function() {
	return gulp.src(paths.css)
		.pipe(less())
		.pipe(rename('styles.css'))
		.pipe(gulp.dest('build/public/css'))
		.pipe(minify_css())
		.pipe(rename('styles.min.css'))
		.pipe(gulp.dest('build/public/css'));
});

gulp.task('jshint', function() {
	return gulp.src(paths.scripts)
		.pipe(jshint())
		.pipe(jshint.reporter(jshint_stylish))
		.pipe(jshint.reporter('fail'));
});

gulp.task('ng', function() {
	return gulp.src(paths.views_ng)
		.pipe(ng_template_cache())
		.pipe(gulp.dest('build/'));
});

gulp.task('js', ['bower', 'jshint'], function() {
	// single entry point to browserify
	return es.merge(
		gulp.src(paths.client_main)
		.pipe(browserify({
			insertGlobals: true,
			debug: true
		})),
		gulp.src(paths.client_externals)
	).pipe(gconcat('bundle.js'))
		.pipe(gulp.dest('build/public/js'))
		.pipe(uglify())
		.pipe(rename('bundle.min.js'))
		.pipe(gulp.dest('build/public/js'));
});

gulp.task('install', ['css', 'js']);

var nodemon_instance;

gulp.task('serve', ['install'], function() {
	if (!nodemon_instance) {
		nodemon_instance = nodemon({
			script: paths.server_main,
			watch: 'src/__manual_watch__/',
			ext: '__manual_watch__',
			verbose: true,
		}).on('restart', function() {
			console.log('~~~ restart server ~~~');
		});
	} else {
		nodemon_instance.emit('restart');
	}
});

gulp.task('start_dev', ['serve'], function() {
	return gulp.watch('src/**/*', ['serve']);
});

gulp.task('start_prod', function() {
	console.log('~~~ START PROD ~~~');
	require(paths.server_main);
});

if (process.env.DEV_MODE === 'dev') {
	gulp.task('start', ['start_dev']);
} else {
	gulp.task('start', ['start_prod']);
}

gulp.task('default', ['start']);
<|endoftext|>


<commit_before>'use strict';

var browserSync = require('browser-sync');
var browserReload = browserSync.reload;
var cssnano = require('cssnano');
var cssnext = require('postcss-cssnext');
var cssimport = require('postcss-import')
var del = require('del');
var gulp = require('gulp');
var header = require('gulp-header');
var jshint = require('gulp-jshint');
var pkg = require('./package.json');
var postcss = require('gulp-postcss');
var rename = require('gulp-rename');
var runSequence = require('run-sequence');
var stylish = require('jshint-stylish');
var uglify = require('gulp-uglify');
var banner = [
'/*!',
' * <%= pkg.name %> v<%= pkg.version %>',
' * <%= pkg.description %>',
' * <%= pkg.homepage %>',
' * License : <%= pkg.license %>',
' * Author : <%= pkg.author %>',
' */',
'',
''].join('\n');

var dirs = {
  src:'./src',
  dist:'./dist',
  sandbox:'./sandbox',
};

gulp.task('css', function () {
  var processors = [
    cssimport,
    cssnext,
  ];
  return gulp
    .src(dirs.src + '/css/drawer.css')
    .pipe(postcss(processors))
    .pipe(header(banner, { pkg: pkg }))
    .pipe(gulp.dest(dirs.dist + '/css'))
    .pipe(postcss([
      cssnano({ discardComments: { removeAll: true } })
    ]))
    .pipe(header(banner, { pkg: pkg }))
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest(dirs.dist + '/css'));
});

gulp.task('js', function(){
  return gulp
    .src(dirs.src + '/js/drawer.js')
    .pipe(jshint())
    .pipe(jshint.reporter(stylish))
    .pipe(header(banner, { pkg:pkg }))
    .pipe(gulp.dest(dirs.dist + '/js'))
    .pipe(uglify())
    .pipe(rename({ suffix: '.min' }))
    .pipe(header(banner, { pkg:pkg }))
    .pipe(gulp.dest(dirs.dist + '/js'));
});

gulp.task('cleanup', function(cb){
  return del([ dirs.dist ], cb);
});

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: '.',
      directory: true
    }
  });
  gulp.watch([ dirs.src + '/css/**/*.css'], ['css']);
  gulp.watch([ dirs.src + '/js/*.js'], ['js']);
  gulp.watch([
    dirs.dist + '/**/*.min.{css,js}',
    dirs.sandbox + '/*.{css,html}'
  ]).on('change', browserReload);
});

gulp.task('default', ['build'], function(cb) {
  runSequence('serve', cb);
});

gulp.task('build', ['cleanup'], function(cb){
  runSequence('js', 'css', cb);
});
<commit_msg>add cssnext options<commit_after>'use strict';

var browserSync = require('browser-sync');
var browserReload = browserSync.reload;
var cssnano = require('cssnano');
var cssnext = require('postcss-cssnext');
var cssimport = require('postcss-import')
var del = require('del');
var gulp = require('gulp');
var header = require('gulp-header');
var jshint = require('gulp-jshint');
var pkg = require('./package.json');
var postcss = require('gulp-postcss');
var rename = require('gulp-rename');
var runSequence = require('run-sequence');
var stylish = require('jshint-stylish');
var uglify = require('gulp-uglify');
var banner = [
'/*!',
' * <%= pkg.name %> v<%= pkg.version %>',
' * <%= pkg.description %>',
' * <%= pkg.homepage %>',
' * License : <%= pkg.license %>',
' * Author : <%= pkg.author %>',
' */',
'',
''].join('\n');

var dirs = {
  src:'./src',
  dist:'./dist',
  sandbox:'./sandbox',
};

gulp.task('css', function () {
  var processors = [
    cssimport,
    cssnext({
      features: {
        colorRgba: false,
        rem: false
      }
    })
  ];
  return gulp
    .src(dirs.src + '/css/drawer.css')
    .pipe(postcss(processors))
    .pipe(header(banner, { pkg: pkg }))
    .pipe(gulp.dest(dirs.dist + '/css'))
    .pipe(postcss([
      cssnano({ discardComments: { removeAll: true } })
    ]))
    .pipe(header(banner, { pkg: pkg }))
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest(dirs.dist + '/css'));
});

gulp.task('js', function(){
  return gulp
    .src(dirs.src + '/js/drawer.js')
    .pipe(jshint())
    .pipe(jshint.reporter(stylish))
    .pipe(header(banner, { pkg:pkg }))
    .pipe(gulp.dest(dirs.dist + '/js'))
    .pipe(uglify())
    .pipe(rename({ suffix: '.min' }))
    .pipe(header(banner, { pkg:pkg }))
    .pipe(gulp.dest(dirs.dist + '/js'));
});

gulp.task('cleanup', function(cb){
  return del([ dirs.dist ], cb);
});

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: '.',
      directory: true
    }
  });
  gulp.watch([ dirs.src + '/css/**/*.css'], ['css']);
  gulp.watch([ dirs.src + '/js/*.js'], ['js']);
  gulp.watch([
    dirs.dist + '/**/*.min.{css,js}',
    dirs.sandbox + '/*.{css,html}'
  ]).on('change', browserReload);
});

gulp.task('default', ['build'], function(cb) {
  runSequence('serve', cb);
});

gulp.task('build', ['cleanup'], function(cb){
  runSequence('js', 'css', cb);
});
<|endoftext|>


<commit_before>'use strict'

const { src, dest, watch, series, parallel } = require('gulp')

const uglify = require('gulp-uglify')
const rename = require('gulp-rename')
const rtlcss = require('gulp-rtlcss')
const sass = require('gulp-sass')
const sourcemaps = require('gulp-sourcemaps')
const typescript = require('gulp-typescript')
const postcss = require('gulp-postcss')
const cssnano = require('cssnano')
const mqpacker = require('css-mqpacker')
const mqsort = require('sort-css-media-queries')
const focus = require('postcss-focus')
const newer = require('gulp-newer')
const rimraf = require('rimraf')
const chmodr = require('chmodr')

const tsConfig = require('./tsconfig.json')

const paths = {
    styles: {
        src: ['./assets/styles/**/*.scss'],
        dest: './dist/styles'
    },
    scripts: {
        src: tsConfig.include,
        dest: tsConfig.compilerOptions.outDir
    },
    vendor: {
        dest: {
            dist: './dist/vendor',
            assets: './assets/vendor'
        }
    }
}

function _scripts(done)
{
    src(paths.scripts.src)
        .pipe(newer(paths.scripts.dest))
        .pipe(sourcemaps.init())
        .pipe(typescript(tsConfig.compilerOptions))
        .pipe(uglify())
        .pipe(rename({'suffix': '.min'}))
        .pipe(sourcemaps.write())
        .pipe(dest(paths.scripts.dest))

    done()
}

function _styles(done)
{
    src(paths.styles.src)
        .pipe(newer(paths.styles.dest))
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss([focus(), mqpacker({sort: mqsort}), cssnano()]))
        .pipe(rename({'suffix': '.min'}))
        .pipe(sourcemaps.write())
        .pipe(dest(paths.styles.dest))
        .pipe(rtlcss())
        .pipe(rename(path =>
            path.basename = path.basename.replace('.min', '-rtl.min')
        ))
        .pipe(dest(paths.styles.dest))

    done()
}

function _vendor(done)
{
    src([
        './node_modules/html5shiv/dist/html5shiv.min.js',
        './node_modules/respond.js/dest/respond.min.js',
        './node_modules/what-input/dist/what-input.min.js',
        './node_modules/jquery/dist/jquery.min.js',
        './node_modules/jquery-migrate/dist/jquery-migrate.min.js'
    ])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/normalize.css/normalize.css'])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(postcss([cssnano()]))
        .pipe(rename({'suffix': '.min'}))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/@fortawesome/fontawesome-free/js/all.min.js'])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(rename({'basename': 'font-awesome.min'}))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/@fortawesome/fontawesome-free/js/v4-shims.min.js'])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(rename({'basename': 'font-awesome-v4-shims.min'}))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/@grottopress/scss/**'])
        .pipe(newer(paths.vendor.dest.assets))
        .pipe(dest(`${paths.vendor.dest.assets}/@grottopress/scss`))

    done()
}

function _watch()
{
    watch(paths.scripts.src, {ignoreInitial: false}, _scripts)
    watch(paths.styles.src, {ignoreInitial: false}, _styles)
}

function _clean(done)
{
    rimraf('./dist', done)
}

function _chmod(done)
{
    const perm = 0o755

    chmodr('./bin', perm, done)
    chmodr('./vendor/bin', perm, done)
    chmodr('./node_modules/.bin', perm, done)
}

exports.styles = _styles
exports.scripts = _scripts
exports.vendor = _vendor
exports.watch = _watch
exports.clean = _clean
exports.chmod = _chmod

exports.default = series(parallel(_styles, _scripts), _watch)
<commit_msg>Remove file extension from glob pattern<commit_after>'use strict'

const { src, dest, watch, series, parallel } = require('gulp')

const uglify = require('gulp-uglify')
const rename = require('gulp-rename')
const rtlcss = require('gulp-rtlcss')
const sass = require('gulp-sass')
const sourcemaps = require('gulp-sourcemaps')
const typescript = require('gulp-typescript')
const postcss = require('gulp-postcss')
const cssnano = require('cssnano')
const mqpacker = require('css-mqpacker')
const mqsort = require('sort-css-media-queries')
const focus = require('postcss-focus')
const newer = require('gulp-newer')
const rimraf = require('rimraf')
const chmodr = require('chmodr')

const tsConfig = require('./tsconfig.json')

const paths = {
    styles: {
        src: ['./assets/styles/**/*'],
        dest: './dist/styles'
    },
    scripts: {
        src: tsConfig.include,
        dest: tsConfig.compilerOptions.outDir
    },
    vendor: {
        dest: {
            dist: './dist/vendor',
            assets: './assets/vendor'
        }
    }
}

function _scripts(done)
{
    src(paths.scripts.src)
        .pipe(newer(paths.scripts.dest))
        .pipe(sourcemaps.init())
        .pipe(typescript(tsConfig.compilerOptions))
        .pipe(uglify())
        .pipe(rename({'suffix': '.min'}))
        .pipe(sourcemaps.write())
        .pipe(dest(paths.scripts.dest))

    done()
}

function _styles(done)
{
    src(paths.styles.src)
        .pipe(newer(paths.styles.dest))
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss([focus(), mqpacker({sort: mqsort}), cssnano()]))
        .pipe(rename({'suffix': '.min'}))
        .pipe(sourcemaps.write())
        .pipe(dest(paths.styles.dest))
        .pipe(rtlcss())
        .pipe(rename(path =>
            path.basename = path.basename.replace('.min', '-rtl.min')
        ))
        .pipe(dest(paths.styles.dest))

    done()
}

function _vendor(done)
{
    src([
        './node_modules/html5shiv/dist/html5shiv.min.js',
        './node_modules/respond.js/dest/respond.min.js',
        './node_modules/what-input/dist/what-input.min.js',
        './node_modules/jquery/dist/jquery.min.js',
        './node_modules/jquery-migrate/dist/jquery-migrate.min.js'
    ])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/normalize.css/normalize.css'])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(postcss([cssnano()]))
        .pipe(rename({'suffix': '.min'}))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/@fortawesome/fontawesome-free/js/all.min.js'])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(rename({'basename': 'font-awesome.min'}))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/@fortawesome/fontawesome-free/js/v4-shims.min.js'])
        .pipe(newer(paths.vendor.dest.dist))
        .pipe(rename({'basename': 'font-awesome-v4-shims.min'}))
        .pipe(dest(paths.vendor.dest.dist))

    src(['./node_modules/@grottopress/scss/**'])
        .pipe(newer(paths.vendor.dest.assets))
        .pipe(dest(`${paths.vendor.dest.assets}/@grottopress/scss`))

    done()
}

function _watch()
{
    watch(paths.scripts.src, {ignoreInitial: false}, _scripts)
    watch(paths.styles.src, {ignoreInitial: false}, _styles)
}

function _clean(done)
{
    rimraf('./dist', done)
}

function _chmod(done)
{
    const perm = 0o755

    chmodr('./bin', perm, done)
    chmodr('./vendor/bin', perm, done)
    chmodr('./node_modules/.bin', perm, done)
}

exports.styles = _styles
exports.scripts = _scripts
exports.vendor = _vendor
exports.watch = _watch
exports.clean = _clean
exports.chmod = _chmod

exports.default = series(parallel(_styles, _scripts), _watch)
<|endoftext|>


<commit_before>var gulp = require('gulp');
var clean = require('gulp-clean');
var less = require('gulp-less');
var lessAutoprefix = require('less-plugin-autoprefix');
var gulpStylelint = require('gulp-stylelint');
var variablesOutput = require('less-plugin-variables-output');
var concat = require('gulp-concat');
var fileinclude = require('gulp-file-include');
var header = require('gulp-header');
var shell = require('gulp-shell');
var cleanCSS = require('gulp-clean-css');
var sourcemaps = require('gulp-sourcemaps');
var rename = require('gulp-rename');
const fs = require('fs');
const path = require('path');

var autoprefix = new lessAutoprefix({ browsers: ['IE 11', 'last 2 Safari versions', 'iOS 9.0', 'last 2 Chrome versions', 'Firefox ESR'] });
var exportLessVariablesToJson = new variablesOutput({ filename: 'build/skin-tool/less-variables.json' });

// windows doesn't add the lib subfolder to global prefixes
const lib = process.platform === 'win32' ? '' : 'lib/';

const browserSyncPath = `./scratch/tools/${lib}node_modules/browser-sync`;
const backstopJsPath = `./scratch/tools/${lib}node_modules/backstopjs`;

const browserSync = (() => {
  let browserSyncInstance;
  return () => {
    // must be lazy loaded otherwise browser-sync is required to run _any_ gulp task
    browserSyncInstance = browserSyncInstance || require(browserSyncPath).create();
    return browserSyncInstance;
  }
})();

//
// Lint less files using stylelint
//
gulp.task('lint', function() {
  return gulp.src('./src/less/**/*.less')
    .pipe(gulpStylelint({
      failAfterError: false,
      reporters: [
        {formatter: 'string', console: true}
      ]
    }));
});

//
// Build CSS
//
gulp.task('less', function() {
  return gulp.src('./src/less/skins/**/*.less')
    .pipe(less({
      relativeUrls: true,
      plugins: [autoprefix, exportLessVariablesToJson]
    }))
    .pipe(gulp.dest('./build/skins/'))
});

//
// Compiling CSS for runtime demo (can this be combined with the above without depending on browsersync?)
//
gulp.task('less-serve', function() {
  return gulp.src('./src/less/skins/**/*.less')
    .pipe(less({
      relativeUrls: true,
      plugins: [autoprefix, exportLessVariablesToJson]
    }).on('error', function(err) {
      console.error(err.message);
      browserSync().notify(err.message, 5000); // Display error in the browser
      this.emit('end'); // Prevent gulp from catching the error and exiting the watch process
    }))
    .pipe(gulp.dest('./build/skins/'))
    .pipe(browserSync().stream());
});

//
// Minify CSS
//
gulp.task('minify-css', function() {
  return gulp.src(['./build/skins/**/*.css', '!**/*.min.css'])
    .pipe(sourcemaps.init())
    .pipe(cleanCSS({ rebase: false }))
    .pipe(header(fs.readFileSync('src/text/license-header.css', 'utf8')))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('./build/skins'));
});

//
// Build HTML
//
gulp.task('buildHtml', function() {
  // Build HTML
  return gulp.src(['./src/demo/**/*.html'])
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest('./build'));
});

//
// Copy Files
//
gulp.task('copyFilesA', function() {
  return gulp.src(['./src/demo/styles.css', './src/demo/scripts.js'])
    .pipe(gulp.dest('./build'));
});

gulp.task('copyFilesB', function() {
  return gulp.src(['./src/demo/skin-tool/*.less', './src/demo/skin-tool/*.css', './src/demo/skin-tool/*.js'])
    .pipe(gulp.dest('./build/skin-tool'));
});

gulp.task('copyFilesC', function() {
  return gulp.src(['./src/less/theme/**'])
    .pipe(gulp.dest('./build/skin-tool/theme/'));
});

gulp.task('copyFilesD', function() {
  return gulp.src(['./src/demo/editor-demos/*.js'])
    .pipe(gulp.dest('./build/editor-demos/'));
});

//
// Concat icon packs and copy iconManager
//
gulp.task('setupIconManager', function() {
  return gulp.src([ 'src/demo/iconManager.js', './node_modules/@tinymce/oxide-icons-*/dist/icons/*/icons.js', './scratch/icons/**/dist/icons/*/icons.js' ])
    .pipe(concat('iconManager.js'))
    .pipe(gulp.dest('./build'));
});

const getDirs = (p) => fs.readdirSync(p).filter(f => fs.statSync(path.join(p, f)).isDirectory());
gulp.task('buildSkinSwitcher', (done) => {
  const uiSkins = getDirs('./build/skins/ui');
  const contentSkins = getDirs('./build/skins/content');
  const data = `uiSkins = ${JSON.stringify(uiSkins)}, contentSkins = ${JSON.stringify(contentSkins)}`;
  const html = fs.readFileSync('./build/index.html', 'utf8');
  fs.writeFileSync('./build/index.html', html.replace('/** ADD_DATA */', data));

  done();
});

gulp.task('copyFiles', gulp.series('copyFilesA', 'copyFilesB', 'copyFilesC', 'copyFilesD', 'setupIconManager'));

//
// Browsersync
//
gulp.task('serve', function() {
  browserSync().init({
    server: './build',
    ghostMode: false, // prevent scrolls and clicks between browsers
    open: false // Don't open a browser by default.
  });

  gulp.watch('./src/**/*.less', gulp.series('lint', 'copyFilesC', 'less-serve', 'minify-css'));
  gulp.watch('./src/demo/**/*.html', gulp.series('buildHtml', 'copyFiles', 'buildSkinSwitcher'));
  gulp.watch(['./src/demo/**/*.css', './src/demo/**/*.js'], gulp.series('buildHtml', 'copyFiles'));
  gulp.watch('./build/**/*.*').on('change', browserSync().reload);
});

//
// clean builds
//
gulp.task('cleanBuild', function () {
  return gulp.src('./build', {
    read: false,
    allowEmpty: true,
  })
  .pipe(clean());
});

const testDeps = ['backstopjs'];
const demoDeps = ['browser-sync'];
const iconPacks = [
  '@tinymce/oxide-icons-material',
  '@tinymce/oxide-icons-jam'
];

const installTools = (modules, prefix = '--prefix ./scratch/tools') => shell.task(`npm install -g --no-package-lock --no-save ${prefix} ${modules.join(' ')}`);

// cheating a bit, adding the registry to the prefix param
gulp.task('getInternal', installTools(iconPacks, '--prefix ./scratch/icons --registry http://nexus:8081/repository/npm-group/'));

gulp.task('getDemoDeps', installTools(demoDeps));

gulp.task('getTestDeps', installTools(testDeps.concat(demoDeps)));

//
// clean tmp
//
gulp.task('cleanTmp', function () {
  return gulp.src('./tmp', {
    read: false,
    allowEmpty: true,
  })
  .pipe(clean());
});

const runBackstopCommand = (command) => {
  const runner = require('./tools/tasks/run_backstop');
  return (done) => {
    // must be lazy loaded otherwise backstop is required to run _any_ gulp task
    const backstop = require(backstopJsPath);
    runner(backstop, browserSync(), done, command)
  }
}

gulp.task('backstop:test', gulp.series('getTestDeps', runBackstopCommand('test')));

gulp.task('backstop:approve', gulp.series('getTestDeps', runBackstopCommand('approve')));

gulp.task('backstop:reference', gulp.series('getTestDeps', runBackstopCommand('reference')));

//
// clean all the things
//
gulp.task('clean', gulp.series('cleanBuild', 'cleanTmp'));

//
// Build project and watch LESS file changes
//
gulp.task('build', gulp.series('clean', 'buildHtml', 'lint', 'less', 'minify-css', 'copyFiles', 'setupIconManager', 'buildSkinSwitcher'));
gulp.task('default', gulp.series('build', 'getDemoDeps', 'serve'));
<commit_msg>Update reference images and enforce build before backstop test<commit_after>var gulp = require('gulp');
var clean = require('gulp-clean');
var less = require('gulp-less');
var lessAutoprefix = require('less-plugin-autoprefix');
var gulpStylelint = require('gulp-stylelint');
var variablesOutput = require('less-plugin-variables-output');
var concat = require('gulp-concat');
var fileinclude = require('gulp-file-include');
var header = require('gulp-header');
var shell = require('gulp-shell');
var cleanCSS = require('gulp-clean-css');
var sourcemaps = require('gulp-sourcemaps');
var rename = require('gulp-rename');
const fs = require('fs');
const path = require('path');

var autoprefix = new lessAutoprefix({ browsers: ['IE 11', 'last 2 Safari versions', 'iOS 9.0', 'last 2 Chrome versions', 'Firefox ESR'] });
var exportLessVariablesToJson = new variablesOutput({ filename: 'build/skin-tool/less-variables.json' });

// windows doesn't add the lib subfolder to global prefixes
const lib = process.platform === 'win32' ? '' : 'lib/';

const browserSyncPath = `./scratch/tools/${lib}node_modules/browser-sync`;
const backstopJsPath = `./scratch/tools/${lib}node_modules/backstopjs`;

const browserSync = (() => {
  let browserSyncInstance;
  return () => {
    // must be lazy loaded otherwise browser-sync is required to run _any_ gulp task
    browserSyncInstance = browserSyncInstance || require(browserSyncPath).create();
    return browserSyncInstance;
  }
})();

//
// Lint less files using stylelint
//
gulp.task('lint', function() {
  return gulp.src('./src/less/**/*.less')
    .pipe(gulpStylelint({
      failAfterError: false,
      reporters: [
        {formatter: 'string', console: true}
      ]
    }));
});

//
// Build CSS
//
gulp.task('less', function() {
  return gulp.src('./src/less/skins/**/*.less')
    .pipe(less({
      relativeUrls: true,
      plugins: [autoprefix, exportLessVariablesToJson]
    }))
    .pipe(gulp.dest('./build/skins/'))
});

//
// Compiling CSS for runtime demo (can this be combined with the above without depending on browsersync?)
//
gulp.task('less-serve', function() {
  return gulp.src('./src/less/skins/**/*.less')
    .pipe(less({
      relativeUrls: true,
      plugins: [autoprefix, exportLessVariablesToJson]
    }).on('error', function(err) {
      console.error(err.message);
      browserSync().notify(err.message, 5000); // Display error in the browser
      this.emit('end'); // Prevent gulp from catching the error and exiting the watch process
    }))
    .pipe(gulp.dest('./build/skins/'))
    .pipe(browserSync().stream());
});

//
// Minify CSS
//
gulp.task('minify-css', function() {
  return gulp.src(['./build/skins/**/*.css', '!**/*.min.css'])
    .pipe(sourcemaps.init())
    .pipe(cleanCSS({ rebase: false }))
    .pipe(header(fs.readFileSync('src/text/license-header.css', 'utf8')))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('./build/skins'));
});

//
// Build HTML
//
gulp.task('buildHtml', function() {
  // Build HTML
  return gulp.src(['./src/demo/**/*.html'])
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest('./build'));
});

//
// Copy Files
//
gulp.task('copyFilesA', function() {
  return gulp.src(['./src/demo/styles.css', './src/demo/scripts.js'])
    .pipe(gulp.dest('./build'));
});

gulp.task('copyFilesB', function() {
  return gulp.src(['./src/demo/skin-tool/*.less', './src/demo/skin-tool/*.css', './src/demo/skin-tool/*.js'])
    .pipe(gulp.dest('./build/skin-tool'));
});

gulp.task('copyFilesC', function() {
  return gulp.src(['./src/less/theme/**'])
    .pipe(gulp.dest('./build/skin-tool/theme/'));
});

gulp.task('copyFilesD', function() {
  return gulp.src(['./src/demo/editor-demos/*.js'])
    .pipe(gulp.dest('./build/editor-demos/'));
});

//
// Concat icon packs and copy iconManager
//
gulp.task('setupIconManager', function() {
  return gulp.src([ 'src/demo/iconManager.js', './node_modules/@tinymce/oxide-icons-*/dist/icons/*/icons.js', './scratch/icons/**/dist/icons/*/icons.js' ])
    .pipe(concat('iconManager.js'))
    .pipe(gulp.dest('./build'));
});

const getDirs = (p) => fs.readdirSync(p).filter(f => fs.statSync(path.join(p, f)).isDirectory());
gulp.task('buildSkinSwitcher', (done) => {
  const uiSkins = getDirs('./build/skins/ui');
  const contentSkins = getDirs('./build/skins/content');
  const data = `uiSkins = ${JSON.stringify(uiSkins)}, contentSkins = ${JSON.stringify(contentSkins)}`;
  const html = fs.readFileSync('./build/index.html', 'utf8');
  fs.writeFileSync('./build/index.html', html.replace('/** ADD_DATA */', data));

  done();
});

gulp.task('copyFiles', gulp.series('copyFilesA', 'copyFilesB', 'copyFilesC', 'copyFilesD', 'setupIconManager'));

//
// Browsersync
//
gulp.task('serve', function() {
  browserSync().init({
    server: './build',
    ghostMode: false, // prevent scrolls and clicks between browsers
    open: false // Don't open a browser by default.
  });

  gulp.watch('./src/**/*.less', gulp.series('lint', 'copyFilesC', 'less-serve', 'minify-css'));
  gulp.watch('./src/demo/**/*.html', gulp.series('buildHtml', 'copyFiles', 'buildSkinSwitcher'));
  gulp.watch(['./src/demo/**/*.css', './src/demo/**/*.js'], gulp.series('buildHtml', 'copyFiles'));
  gulp.watch('./build/**/*.*').on('change', browserSync().reload);
});

//
// clean builds
//
gulp.task('cleanBuild', function () {
  return gulp.src('./build', {
    read: false,
    allowEmpty: true,
  })
  .pipe(clean());
});

const testDeps = ['backstopjs'];
const demoDeps = ['browser-sync'];
const iconPacks = [
  '@tinymce/oxide-icons-material',
  '@tinymce/oxide-icons-jam'
];

const installTools = (modules, prefix = '--prefix ./scratch/tools') => shell.task(`npm install -g --no-package-lock --no-save ${prefix} ${modules.join(' ')}`);

// cheating a bit, adding the registry to the prefix param
gulp.task('getInternal', installTools(iconPacks, '--prefix ./scratch/icons --registry http://nexus:8081/repository/npm-group/'));

gulp.task('getDemoDeps', installTools(demoDeps));

gulp.task('getTestDeps', installTools(testDeps.concat(demoDeps)));

//
// clean tmp
//
gulp.task('cleanTmp', function () {
  return gulp.src('./tmp', {
    read: false,
    allowEmpty: true,
  })
  .pipe(clean());
});

//
// clean all the things
//
gulp.task('clean', gulp.series('cleanBuild', 'cleanTmp'));

//
// Build project and watch LESS file changes
//
gulp.task('build', gulp.series('clean', 'buildHtml', 'lint', 'less', 'minify-css', 'copyFiles', 'setupIconManager', 'buildSkinSwitcher'));
gulp.task('default', gulp.series('build', 'getDemoDeps', 'serve'));

const runBackstopCommand = (command) => {
  const runner = require('./tools/tasks/run_backstop');
  return (done) => {
    // must be lazy loaded otherwise backstop is required to run _any_ gulp task
    const backstop = require(backstopJsPath);
    runner(backstop, browserSync(), done, command)
  }
}

gulp.task('backstop:test', gulp.series('build', 'getTestDeps', runBackstopCommand('test')));

gulp.task('backstop:approve', gulp.series('getTestDeps', runBackstopCommand('approve')));

gulp.task('backstop:reference', gulp.series('getTestDeps', runBackstopCommand('reference')));
<|endoftext|>


<commit_before>var gulp = require('gulp');
var NwBuilder = require('nw-builder');
var plumber = require('gulp-plumber');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var concat = require('gulp-concat');
var notify = require('gulp-notify');
var zip = require('gulp-zip');
var browserify = require('gulp-browserify');
var partialify = require('partialify');
var release = require('github-release');
var download = require("gulp-download");
var Path = require('path');
var fs = require('fs');
var info = require('./package.json');
var request = require('request');

var isWin = process.platform.indexOf('win') > -1;

var builderOptions = {
  version: info.devDependencies.nw,
  buildType: 'versioned',
  files: [ './public/**'],
  buildDir: './dist',
  platforms: ['osx64', 'win64'],
  macIcns: './icons/p5js.icns',
  winIco: './icons/p5js.ico',
  macPlist: {
    'CFBundleDocumentTypes':[
      {
        'CFBundleTypeName': 'js',
        'CFBundleTypeIconFile': 'p5js.icons',
        'LSItemContentTypes': ['com.netscape.javascript-source']
      },
      {
        'CFBundleTypeName': 'html',
        'CFBundleTypeIconFile': 'p5js.icons',
        'LSItemContentTypes': ['public.html']
      },
      {
        'CFBundleTypeName': 'css',
        'CFBundleTypeIconFile': 'p5js.icons',
      },
      {
        'CFBundleTypeName': 'Folder',
        'CFBundleTypeOSTypes': [
          'fold'
        ]
      }
    ]
  }
};

var binaryDir = Path.join(builderOptions.buildDir, info.name + " - v" + info.version);
var latestDir = Path.join(Path.join(builderOptions.buildDir, 'latest'));

var jsPath = ['./app/*.js', './app/**/*.js', './app/**/*.html', './public/index.html'];
var cssPath = './app/**/*.scss';
var debugClientPath = './app/debug/client.js';

gulp.task('browserify', function() {
  gulp.src('./app/main.js', { read: false })
    .pipe(plumber())
    .pipe(browserify({
      transform: [partialify],
    }))
    .on("error", notify.onError({
      message: "<%= error.message %>",
      title: "Error"
    }))
    .pipe(rename('main.js'))
    .pipe(gulp.dest('./public/js/'));
});

gulp.task('injected-js', function(){
  return gulp.src(['./public/node_modules/socket.io/node_modules/socket.io-client/socket.io.js', debugClientPath])
    .pipe(concat('debug-console.js'))
    .pipe(gulp.dest('./public/js/'));
});

gulp.task('css', function() {
  gulp.src(cssPath)
    .pipe(plumber())
    .pipe(concat('main.css'))
    .pipe(sass({
      //outputStyle: 'compressed'
    }))
    .pipe(gulp.dest('./public/css/'));
});

gulp.task('watch', function() {
  gulp.watch(jsPath, ['browserify']);
  gulp.watch(cssPath, ['css']);
  gulp.watch(debugClientPath, ['injected-js']);
});

function build (cb) {
  var nw = new NwBuilder(builderOptions);

  nw.on('log', console.log);

  nw.build().then(function () {

    copyFfmpegBuild();

    cb();
  }).catch(function (error) {
    console.error(error);
  });

}

// copies the ffmpegsumo.so with mp3/mp4 decoders to nwjs directory for BUILD (currently only MacOS)
// puts the correct library in the dist folder.
function copyFfmpegBuild() {
  console.log('copying ffmpegsumo.so to ./dist');
  gulp.src('./lib/ffmpegsumo.so')
    .pipe(gulp.dest(binaryDir + '/osx64/p5.app/Contents/Frameworks/nwjs Framework.framework/Libraries',
       {overwrite: true}));

  console.log('copying ffmpegsumo.dll to ./dist');
  gulp.src('./lib/ffmpegsumo.so')
    .pipe(gulp.dest(binaryDir + '/win64',
       {overwrite: true}));
}

// copies the ffmpegsumo.so with mp3/mp4 decoders to nwjs directory for development, assuming npm is already run
gulp.task('copy-ffmpeg-default', function() {
  console.log('copying ffmpegsumo to ./node_modules');
  if (isWin) {
    gulp.src('./lib/ffmpegsumo.dll')
      .pipe(gulp.dest('./node_modules/nw/nwjs/',
         {overwrite: true}));
  } else {
    gulp.src('./lib/ffmpegsumo.so')
      .pipe(gulp.dest('./node_modules/nw/nwjs/nwjs.app/Contents/Frameworks/nwjs Framework.framework/Libraries/',
         {overwrite: true}));
    }
});

function latest () {
  console.log('Compressing...');

  builderOptions.platforms.forEach(function(p){
    var output = 'p5-' + (p.indexOf('win') > -1 ? 'win' : 'mac') + '.zip';
    gulp.src(binaryDir + '/' + p +'/**').
      pipe(zip(output)).
      pipe(gulp.dest(latestDir)).
      on('end', function(){
        console.log('Build compressed');
      });

  });
}

gulp.task('p5', function () {
  // which files to download
  var fileNames = ['p5.js', 'p5.dom.js', 'p5.sound.js'];

  // get latest repo data from github api
  request({
    url: 'https://api.github.com/repos/processing/p5.js/releases/latest',
    headers: {
      'User-Agent' : 'request'
    }
  }, function(error, response, body) {
    var assets = JSON.parse(body).assets;
    assets.forEach(function(asset) {
      if (fileNames.indexOf(asset.name) > -1) {
        var url = asset.browser_download_url;
        download(url)
          .pipe(gulp.dest("./public/mode_assets/p5/empty_project/libraries/"));
      }
    })
  });

});

gulp.task('release', function(){
  build(function(){
    latest().pipe(release(info));
  });
});

function saveDataForCategory(requestParams) {
  var headers = {'User-Agent': 'p5.js-editor/0.0.1'};
  requestParams.forEach(function(params)  {
    // extract download URL for examples in this category
    var options = {
      url: params.url,
      method: 'GET',
      headers: headers
    };
    var fileMetadata = [];
    request(options, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var json = JSON.parse(body);
        json.forEach(function(data) {
          var fileName = data.name;
          var destination = "./public/mode_assets/p5/examples/".concat(params.category);
          download(data.download_url)
            .pipe(gulp.dest(destination));
        });
      }
    });
  });
}

gulp.task('getExamples', function(){
  var headers = {'User-Agent': 'p5.js-editor/0.0.1'};
  // get example source files
  var options = {
      url: 'https://api.github.com/repos/processing/p5.js-website/contents/examples/examples_src',
      method: 'GET',
      headers: headers
  };
  var requestParams = [];
  request(options, function (error, response, body) {
    var json = JSON.parse(body);
    json.forEach(function(metadata) {
      // extract category for filename
      var category = metadata.name.split("_")[1];
      requestParams.push({url: metadata.url, category: category});
    });
    saveDataForCategory(requestParams);
  });
  // get example assets
  options.url = 'https://api.github.com/repos/processing/p5.js-website/contents/examples/examples/assets';
  request(options, function (error, response, body) {
    var assetsDest = "./public/mode_assets/p5/example_assets/";
    if (!error && response.statusCode == 200) {
      var json = JSON.parse(body);
      json.forEach(function(data) {
        var fileName = data.name;
        download(data.download_url)
          .pipe(gulp.dest(assetsDest));
      });
    }
  });
});

gulp.task('build',  build);
//gulp.task('build', ['nw-build', 'copy-ffmpeg-build']);
gulp.task('latest', latest);
gulp.task('default', ['copy-ffmpeg-default', 'css', 'browserify', 'injected-js', 'watch']);
<commit_msg>fix typo in gulp file<commit_after>var gulp = require('gulp');
var NwBuilder = require('nw-builder');
var plumber = require('gulp-plumber');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var concat = require('gulp-concat');
var notify = require('gulp-notify');
var zip = require('gulp-zip');
var browserify = require('gulp-browserify');
var partialify = require('partialify');
var release = require('github-release');
var download = require("gulp-download");
var Path = require('path');
var fs = require('fs');
var info = require('./package.json');
var request = require('request');

var isWin = process.platform.indexOf('win') > -1;

var builderOptions = {
  version: info.devDependencies.nw,
  buildType: 'versioned',
  files: [ './public/**'],
  buildDir: './dist',
  platforms: ['osx64', 'win64'],
  macIcns: './icons/p5js.icns',
  winIco: './icons/p5js.ico',
  macPlist: {
    'CFBundleDocumentTypes':[
      {
        'CFBundleTypeName': 'js',
        'CFBundleTypeIconFile': 'p5js.icons',
        'LSItemContentTypes': ['com.netscape.javascript-source']
      },
      {
        'CFBundleTypeName': 'html',
        'CFBundleTypeIconFile': 'p5js.icons',
        'LSItemContentTypes': ['public.html']
      },
      {
        'CFBundleTypeName': 'css',
        'CFBundleTypeIconFile': 'p5js.icons',
      },
      {
        'CFBundleTypeName': 'Folder',
        'CFBundleTypeOSTypes': [
          'fold'
        ]
      }
    ]
  }
};

var binaryDir = Path.join(builderOptions.buildDir, info.name + " - v" + info.version);
var latestDir = Path.join(Path.join(builderOptions.buildDir, 'latest'));

var jsPath = ['./app/*.js', './app/**/*.js', './app/**/*.html', './public/index.html'];
var cssPath = './app/**/*.scss';
var debugClientPath = './app/debug/client.js';

gulp.task('browserify', function() {
  gulp.src('./app/main.js', { read: false })
    .pipe(plumber())
    .pipe(browserify({
      transform: [partialify],
    }))
    .on("error", notify.onError({
      message: "<%= error.message %>",
      title: "Error"
    }))
    .pipe(rename('main.js'))
    .pipe(gulp.dest('./public/js/'));
});

gulp.task('injected-js', function(){
  return gulp.src(['./public/node_modules/socket.io/node_modules/socket.io-client/socket.io.js', debugClientPath])
    .pipe(concat('debug-console.js'))
    .pipe(gulp.dest('./public/js/'));
});

gulp.task('css', function() {
  gulp.src(cssPath)
    .pipe(plumber())
    .pipe(concat('main.css'))
    .pipe(sass({
      //outputStyle: 'compressed'
    }))
    .pipe(gulp.dest('./public/css/'));
});

gulp.task('watch', function() {
  gulp.watch(jsPath, ['browserify']);
  gulp.watch(cssPath, ['css']);
  gulp.watch(debugClientPath, ['injected-js']);
});

function build (cb) {
  var nw = new NwBuilder(builderOptions);

  nw.on('log', console.log);

  nw.build().then(function () {

    copyFfmpegBuild();

    cb();
  }).catch(function (error) {
    console.error(error);
  });

}

// copies the ffmpegsumo.so with mp3/mp4 decoders to nwjs directory for BUILD (currently only MacOS)
// puts the correct library in the dist folder.
function copyFfmpegBuild() {
  console.log('copying ffmpegsumo.so to ./dist');
  gulp.src('./lib/ffmpegsumo.so')
    .pipe(gulp.dest(binaryDir + '/osx64/p5.app/Contents/Frameworks/nwjs Framework.framework/Libraries',
       {overwrite: true}));

  console.log('copying ffmpegsumo.dll to ./dist');
  gulp.src('./lib/ffmpegsumo.dll')
    .pipe(gulp.dest(binaryDir + '/win64',
       {overwrite: true}));
}

// copies the ffmpegsumo.so with mp3/mp4 decoders to nwjs directory for development, assuming npm is already run
gulp.task('copy-ffmpeg-default', function() {
  console.log('copying ffmpegsumo to ./node_modules');
  if (isWin) {
    gulp.src('./lib/ffmpegsumo.dll')
      .pipe(gulp.dest('./node_modules/nw/nwjs/',
         {overwrite: true}));
  } else {
    gulp.src('./lib/ffmpegsumo.so')
      .pipe(gulp.dest('./node_modules/nw/nwjs/nwjs.app/Contents/Frameworks/nwjs Framework.framework/Libraries/',
         {overwrite: true}));
    }
});

function latest () {
  console.log('Compressing...');

  builderOptions.platforms.forEach(function(p){
    var output = 'p5-' + (p.indexOf('win') > -1 ? 'win' : 'mac') + '.zip';
    gulp.src(binaryDir + '/' + p +'/**').
      pipe(zip(output)).
      pipe(gulp.dest(latestDir)).
      on('end', function(){
        console.log('Build compressed');
      });

  });
}

gulp.task('p5', function () {
  // which files to download
  var fileNames = ['p5.js', 'p5.dom.js', 'p5.sound.js'];

  // get latest repo data from github api
  request({
    url: 'https://api.github.com/repos/processing/p5.js/releases/latest',
    headers: {
      'User-Agent' : 'request'
    }
  }, function(error, response, body) {
    var assets = JSON.parse(body).assets;
    assets.forEach(function(asset) {
      if (fileNames.indexOf(asset.name) > -1) {
        var url = asset.browser_download_url;
        download(url)
          .pipe(gulp.dest("./public/mode_assets/p5/empty_project/libraries/"));
      }
    })
  });

});

gulp.task('release', function(){
  build(function(){
    latest().pipe(release(info));
  });
});

function saveDataForCategory(requestParams) {
  var headers = {'User-Agent': 'p5.js-editor/0.0.1'};
  requestParams.forEach(function(params)  {
    // extract download URL for examples in this category
    var options = {
      url: params.url,
      method: 'GET',
      headers: headers
    };
    var fileMetadata = [];
    request(options, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var json = JSON.parse(body);
        json.forEach(function(data) {
          var fileName = data.name;
          var destination = "./public/mode_assets/p5/examples/".concat(params.category);
          download(data.download_url)
            .pipe(gulp.dest(destination));
        });
      }
    });
  });
}

gulp.task('getExamples', function(){
  var headers = {'User-Agent': 'p5.js-editor/0.0.1'};
  // get example source files
  var options = {
      url: 'https://api.github.com/repos/processing/p5.js-website/contents/examples/examples_src',
      method: 'GET',
      headers: headers
  };
  var requestParams = [];
  request(options, function (error, response, body) {
    var json = JSON.parse(body);
    json.forEach(function(metadata) {
      // extract category for filename
      var category = metadata.name.split("_")[1];
      requestParams.push({url: metadata.url, category: category});
    });
    saveDataForCategory(requestParams);
  });
  // get example assets
  options.url = 'https://api.github.com/repos/processing/p5.js-website/contents/examples/examples/assets';
  request(options, function (error, response, body) {
    var assetsDest = "./public/mode_assets/p5/example_assets/";
    if (!error && response.statusCode == 200) {
      var json = JSON.parse(body);
      json.forEach(function(data) {
        var fileName = data.name;
        download(data.download_url)
          .pipe(gulp.dest(assetsDest));
      });
    }
  });
});

gulp.task('build',  build);
//gulp.task('build', ['nw-build', 'copy-ffmpeg-build']);
gulp.task('latest', latest);
gulp.task('default', ['copy-ffmpeg-default', 'css', 'browserify', 'injected-js', 'watch']);
<|endoftext|>


<commit_before>// Gulp
//
// This is not a normal require, because our gulp-help tool (which provides the
// nice task descriptions on the command-line) requires changing the function
// signature of gulp tasks to include the task description.
var gulp = require('gulp-help')(require('gulp'));

// Gulp / Node utilities
var u = require('gulp-util');
var log = u.log;
var c = u.colors;
var del = require('del');
var spawn = require('child_process').spawn;
var sequence = require('run-sequence');

// Basic workflow plugins
var prefix = require('gulp-autoprefixer');
var sass = require('gulp-sass');
var bs = require('browser-sync');
var reload = bs.reload;

// Performance workflow plugins
var concat = require('gulp-concat');
var mincss = require('gulp-minify-css');
var imagemin = require('gulp-imagemin');
var uncss = require('gulp-uncss');
var uglify = require('gulp-uglify');
var critical = require('critical');

// Performance testing plugins
var psi = require('psi');
var wpt = require('webpagetest');
var ngrok = require('ngrok');

// -----------------------------------------------------------------------------
// Remove old CSS
//
// This task only deletes the files generated by the 'sass' and 'css' tasks.
// The 'uncss' task is slow to run and less frequently needed, so we keep the
// build process fast by preserving the results of uncss.
// -----------------------------------------------------------------------------
gulp.task('clean-css', false, function() {
  return del(['css/{all,main}*'], function (err) {
    if (err) { log(c.red('clean-css'), err); }
    else {
      log(
        c.green('clean-css'),
        'deleted old stylesheets'
      );
    }
  });
});

// -----------------------------------------------------------------------------
// Sass Task
//
// Compiles Sass and runs the CSS through autoprefixer. A separate task will
// combine the compiled CSS with vendor files and minify the aggregate.
// -----------------------------------------------------------------------------
gulp.task('sass', 'Compiles Sass and uses autoprefixer', function() {
  return gulp.src('_sass/**/*.scss')
    .pipe(sass({
      outputStyle: 'nested',
      onSuccess: function(css) {
        var dest = css.stats.entry.split('/');
        log(c.green('sass'), 'compiled to', dest[dest.length - 1]);
      },
      onError: function(err, res) {
        log(c.red('Sass failed to compile'));
        log(c.red('> ') + err.file.split('/')[err.file.split('/').length - 1] + ' ' + c.underline('line ' + err.line) + ': ' + err.message);
      }
    }))
    .pipe(prefix("last 2 versions", "> 1%"))
    .pipe(gulp.dest('css'));
});

// -----------------------------------------------------------------------------
// Combine and Minify CSS
//
// This task minifies all the CSS found in the css/ directory, including the
// uncss-ed copies of bootstrap. The end result is a minified aggregate, ready
// to be served.
// -----------------------------------------------------------------------------
gulp.task('css', 'Removes old CSS, compiles Sass, combines CSS, minifies CSS', ['clean-css', 'sass'], function() {
  bs.notify('Running: CSS task');

  return gulp.src('css/*.css')
    .pipe(concat('all.min.css'))
    .pipe(mincss())
    .pipe(gulp.dest('css'))
    .pipe(gulp.dest('_site/css'))
    .pipe(reload({stream: true}));
});

// -----------------------------------------------------------------------------
// UnCSS Task
//
// Checks the site's usage of Bootstrap and strips unused styles out. Outputs
// the resulting files in the css/ directory where they will be combined and
// minified by a separate task.
//
// Note: this task requires a local server to be running because it references
// the actual compiled site to calculate the unused styles.
// -----------------------------------------------------------------------------
gulp.task('uncss', 'Removes unused CSS from frameworks', function() {
  return gulp.src([
      'node_modules/bootstrap/dist/css/bootstrap.css',
      'node_modules/bootstrap/dist/css/bootstrap-theme.css'
    ])
    .pipe(uncss({
      html: [
        'http://localhost:4000/',
        'http://localhost:4000/audit/',
        'http://localhost:4000/foundation/',
        'http://localhost:4000/budgets/'
      ]
    }))
    .pipe(gulp.dest('css/'));
});

// -----------------------------------------------------------------------------
// Combine and Minify JS
//
// Just like the CSS task, the end result of this task is a minified aggregate
// of JS ready to be served.
// -----------------------------------------------------------------------------
gulp.task('js', 'Combines and minifies JS', function() {
  return gulp.src('_js/**/*.js')
    .pipe(concat('all.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest('js'))
    .pipe(gulp.dest('_site/js'))
    .pipe(reload({stream: true}));
});

// -----------------------------------------------------------------------------
// Generate critical-path CSS
//
// This task generates a small, minimal amount of your CSS based on which rules
// are visible (aka "above the fold") during a page load. We will use a Jekyll
// template command to inline the CSS when the site is generated.
//
// All styles should be directly applying to an element visible when your
// website renders. If the user has to scroll even a small amount, it's not
// critical CSS.
// -----------------------------------------------------------------------------
gulp.task('critical', 'Generates critical CSS for the example site', function (cb) {
  critical.generate({
    base: '_site/',
    src: 'index.html',
    css: ['css/all.min.css'],
    dimensions: [{
      width: 320,
      height: 480
    },{
      width: 768,
      height: 1024
    },{
      width: 1280,
      height: 960
    }],
    dest: '../_includes/critical.css',
    minify: true,
    extract: false
  });
});

// -----------------------------------------------------------------------------
// Minify SVGs and compress images
//
// It's good to maintain high-quality, uncompressed assets in your codebase.
// However, it's not always appropriate to serve such high-bandwidth assets to
// users, in order to reduce mobile data plan usage.
// -----------------------------------------------------------------------------
gulp.task('imagemin', 'Minifies and compresses images on the example site', function() {
  return gulp.src('_img/**/*')
    .pipe(imagemin({
      progressive: true,
      svgoPlugins: [{removeViewBox: false}]
    }))
    .pipe(gulp.dest('img'));
});

// -----------------------------------------------------------------------------
// Jekyll
//
// Regenerate the Jekyll site when files are touched. The --watch flag is not
// used because the bs/watch tasks will handle the "watching" of the files.
// -----------------------------------------------------------------------------
gulp.task('jekyll', 'Development task: generate the Jekyll server', function() {
  bs.notify('Running: Jekyll task');

  return spawn('bundle', ['exec', 'jekyll', 'build', '--config=_config.yml'], {stdio: 'inherit'})
    .on('close', reload);
});

// -----------------------------------------------------------------------------
// Jekyll Serve
//
// This command is used exclusively by Travis to start Jekyll in the background
// then run tests against it.
// -----------------------------------------------------------------------------
gulp.task('jekyll-serve', false, function(callback) {
  spawn('bundle', ['exec', 'jekyll', 'serve', '--detach', '--no-watch', '--config=_config.yml'], {stdio: 'inherit'})
    .on('close', callback)
});

// -----------------------------------------------------------------------------
// Browser Sync
//
// Makes web development better by eliminating the need to refresh. Essential
// for CSS development and multi-device testing.
// -----------------------------------------------------------------------------
gulp.task('browser-sync', false, function() {
  bs({
    server: './_site/'
  });
});

// -----------------------------------------------------------------------------
// Browser Sync using Proxy server
//
// This is a second (unused) example to demonstrate how you'd connect to a local
// server that runs itself. Examples would be a PHP site such as Wordpress or a
// Drupal site, or a node.js site like Express.
//
// Usage: gulp browser-sync-proxy --port 8080
// -----------------------------------------------------------------------------
gulp.task('browser-sync-proxy', false, function () {
  bs({
    // Point this to your pre-existing server.
    proxy: 'my-local-site.dev' + (u.env.port ? ':' + u.env.port : ''),
    // This tells BrowserSync to auto-open a tab once it boots.
    open: true
  }, function(err, bs) {
    if (err) {
      console.log(bs.options);
    }
  });
});

// -----------------------------------------------------------------------------
// Watch tasks
//
// These tasks are run whenever a file is saved. Don't confuse the files being
// watched (gulp.watch blobs in this task) with the files actually operated on
// by the gulp.src blobs in each individual task.
//
// A few of the performance-related tasks are excluded because they can take a
// bit of time to run and don't need to happen on every file change. If you want
// to run those tasks more frequently, set up a new watch task here.
// -----------------------------------------------------------------------------
gulp.task('watch', 'Watch for changes to various files and process them', function() {
  gulp.watch('_sass/**/*.scss', ['css']);
  gulp.watch('_js/**/*.js', ['js']);
  gulp.watch('_img/**/*', ['imagemin']);
  gulp.watch(['./**/*.{md,html}', '!./_site/**/*.*', '!./node_modules/**/*.*'], ['jekyll']);
});

// -----------------------------------------------------------------------------
// Convenience task for development.
//
// This is the command you run to warm the site up for development. It will do
// a full build, open BrowserSync, and start listening for changes.
// -----------------------------------------------------------------------------
gulp.task('bs', 'Main development task:', ['css', 'js', /*'imagemin',*/ 'jekyll', 'browser-sync', 'watch']);

// -----------------------------------------------------------------------------
// Performance test: Phantomas
//
// Phantomas can be used to test granular performance metrics. This example
// ensures that the site never exceeds a specific number of HTTP requests.
// -----------------------------------------------------------------------------
gulp.task('phantomas', 'Performance: measure a URL using Phantomas', function() {
  var limit = 5;
  var phantomas = spawn('./node_modules/.bin/phantomas', ['--url', 'http://localhost:4000', '--assert-requests=' + limit]);

  // Uncomment this block to see the full Phantomas output.
  // phantomas.stdout.on('data', function (data) {
  //   data = data.toString().slice(0, -1);
  //   log('Phantomas:', data);
  // });

  // Catch any errors.
  phantomas.on('error', function (err) {
    log(err);
  });

  // Log results to console.
  phantomas.on('close', function (code) {
    // Exit status of 0 means success!
    if (code === 0) {
      log('Phantomas:', c.green('✔ Yay! The site makes ' + limit + ' or fewer HTTP requests.'));
    }

    // Exit status of 1 means the site failed the test.
    else if (code === 1) {
      log('Phantomas:', c.red('✘ Rats! The site makes more than ' + limit + ' HTTP requests.'));
      process.exit(code);
    }

    // Other exit codes indicate problems with the test itself, not a failed test.
    else {
      log('Phantomas:', c.bgRed('', c.black('Something went wrong. Exit code'), code, ''));
      process.exit(code);
    }
  });
});

// -----------------------------------------------------------------------------
// Performance test: PageSpeed Insights
//
// Initializes a public tunnel so the PageSpeed service can access your local
// site, then it tests the site. This task outputs the standard PageSpeed results.
//
// The task will output a standard exit code based on the result of the PSI test
// results. 0 is success and any other number is a failure. To learn more about
// bash-compatible exit status codes read this page:
//
// http://tldp.org/LDP/abs/html/exit-status.html
// -----------------------------------------------------------------------------
gulp.task('psi', 'Performance: PageSpeed Insights', function() {
  // Set up a public tunnel so PageSpeed can see the local site.
  return ngrok.connect(4000, function (err_ngrok, url) {
    log(c.cyan('ngrok'), '- serving your site from', c.yellow(url));

    // Run PageSpeed once the tunnel is up.
    psi.output(url, {
      strategy: 'mobile',
      threshold: 80
    }, function (err_psi, data) {
      // Log any potential errors and return a FAILURE.
      if (err_psi) {
        log(err_psi);
        process.exit(1);
      }

      // Kill the ngrok tunnel and return SUCCESS.
      process.exit(0);
    });
  });
});

// -----------------------------------------------------------------------------
// Performance test: Critical CSS
//
// This test checks our generated critical CSS to make sure there are no external
// requests which would block rendering. Having external calls defeats the entire
// purpose of inlining the CSS, since the external call blocks rendering.
// -----------------------------------------------------------------------------
gulp.task('critical-test', 'Performance: check the contents of critical CSS', function () {
  // Spawn our critical CSS test and suppress all output.
  var critical = spawn('./examples/critical/critical.sh', ['>/dev/null']);

  // Catch any errors.
  critical.on('error', function (err) {
    log(err);
  });

  // Log results to console.
  critical.on('close', function (code) {
    // Exit status of 0 means success!
    if (code === 0) {
      log('Critical:', c.green('✔ Yay! The generated CSS makes zero external requests.'));
    }

    // Exit status of anything else means the test failed.
    else {
      log('Critical:', c.red('✘ Rats! The generated CSS makes ' + code + ' external requests.'));
      process.exit(code);
    }
  });
});

// -----------------------------------------------------------------------------
// Performance test: WebPageTest.org
//
// Initializes a public tunnel so the PageSpeed service can access your local
// site, then it tests the site. This task outputs the standard PageSpeed results.
// -----------------------------------------------------------------------------
gulp.task('wpt', 'Performance: WebPageTest.org', function () {
  var keys = require('./settings.json');
  var wpt_test = wpt('www.webpagetest.org', keys.wpt);

  // Set up a public tunnel so WebPageTest can see the local site.
  return ngrok.connect(4000, function (err_ngrok, url) {
    log(c.cyan('ngrok'), '- serving your site from', c.yellow(url));

    // The `url` variable was supplied by ngrok.
    wpt_test.runTest(url, function(err_wpt, data_wpt) {
      // Log any potential errors and return a FAILURE.
      if (err_wpt) {
        log(err_wpt);
        process.exit(1);
      }

      // Open window to results.
      var wpt_results = 'http://www.webpagetest.org/result/' + data_wpt.data.testId;
      log(c.green('✔  Opening results page:', wpt_results));
      spawn('open', [wpt_results]);

      // Note to developer.
      log(c.yellow('⚠  Please keep this process running until WPT is finished.'));
      log(c.yellow('⚠  Once the results load, hit Control + C to kill this process.'));
    });
  });
});

// -----------------------------------------------------------------------------
// Performance test: run everything at once
//
// Having a task that simply runs other tasks is nice for Travis or other CI
// solutions, because you only have to specify one command, and gulp handles
// the rest.
// -----------------------------------------------------------------------------
gulp.task('test', 'Run all tests', function (callback) {
  sequence(
    'jekyll-serve',
    'critical-test',
    'phantomas',
    'psi',
    'wpt',
    callback
  );
});

// -----------------------------------------------------------------------------
// Default: load task listing
//
// Instead of launching some unspecified build process when someone innocently
// types `gulp` into the command line, we provide a task listing so they know
// what options they have without digging into the file.
// -----------------------------------------------------------------------------
gulp.task('default', false, ['help']);
<commit_msg>:construction: use browsersync port for uncss<commit_after>// Gulp
//
// This is not a normal require, because our gulp-help tool (which provides the
// nice task descriptions on the command-line) requires changing the function
// signature of gulp tasks to include the task description.
var gulp = require('gulp-help')(require('gulp'));

// Gulp / Node utilities
var u = require('gulp-util');
var log = u.log;
var c = u.colors;
var del = require('del');
var spawn = require('child_process').spawn;
var sequence = require('run-sequence');

// Basic workflow plugins
var prefix = require('gulp-autoprefixer');
var sass = require('gulp-sass');
var bs = require('browser-sync');
var reload = bs.reload;

// Performance workflow plugins
var concat = require('gulp-concat');
var mincss = require('gulp-minify-css');
var imagemin = require('gulp-imagemin');
var uncss = require('gulp-uncss');
var uglify = require('gulp-uglify');
var critical = require('critical');

// Performance testing plugins
var psi = require('psi');
var wpt = require('webpagetest');
var ngrok = require('ngrok');

// -----------------------------------------------------------------------------
// Remove old CSS
//
// This task only deletes the files generated by the 'sass' and 'css' tasks.
// The 'uncss' task is slow to run and less frequently needed, so we keep the
// build process fast by preserving the results of uncss.
// -----------------------------------------------------------------------------
gulp.task('clean-css', false, function() {
  return del(['css/{all,main}*'], function (err) {
    if (err) { log(c.red('clean-css'), err); }
    else {
      log(
        c.green('clean-css'),
        'deleted old stylesheets'
      );
    }
  });
});

// -----------------------------------------------------------------------------
// Sass Task
//
// Compiles Sass and runs the CSS through autoprefixer. A separate task will
// combine the compiled CSS with vendor files and minify the aggregate.
// -----------------------------------------------------------------------------
gulp.task('sass', 'Compiles Sass and uses autoprefixer', function() {
  return gulp.src('_sass/**/*.scss')
    .pipe(sass({
      outputStyle: 'nested',
      onSuccess: function(css) {
        var dest = css.stats.entry.split('/');
        log(c.green('sass'), 'compiled to', dest[dest.length - 1]);
      },
      onError: function(err, res) {
        log(c.red('Sass failed to compile'));
        log(c.red('> ') + err.file.split('/')[err.file.split('/').length - 1] + ' ' + c.underline('line ' + err.line) + ': ' + err.message);
      }
    }))
    .pipe(prefix("last 2 versions", "> 1%"))
    .pipe(gulp.dest('css'));
});

// -----------------------------------------------------------------------------
// Combine and Minify CSS
//
// This task minifies all the CSS found in the css/ directory, including the
// uncss-ed copies of bootstrap. The end result is a minified aggregate, ready
// to be served.
// -----------------------------------------------------------------------------
gulp.task('css', 'Removes old CSS, compiles Sass, combines CSS, minifies CSS', ['clean-css', 'sass'], function() {
  bs.notify('Running: CSS task');

  return gulp.src('css/*.css')
    .pipe(concat('all.min.css'))
    .pipe(mincss())
    .pipe(gulp.dest('css'))
    .pipe(gulp.dest('_site/css'))
    .pipe(reload({stream: true}));
});

// -----------------------------------------------------------------------------
// UnCSS Task
//
// Checks the site's usage of Bootstrap and strips unused styles out. Outputs
// the resulting files in the css/ directory where they will be combined and
// minified by a separate task.
//
// Note: this task requires a local server to be running because it references
// the actual compiled site to calculate the unused styles.
// -----------------------------------------------------------------------------
gulp.task('uncss', 'Removes unused CSS from frameworks', function() {
  return gulp.src([
      'node_modules/bootstrap/dist/css/bootstrap.css',
      'node_modules/bootstrap/dist/css/bootstrap-theme.css'
    ])
    .pipe(uncss({
      html: [
        'http://localhost:3000/',
        'http://localhost:3000/audit/',
        'http://localhost:3000/foundation/',
        'http://localhost:3000/budgets/'
      ]
    }))
    .pipe(gulp.dest('css/'));
});

// -----------------------------------------------------------------------------
// Combine and Minify JS
//
// Just like the CSS task, the end result of this task is a minified aggregate
// of JS ready to be served.
// -----------------------------------------------------------------------------
gulp.task('js', 'Combines and minifies JS', function() {
  return gulp.src('_js/**/*.js')
    .pipe(concat('all.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest('js'))
    .pipe(gulp.dest('_site/js'))
    .pipe(reload({stream: true}));
});

// -----------------------------------------------------------------------------
// Generate critical-path CSS
//
// This task generates a small, minimal amount of your CSS based on which rules
// are visible (aka "above the fold") during a page load. We will use a Jekyll
// template command to inline the CSS when the site is generated.
//
// All styles should be directly applying to an element visible when your
// website renders. If the user has to scroll even a small amount, it's not
// critical CSS.
// -----------------------------------------------------------------------------
gulp.task('critical', 'Generates critical CSS for the example site', function (cb) {
  critical.generate({
    base: '_site/',
    src: 'index.html',
    css: ['css/all.min.css'],
    dimensions: [{
      width: 320,
      height: 480
    },{
      width: 768,
      height: 1024
    },{
      width: 1280,
      height: 960
    }],
    dest: '../_includes/critical.css',
    minify: true,
    extract: false
  });
});

// -----------------------------------------------------------------------------
// Minify SVGs and compress images
//
// It's good to maintain high-quality, uncompressed assets in your codebase.
// However, it's not always appropriate to serve such high-bandwidth assets to
// users, in order to reduce mobile data plan usage.
// -----------------------------------------------------------------------------
gulp.task('imagemin', 'Minifies and compresses images on the example site', function() {
  return gulp.src('_img/**/*')
    .pipe(imagemin({
      progressive: true,
      svgoPlugins: [{removeViewBox: false}]
    }))
    .pipe(gulp.dest('img'));
});

// -----------------------------------------------------------------------------
// Jekyll
//
// Regenerate the Jekyll site when files are touched. The --watch flag is not
// used because the bs/watch tasks will handle the "watching" of the files.
// -----------------------------------------------------------------------------
gulp.task('jekyll', 'Development task: generate the Jekyll server', function() {
  bs.notify('Running: Jekyll task');

  return spawn('bundle', ['exec', 'jekyll', 'build', '--config=_config.yml'], {stdio: 'inherit'})
    .on('close', reload);
});

// -----------------------------------------------------------------------------
// Jekyll Serve
//
// This command is used exclusively by Travis to start Jekyll in the background
// then run tests against it.
// -----------------------------------------------------------------------------
gulp.task('jekyll-serve', false, function(callback) {
  spawn('bundle', ['exec', 'jekyll', 'serve', '--detach', '--no-watch', '--config=_config.yml'], {stdio: 'inherit'})
    .on('close', callback)
});

// -----------------------------------------------------------------------------
// Browser Sync
//
// Makes web development better by eliminating the need to refresh. Essential
// for CSS development and multi-device testing.
// -----------------------------------------------------------------------------
gulp.task('browser-sync', false, function() {
  bs({
    server: './_site/'
  });
});

// -----------------------------------------------------------------------------
// Browser Sync using Proxy server
//
// This is a second (unused) example to demonstrate how you'd connect to a local
// server that runs itself. Examples would be a PHP site such as Wordpress or a
// Drupal site, or a node.js site like Express.
//
// Usage: gulp browser-sync-proxy --port 8080
// -----------------------------------------------------------------------------
gulp.task('browser-sync-proxy', false, function () {
  bs({
    // Point this to your pre-existing server.
    proxy: 'my-local-site.dev' + (u.env.port ? ':' + u.env.port : ''),
    // This tells BrowserSync to auto-open a tab once it boots.
    open: true
  }, function(err, bs) {
    if (err) {
      console.log(bs.options);
    }
  });
});

// -----------------------------------------------------------------------------
// Watch tasks
//
// These tasks are run whenever a file is saved. Don't confuse the files being
// watched (gulp.watch blobs in this task) with the files actually operated on
// by the gulp.src blobs in each individual task.
//
// A few of the performance-related tasks are excluded because they can take a
// bit of time to run and don't need to happen on every file change. If you want
// to run those tasks more frequently, set up a new watch task here.
// -----------------------------------------------------------------------------
gulp.task('watch', 'Watch for changes to various files and process them', function() {
  gulp.watch('_sass/**/*.scss', ['css']);
  gulp.watch('_js/**/*.js', ['js']);
  gulp.watch('_img/**/*', ['imagemin']);
  gulp.watch(['./**/*.{md,html}', '!./_site/**/*.*', '!./node_modules/**/*.*'], ['jekyll']);
});

// -----------------------------------------------------------------------------
// Convenience task for development.
//
// This is the command you run to warm the site up for development. It will do
// a full build, open BrowserSync, and start listening for changes.
// -----------------------------------------------------------------------------
gulp.task('bs', 'Main development task:', ['css', 'js', /*'imagemin',*/ 'jekyll', 'browser-sync', 'watch']);

// -----------------------------------------------------------------------------
// Performance test: Phantomas
//
// Phantomas can be used to test granular performance metrics. This example
// ensures that the site never exceeds a specific number of HTTP requests.
// -----------------------------------------------------------------------------
gulp.task('phantomas', 'Performance: measure a URL using Phantomas', function() {
  var limit = 5;
  var phantomas = spawn('./node_modules/.bin/phantomas', ['--url', 'http://localhost:4000', '--assert-requests=' + limit]);

  // Uncomment this block to see the full Phantomas output.
  // phantomas.stdout.on('data', function (data) {
  //   data = data.toString().slice(0, -1);
  //   log('Phantomas:', data);
  // });

  // Catch any errors.
  phantomas.on('error', function (err) {
    log(err);
  });

  // Log results to console.
  phantomas.on('close', function (code) {
    // Exit status of 0 means success!
    if (code === 0) {
      log('Phantomas:', c.green('✔ Yay! The site makes ' + limit + ' or fewer HTTP requests.'));
    }

    // Exit status of 1 means the site failed the test.
    else if (code === 1) {
      log('Phantomas:', c.red('✘ Rats! The site makes more than ' + limit + ' HTTP requests.'));
      process.exit(code);
    }

    // Other exit codes indicate problems with the test itself, not a failed test.
    else {
      log('Phantomas:', c.bgRed('', c.black('Something went wrong. Exit code'), code, ''));
      process.exit(code);
    }
  });
});

// -----------------------------------------------------------------------------
// Performance test: PageSpeed Insights
//
// Initializes a public tunnel so the PageSpeed service can access your local
// site, then it tests the site. This task outputs the standard PageSpeed results.
//
// The task will output a standard exit code based on the result of the PSI test
// results. 0 is success and any other number is a failure. To learn more about
// bash-compatible exit status codes read this page:
//
// http://tldp.org/LDP/abs/html/exit-status.html
// -----------------------------------------------------------------------------
gulp.task('psi', 'Performance: PageSpeed Insights', function() {
  // Set up a public tunnel so PageSpeed can see the local site.
  return ngrok.connect(4000, function (err_ngrok, url) {
    log(c.cyan('ngrok'), '- serving your site from', c.yellow(url));

    // Run PageSpeed once the tunnel is up.
    psi.output(url, {
      strategy: 'mobile',
      threshold: 80
    }, function (err_psi, data) {
      // Log any potential errors and return a FAILURE.
      if (err_psi) {
        log(err_psi);
        process.exit(1);
      }

      // Kill the ngrok tunnel and return SUCCESS.
      process.exit(0);
    });
  });
});

// -----------------------------------------------------------------------------
// Performance test: Critical CSS
//
// This test checks our generated critical CSS to make sure there are no external
// requests which would block rendering. Having external calls defeats the entire
// purpose of inlining the CSS, since the external call blocks rendering.
// -----------------------------------------------------------------------------
gulp.task('critical-test', 'Performance: check the contents of critical CSS', function () {
  // Spawn our critical CSS test and suppress all output.
  var critical = spawn('./examples/critical/critical.sh', ['>/dev/null']);

  // Catch any errors.
  critical.on('error', function (err) {
    log(err);
  });

  // Log results to console.
  critical.on('close', function (code) {
    // Exit status of 0 means success!
    if (code === 0) {
      log('Critical:', c.green('✔ Yay! The generated CSS makes zero external requests.'));
    }

    // Exit status of anything else means the test failed.
    else {
      log('Critical:', c.red('✘ Rats! The generated CSS makes ' + code + ' external requests.'));
      process.exit(code);
    }
  });
});

// -----------------------------------------------------------------------------
// Performance test: WebPageTest.org
//
// Initializes a public tunnel so the PageSpeed service can access your local
// site, then it tests the site. This task outputs the standard PageSpeed results.
// -----------------------------------------------------------------------------
gulp.task('wpt', 'Performance: WebPageTest.org', function () {
  var keys = require('./settings.json');
  var wpt_test = wpt('www.webpagetest.org', keys.wpt);

  // Set up a public tunnel so WebPageTest can see the local site.
  return ngrok.connect(4000, function (err_ngrok, url) {
    log(c.cyan('ngrok'), '- serving your site from', c.yellow(url));

    // The `url` variable was supplied by ngrok.
    wpt_test.runTest(url, function(err_wpt, data_wpt) {
      // Log any potential errors and return a FAILURE.
      if (err_wpt) {
        log(err_wpt);
        process.exit(1);
      }

      // Open window to results.
      var wpt_results = 'http://www.webpagetest.org/result/' + data_wpt.data.testId;
      log(c.green('✔  Opening results page:', wpt_results));
      spawn('open', [wpt_results]);

      // Note to developer.
      log(c.yellow('⚠  Please keep this process running until WPT is finished.'));
      log(c.yellow('⚠  Once the results load, hit Control + C to kill this process.'));
    });
  });
});

// -----------------------------------------------------------------------------
// Performance test: run everything at once
//
// Having a task that simply runs other tasks is nice for Travis or other CI
// solutions, because you only have to specify one command, and gulp handles
// the rest.
// -----------------------------------------------------------------------------
gulp.task('test', 'Run all tests', function (callback) {
  sequence(
    'jekyll-serve',
    'critical-test',
    'phantomas',
    'psi',
    'wpt',
    callback
  );
});

// -----------------------------------------------------------------------------
// Default: load task listing
//
// Instead of launching some unspecified build process when someone innocently
// types `gulp` into the command line, we provide a task listing so they know
// what options they have without digging into the file.
// -----------------------------------------------------------------------------
gulp.task('default', false, ['help']);
<|endoftext|>


<commit_before>var gulp = require('gulp'),
    sass = require('gulp-ruby-sass'),
    autoprefixer = require('gulp-autoprefixer'),
    minifycss = require('gulp-minify-css'),
    jshint = require('gulp-jshint'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    clean = require('gulp-clean'),
    concat = require('gulp-concat'),
    cache = require('gulp-cache'),
    express = require('express'),
    livereload = require('gulp-livereload'),
    lr = require('tiny-lr'),
    lrserver = lr(),
    server = express(),
    livereloadport = 35729,
    serverport = 5000;

server.use(livereload({
    port: livereloadport
}));
server.use(express.static(__dirname + '/dist/'));

gulp.task('styles', function() {
  return gulp.src('src/sass/main.scss')
    .pipe(sass({ style: 'expanded' }))
    .pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(rename({suffix: '.min'}))
    .pipe(minifycss())
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(livereload(lrserver));
});

gulp.task('scripts', function() {
  return gulp.src('src/js/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('default'))
    .pipe(concat('main.js'))
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(uglify())
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(livereload(lrserver));
});

//gulp.task('images', function() {
//  return gulp.src('src/img/**/*')
//    .pipe(cache(imageop({ optimizationLevel: 5, progressive: true, interlaced: true })))
//    .pipe(gulp.dest('dist/assets/img'))
//    .pipe(livereload(lrserver));
//});

gulp.task('clean', function() {
  return gulp.src(['dist/assets/css', 'dist/assets/js', 'dist/assets/img'], {read: false})
    .pipe(clean());
});

gulp.task('serve', function() {
  server.listen(serverport);

  lrserver.listen(livereloadport);
});

gulp.task('default', ['clean'], function() {
    gulp.start('styles', 'scripts');
});

gulp.task('watch', function() {

    gulp.start('serve');

    // Watch .scss files
    gulp.watch('src/sass/**/*.scss', ['styles']);

    // Watch .js files
    gulp.watch('src/js/**/*.js', ['scripts']);

    // Watch image files
    // gulp.watch('src/img/**/*', ['images']);

});<commit_msg>Add new software to gulpfile<commit_after>var gulp = require('gulp'),
    sass = require('gulp-ruby-sass'),
    autoprefixer = require('gulp-autoprefixer'),
    minifycss = require('gulp-minify-css'),
    cmq = require('gulp-combine-media-queries'),
    jshint = require('gulp-jshint'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    clean = require('gulp-clean'),
    concat = require('gulp-concat'),
    cache = require('gulp-cache'),
    express = require('express'),
    livereload = require('gulp-livereload'),
    lr = require('tiny-lr'),
    uncss = require('gulp-uncss'),
    glob = require('glob'),
    lrserver = lr(),
    server = express(),
    livereloadport = 35729,
    serverport = 5000;

server.use(livereload({
    port: livereloadport
}));
server.use(express.static(__dirname + '/dist/'));

gulp.task('styles', function() {
  return gulp.src('src/sass/main.scss')
    .pipe(sass({ style: 'expanded' }))
    .pipe(autoprefixer('last 2 versions'))
    .pipe(uncss({
      html: glob.sync('dist/**/*.html'),
      ignore: [/is-/, /not-/]
    }))
    .pipe(cmq({
      log: true
    }))
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(rename({suffix: '.min'}))
    .pipe(minifycss())
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(livereload(lrserver));
});

gulp.task('scripts', function() {
  return gulp.src('src/js/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('default'))
    .pipe(concat('main.js'))
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(uglify())
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(livereload(lrserver));
});

gulp.task('clean', function() {
  return gulp.src(['dist/assets/css', 'dist/assets/js'], {read: false})
    .pipe(clean());
});

gulp.task('serve', function() {
  server.listen(serverport);

  lrserver.listen(livereloadport);
});

gulp.task('default', ['clean'], function() {
    gulp.start('styles', 'scripts');
});

gulp.task('watch', function() {

    gulp.start('serve');

    // Watch .scss files
    gulp.watch('src/sass/**/*.scss', ['styles']);

    // Watch .js files
    gulp.watch('src/js/**/*.js', ['scripts']);

});<|endoftext|>


<commit_before>var gulp = require('gulp');

var path = require('path');
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

config = {
  docs: {
    entry: ['webpack-dev-server/client?http://localhost:9100', 'webpack/hot/dev-server', './docs/index.js'],
    output: {
      path: path.join(__dirname, 'build'),
      filename: 'bundle.js',
      publicPath: 'http://localhost:9100/build/'
    },
    module: {
      loaders: [
        {
          exclude: /node_modules/,
          test: /\.js$/,
          loaders: ['react-hot-loader']
        }, {
          test: /\.jsx$/,
          exclude: /node_modules/,
          loaders: ['react-hot-loader', 'jsx-loader', 'babel-loader', 'react-map-styles']
        }, {
          test: /\.css$/,
          loaders: [ 'style-loader', 'css-loader' ]
        }, {
          test: /\.md$/,
          loaders: [ 'html-loader' ]
        }
      ]
    },
    resolve: {
      alias: {
        'react-context': path.resolve(__dirname, './src/context.jsx'),
        'react': path.resolve(__dirname, './node_modules/react')
      },
      extensions: ['', '.js', '.jsx'],
      fallback: [ path.resolve(__dirname, './modules') ]
    },
    plugins: [
      new webpack.HotModuleReplacementPlugin({ quiet: true }),
      new webpack.NoErrorsPlugin()
    ],
    devtool: 'eval',
    quiet: true
  }
};

gulp.task('docs', function(done) {
  done();
  return new WebpackDevServer(webpack(config.docs), {
    publicPath: config.docs.output.publicPath,
    hot: true,
    stats: {
      cached: false,
      cachedAssets: false,
      exclude: ['node_modules', 'components']
    }
  }).listen(9100, 'localhost', function(err, result) {
    if (err) {
      return console.log(err);
    } else {
      return console.log('webpack dev server listening at localhost:9100');
    }
  });
});

gulp.task('static', function(done){

  prodConfig = {
    entry: ['./docs/index.js'],
    output: {
      path: path.join(__dirname, '/build'),
      filename: 'bundle.js',
      publicPath: '/build/'
    },
    module: {
      loaders: [{
          test: /\.jsx$/,
          exclude: /node_modules/,
          loaders: ['jsx-loader', 'babel-loader', 'react-map-styles']
        }, {
          test: /\.coffee$/,
          loaders: ['coffee-loader']
        }, {
          test: /\.cjsx$/,
          loaders: ['coffee-jsx-loader', 'react-map-styles']
        }, {
          test: /\.css$/,
          loaders: [ 'style-loader', 'css-loader' ]
        }, {
          test: /\.md$/,
          loaders: [ 'html-loader' ]
        }
      ]
    },
    resolve: {
      alias: {
        'react-context': path.resolve(__dirname, './src/context.jsx'),
        'react': path.resolve(__dirname, './node_modules/react')
      },
      extensions: ['', '.js', '.coffee', '.jsx', '.cjsx'],
      fallback: [path.resolve(__dirname, './modules')]
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: JSON.stringify('production')
        }
      }),
      new webpack.optimize.DedupePlugin(),
      // new webpack.optimize.UglifyJsPlugin({
      //   mangle: {
      //     except: ['exports', 'require']
      // },
      //   sourceMap: false,
      //   output: {comments: false}
      // }),
      // new webpack.optimize.CommonsChunkPlugin("common.js")
    ],
    devtool: 'eval',
    quiet: true
  };

  webpack(prodConfig, function(err, stats){

    if(err) {
      throw new Error(err);
    }

    done();
  });
});

gulp.task('default', ['docs']);
<commit_msg>Add Babel Loader for `.js`<commit_after>var gulp = require('gulp');

var path = require('path');
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

config = {
  docs: {
    entry: ['webpack-dev-server/client?http://localhost:9100', 'webpack/hot/dev-server', './docs/index.js'],
    output: {
      path: path.join(__dirname, 'build'),
      filename: 'bundle.js',
      publicPath: 'http://localhost:9100/build/'
    },
    module: {
      loaders: [
        {
          exclude: /node_modules/,
          test: /\.js$/,
          loaders: ['react-hot-loader', 'babel-loader']
        }, {
          test: /\.jsx$/,
          exclude: /node_modules/,
          loaders: ['react-hot-loader', 'jsx-loader', 'babel-loader', 'react-map-styles']
        }, {
          test: /\.css$/,
          loaders: [ 'style-loader', 'css-loader' ]
        }, {
          test: /\.md$/,
          loaders: [ 'html-loader' ]
        }
      ]
    },
    resolve: {
      alias: {
        'react-context': path.resolve(__dirname, './src/context.jsx'),
        'react': path.resolve(__dirname, './node_modules/react')
      },
      extensions: ['', '.js', '.jsx'],
      fallback: [ path.resolve(__dirname, './modules') ]
    },
    plugins: [
      new webpack.HotModuleReplacementPlugin({ quiet: true }),
      new webpack.NoErrorsPlugin()
    ],
    devtool: 'eval',
    quiet: true
  }
};

gulp.task('docs', function(done) {
  done();
  return new WebpackDevServer(webpack(config.docs), {
    publicPath: config.docs.output.publicPath,
    hot: true,
    stats: {
      cached: false,
      cachedAssets: false,
      exclude: ['node_modules', 'components']
    }
  }).listen(9100, 'localhost', function(err, result) {
    if (err) {
      return console.log(err);
    } else {
      return console.log('webpack dev server listening at localhost:9100');
    }
  });
});

gulp.task('static', function(done){

  prodConfig = {
    entry: ['./docs/index.js'],
    output: {
      path: path.join(__dirname, '/build'),
      filename: 'bundle.js',
      publicPath: '/build/'
    },
    module: {
      loaders: [{
          exclude: /node_modules/,
          test: /\.js$/,
          loaders: ['babel-loader']
        }, {
          test: /\.jsx$/,
          exclude: /node_modules/,
          loaders: ['jsx-loader', 'babel-loader', 'react-map-styles']
        }, {
          test: /\.css$/,
          loaders: [ 'style-loader', 'css-loader' ]
        }, {
          test: /\.md$/,
          loaders: [ 'html-loader' ]
        }
      ]
    },
    resolve: {
      alias: {
        'react-context': path.resolve(__dirname, './src/context.jsx'),
        'react': path.resolve(__dirname, './node_modules/react')
      },
      extensions: ['', '.js', '.coffee', '.jsx', '.cjsx'],
      fallback: [path.resolve(__dirname, './modules')]
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: JSON.stringify('production')
        }
      }),
      new webpack.optimize.DedupePlugin(),
      // new webpack.optimize.UglifyJsPlugin({
      //   mangle: {
      //     except: ['exports', 'require']
      // },
      //   sourceMap: false,
      //   output: {comments: false}
      // }),
      // new webpack.optimize.CommonsChunkPlugin("common.js")
    ],
    devtool: 'eval',
    quiet: true
  };

  webpack(prodConfig, function(err, stats){

    if(err) {
      throw new Error(err);
    }

    done();
  });
});

gulp.task('default', ['docs']);
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');

gulp.task('compress', function() {
  return gulp.src('plunge.js')
  .pipe(uglify())
  .pipe(rename('plunge.min.js'))
  .pipe(gulp.dest('dist'));
})
<commit_msg>added watch function and default task<commit_after>'use strict';

var gulp = require('gulp');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');

gulp.task('compress', function() {
  return gulp.src('plunge.js')
  .pipe(uglify())
  .pipe(rename('plunge.min.js'))
  .pipe(gulp.dest('dist'));
});

gulp.task('watch', function() {
  gulp.watch('plunge.js', ['compress']);
});

gulp.task('default', ['watch']);
<|endoftext|>