/* * Copyright 2018 Scytl Secure Electronic Voting SA * * All rights reserved * * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package */ /** * Js Tasks * @module tasks/compile-js */ const gulp = require('gulp'); const eslint = require('gulp-eslint'); const cache = require('gulp-cached'); const browserify = require('browserify'); const babelify = require('babelify'); const gutil = require('gulp-util'); const gulpif = require('gulp-if'); const uglify = require('gulp-uglify'); const sourcemaps = require('gulp-sourcemaps'); const source = require('vinyl-source-stream'); const buffer = require('vinyl-buffer'); const KarmaServer = require('karma').Server; const filesize = require('gulp-size'); const addsrc = require('gulp-add-src'); const concat = require('gulp-concat'); const runSequence = require('run-sequence'); const paths = require('../paths.json'); const { getCommandArguments, notificationOnError, } = require('./helpers'); const argv = getCommandArguments(); const libBundle = browserify({ entries : [paths.js.entryFile], debug : !argv.production || argv.debug, paths : [paths.js.src], cache : true, transform : [ babelify.configure({ presets : ['es2015'], sourceMaps : true, }), ], }); /** * Checks and flags code that doesn't correspond to the * style guidelines configured under .eslintrc file * * @task js-lint */ gulp.task('js-lint', (done) => { if (argv['skip-linting']) { console.log('[!] js-lint skipped [!]'); done(); return; } // ESLint ignores files with "node_modules" paths. // So, it's best to have gulp ignore the directory as well. // Also, Be sure to return the stream from the task; // Otherwise, the task may end before the stream has finished. return gulp.src([ `${paths.js.src}/**/*.js`, ]) .pipe(cache('js-lint', { optimizeMemory: true })) // eslint() attaches the lint output to the "eslint" property // of the file object so it can be used by other modules. .pipe(eslint()) // eslint.format() outputs the lint results to the console. // Alternatively use eslint.formatEach() (see Docs). .pipe(eslint.format()) // To have the process exit with an error code (1) on // lint error, return the stream and pipe to failOnError last. .pipe(gulpif(!argv.force, eslint.failAfterError())) .on('error', notificationOnError('\uD83D\uDE25 Linting errors found!', '<%= error.message %>')); }); /** * Runs the unit tests test/unit folder * * @task unit-tests */ gulp.task('unit-tests', (done) => { if (argv['skip-unit-tests']) { console.log('[!] unit-tests skipped [!]'); done(); return; } runSequence( 'unit-tests:all', // 'unit-tests:precompute', // 'unit-tests:proofs', done ); }); gulp.task('unit-tests:all', [], (done) => { new KarmaServer({ configFile : __dirname + '/../karma.conf.js', singleRun : true, }, done).start(); }); gulp.task('unit-tests:precompute', (done) => { new KarmaServer({ configFile : __dirname + '/../karma-precompute.conf.js', singleRun : true, }, done).start(); }); gulp.task('unit-tests:proofs', (done) => { new KarmaServer({ configFile : __dirname + '/../karma-proofs.conf.js', singleRun : true, }, done).start(); }); /** * Bundles, minifies (if production flag is true), generates the * source maps and suffixes project's version to the resulted bundle file * for the provided browserify stream. * * @param {BrowserifyObject} browserifyStream * @param {String} bundleFilename The desired filename for the bundle */ const compileBundle = (browserifyStream, bundleFilename, uglifyCode = true) => { return browserifyStream.bundle() .on('error', gutil.log) .pipe(source(bundleFilename)) .pipe(buffer()) .pipe(addsrc([`${paths.js.crypto}/forge.min.js`])) .pipe(addsrc([`${paths.js.crypto}/sjcl.js`])) .pipe(concat(uglifyCode ? paths.js.bundleMinFile : paths.js.bundleFile)) .pipe( gulpif( (!argv.production || argv.debug), sourcemaps.init({ loadMaps: true }) ) ) .pipe(gulpif(uglifyCode, uglify())) .pipe( gulpif( (!argv.production || argv.debug), sourcemaps.write('./', { includeContent: true, sourceRoot: '/ov-api' }) ) ) .pipe(filesize({ showFiles: true })); } /** * Bundles, minifies (if production arg is true), generates the source maps * (if no production arg was passed or debug args is present along with production arg) * and suffixes project's version to the resulted bundle file for the provided browserify stream. * * @task build-js */ gulp.task('build-js', ['build-js:include-sjcl', 'build-js:include-node-forge'], () => { return compileBundle(libBundle, paths.js.bundleFile) .pipe(gulp.dest(`${paths.js.dist}`)); }); gulp.task('build-js:include-node-forge', () => { return gulp.src(['./node_modules/node-forge/dist/forge.min.js']) .pipe(gulp.dest(paths.js.crypto)); }); gulp.task('build-js:include-sjcl', () => { return gulp.src(['./node_modules/sjcl/sjcl.js']) .pipe(gulp.dest(paths.js.crypto)); }); gulp.task('build-js:for-doc', () => { return compileBundle(libBundle, paths.js.bundleFile, false) .pipe(gulp.dest('./dist/doc/src')); }); gulp.task('watch:js', () => { gulp.watch( [ `${paths.js.src}/**/*.js`, `${paths.js.src}/**/*.coffee`, ], [ 'build-js', ] ); });