module.exports = function(grunt) { const version = grunt.option('release'); const fs = require('fs'); // Project configuration. const dev = !!grunt.option('dev'); const compat = !!grunt.option('compat'); const lightweight = !!grunt.option('lightweight'); const plugins = compat ? [ "transform-async-to-generator", "syntax-async-functions", "transform-regenerator", "transform-runtime" ] : []; const presets = [[require.resolve('babel-preset-env'), { targets: { browsers: compat ? [ 'IE >= 11', 'Safari >= 9', 'Last 2 Chrome versions', 'Last 2 Firefox versions', 'Last 2 Edge versions' ] : [ 'Last 2 Chrome versions', 'Last 2 Firefox versions', 'Last 2 Safari versions', 'Last 2 Edge versions' ] } }]]; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), browserify: { openpgp: { files: { 'dist/openpgp.js': ['./src/index.js'] }, options: { browserifyOptions: { fullPaths: dev, debug: dev, standalone: 'openpgp' }, cacheFile: 'browserify-cache' + (compat ? '-compat' : '') + (lightweight ? '-lightweight' : '') + '.json', // Don't bundle these packages with openpgp.js external: ['crypto', 'zlib', 'node-localstorage', 'node-fetch', 'asn1.js', 'stream', 'buffer'].concat( compat ? [] : [ 'whatwg-fetch', 'core-js/fn/array/fill', 'core-js/fn/array/find', 'core-js/fn/array/includes', 'core-js/fn/array/from', 'core-js/fn/promise', 'core-js/fn/typed/uint8-array', 'core-js/fn/string/repeat', 'core-js/fn/symbol', 'core-js/fn/object/assign' ], lightweight ? [ 'elliptic', 'elliptic.min.js' ] : [] ), transform: [ ["babelify", { global: true, // Only babelify web-streams-polyfill, web-stream-tools, asmcrypto, email-addresses and seek-bzip in node_modules only: /^(?:.*\/node_modules\/@mattiasbuelens\/web-streams-polyfill\/|.*\/node_modules\/web-stream-tools\/|.*\/node_modules\/asmcrypto\.js\/|.*\/node_modules\/email-addresses\/|.*\/node_modules\/seek-bzip\/|(?!.*\/node_modules\/)).*$/, ignore: ['*.min.js'], plugins, presets }] ], plugin: ['browserify-derequire'] } }, worker: { files: { 'dist/openpgp.worker.js': ['./src/worker/worker.js'] }, options: { cacheFile: 'browserify-cache-worker.json' } }, unittests: { files: { 'test/lib/unittests-bundle.js': ['./test/unittests.js'] }, options: { cacheFile: 'browserify-cache-unittests.json', external: ['buffer', 'openpgp', '../../dist/openpgp', '../../../dist/openpgp'], transform: [ ["babelify", { global: true, // Only babelify chai-as-promised in node_modules only: /^(?:.*\/node_modules\/chai-as-promised\/|(?!.*\/node_modules\/)).*$/, ignore: ['*.min.js'], plugins, presets }] ] } } }, nyc: { cover: { options: { include: ['dist/**'], reporter: ['text-summary'], reportDir: 'coverage' }, cmd: false, args: ['grunt', 'mochaTest'], sourceMap: true }, report: { options: { reporter: 'text' } } }, replace: { openpgp: { src: ['dist/openpgp.js'], dest: ['dist/openpgp.js'], replacements: [{ from: /OpenPGP.js VERSION/g, to: 'OpenPGP.js v<%= pkg.version %>' }] }, openpgp_min: { src: ['dist/openpgp.min.js'], dest: ['dist/openpgp.min.js'], replacements: [{ from: "openpgp.worker.js", to: "openpgp.worker.min.js" }] }, worker_min: { src: ['dist/openpgp.worker.min.js'], dest: ['dist/openpgp.worker.min.js'], replacements: [{ from: "openpgp.js", to: "openpgp.min.js" }] }, lightweight_build: { src: ['dist/openpgp.js'], overwrite: true, replacements: [ { from: "external_indutny_elliptic: false", to: "external_indutny_elliptic: true" } ] }, indutny_global: { src: ['dist/elliptic.min.js'], overwrite: true, replacements: [ { from: 'b.elliptic=a()', to: 'b.openpgp.elliptic=a()' } ] } }, terser: { openpgp: { files: { 'dist/openpgp.min.js' : ['dist/openpgp.js'], 'dist/openpgp.worker.min.js' : ['dist/openpgp.worker.js'] }, options: { output: { comments: `/^!/` }, sourceMap: dev ? { content: 'inline', url: 'inline' } : {}, safari10: true } } }, header: { openpgp: { options: { text: '/*! OpenPGP.js v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> - ' + 'this is LGPL licensed code, see LICENSE/our website <%= pkg.homepage %> for more information. */' }, files: { 'dist/openpgp.js': 'dist/openpgp.js', 'dist/openpgp.worker.js': 'dist/openpgp.worker.js' } } }, jsbeautifier: { files: ['src/**/*.js'], options: { indent_size: 2, preserve_newlines: true, keep_array_indentation: false, keep_function_indentation: false, wrap_line_length: 120 } }, eslint: { target: ['src/**/*.js', './Gruntfile.js', './eslintrc.js', 'test/crypto/**/*.js'], options: { configFile: '.eslintrc.js', fix: !!grunt.option('fix') } }, jsdoc: { dist: { src: ['README.md', 'src'], options: { configure: '.jsdocrc.js', destination: 'doc', recurse: true } } }, mochaTest: { unittests: { options: { reporter: 'spec', timeout: 120000, grep: lightweight ? 'lightweight' : undefined }, src: ['test/unittests.js'] } }, copy: { browsertest: { expand: true, flatten: true, cwd: 'node_modules/', src: ['mocha/mocha.css', 'mocha/mocha.js'], dest: 'test/lib/' }, openpgp_compat: { expand: true, cwd: 'dist/', src: ['*.js'], dest: 'dist/compat/' }, openpgp_lightweight: { expand: true, cwd: 'dist/', src: ['*.js'], dest: 'dist/lightweight/' }, indutny_elliptic: { expand: true, flatten: true, src: ['./node_modules/elliptic/dist/elliptic.min.js'], dest: 'dist/' } }, clean: { dist: ['dist/'], js: ['dist/*.js'] }, connect: { dev: { options: { port: 3001, base: '.', keepalive: true } }, test: { options: { port: 3000, base: '.' } } }, watch: { src: { files: ['src/**/*.js'], tasks: lightweight ? ['browserify:openpgp', 'browserify:worker', 'replace:lightweight_build'] : ['browserify:openpgp', 'browserify:worker'] }, test: { files: ['test/*.js', 'test/crypto/**/*.js', 'test/general/**/*.js', 'test/worker/**/*.js'], tasks: ['browserify:unittests'] } } }); // Load the plugin(s) grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-terser'); grunt.loadNpmTasks('grunt-header'); grunt.loadNpmTasks('grunt-text-replace'); grunt.loadNpmTasks('grunt-jsbeautifier'); grunt.loadNpmTasks('grunt-jsdoc'); grunt.loadNpmTasks('gruntify-eslint'); grunt.loadNpmTasks('grunt-mocha-test'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-simple-nyc'); grunt.registerTask('set_version', function() { if (!version) { throw new Error('You must specify the version: "--release=1.0.0"'); } patchFile({ fileName: 'package.json', version: version }); patchFile({ fileName: 'package-lock.json', version: version }); patchFile({ fileName: 'bower.json', version: version }); }); function patchFile(options) { const path = './' + options.fileName; //eslint-disable-next-line const file = require(path); if (options.version) { file.version = options.version; } //eslint-disable-next-line fs.writeFileSync(path, JSON.stringify(file, null, 2) + '\n'); } // Build tasks grunt.registerTask('version', ['replace:openpgp']); grunt.registerTask('replace_min', ['replace:openpgp_min', 'replace:worker_min']); grunt.registerTask('build', function() { if (lightweight) { grunt.task.run(['copy:indutny_elliptic', 'browserify:openpgp', 'browserify:worker', 'replace:lightweight_build', 'replace:indutny_global', 'version', 'header', 'terser', 'replace_min']); return; } grunt.task.run(['browserify:openpgp', 'browserify:worker', 'version', 'header', 'terser', 'replace_min']); } ); grunt.registerTask('documentation', ['jsdoc']); grunt.registerTask('default', ['build']); // Test/Dev tasks grunt.registerTask('test', ['eslint', 'mochaTest']); grunt.registerTask('coverage', ['nyc']); grunt.registerTask('browsertest', ['build', 'browserify:unittests', 'copy:browsertest', 'connect:test', 'watch']); };