module.exports = function (grunt) { // var esperanto = require('esperanto'); var rollup = require('rollup').rollup; // var babel = require('rollup-plugin-babel'); var path = require('path'), Promise = require('es6-promise').Promise, TMP_DIR = 'build/tmp', headerCache = {}; function collectComments(filename) { return grunt.file .read(filename) .split('\n') .filter(function (line) { return line.startsWith('//!'); }) .join('\n'); } function getHeaderByFile(headerFile) { if (headerFile === 'none') { return ''; } if (!(headerFile in headerCache)) { headerCache[headerFile] = grunt.file.read(headerFile); } return headerCache[headerFile]; } function rollupBundle(opts) { // entry, umdName, skipMoment var rollupOpts = { input: opts.entry, plugins: [ // babel({}) ], }, bundleOpts = { format: opts.format != null ? opts.format : 'umd', name: opts.umdName != null ? opts.umdName : 'not_used', }; if (opts.skipMoment) { // And this is what people call progress? rollupOpts.external = [ './moment', '../moment', '../../moment', path.resolve('src/moment'), path.resolve('build/tmp/moment'), ]; bundleOpts.globals = {}; bundleOpts.globals[path.resolve('src/moment')] = 'moment'; bundleOpts.globals[path.resolve('build/tmp/moment')] = 'moment'; } return rollup(rollupOpts) .then(function (bundle) { return bundle.generate(bundleOpts); }) .then(function (result) { return result.output[0].code; }); } function transpile(opts) { // base, entry, skipMoment, headerFile, skipLines, target var umdName = opts.headerFile != null && opts.headerFile !== 'none' ? 'not_used' : opts.umdName, headerFile = opts.headerFile ? opts.headerFile : 'templates/default.js', header = getHeaderByFile(headerFile), skipLines = opts.skipLines != null ? opts.skipLines : 5, entry = path.join(opts.base, opts.entry); return rollupBundle({ entry: entry, skipMoment: opts.skipMoment != null ? opts.skipMoment : false, umdName: umdName, format: opts.format, }).then(function (code) { var fixed = header + code.split('\n').slice(skipLines).join('\n'); if (opts.moveComments) { fixed = collectComments(entry) + '\n\n' + fixed; } grunt.file.write(opts.target, fixed); }); } function transpileMany(opts) { var batchSize = 50, promise = Promise.resolve(null), files = grunt.file.expand({ cwd: opts.base }, opts.pattern), i, transpileOne = function (i) { promise = promise.then(function () { return Promise.all( files.slice(i, i + batchSize).map(function (file) { return transpile({ base: opts.base, entry: file, headerFile: opts.headerFile, skipMoment: opts.skipMoment, skipLines: opts.skipLines, moveComments: opts.moveComments, target: path.join(opts.targetDir, file), }); }) ); }); }; for (i = 0; i < files.length; i += batchSize) { transpileOne(i); } return promise; } function prepareTemp(base) { var files = grunt.file.expand({ cwd: base }, '**/*.js'), tmpDir = TMP_DIR; if (grunt.file.exists(tmpDir)) { return; } files.forEach(function (file) { grunt.file.copy(path.join(base, file), path.join(tmpDir, file)); }); } function transpileCode(opts) { var entry = opts.entry || path.basename(opts.target); prepareTemp(opts.base); grunt.file.write(path.join(TMP_DIR, entry), opts.code); return transpile({ base: TMP_DIR, entry: entry, umdName: opts.umdName || 'not_used', headerFile: opts.headerFile, skipLines: opts.skipLines, moveComments: opts.moveComments, target: opts.target, skipMoment: opts.skipMoment, }); } function generateLocales(target, localeFiles, opts) { var files = localeFiles, code = ['import moment from "./moment";', 'export default moment;'] .concat( files.map(function (file) { var identifier = path .basename(file, '.js') .replace('-', '_'); return ( 'import ' + identifier + ' from "./' + file + '";' ); }) ) .concat([ // Reset the language back to 'en', because every defineLocale // also sets it. "moment.locale('en');", ]) .join('\n'); return transpileCode({ base: 'src', code: code, target: target, skipMoment: opts.skipMoment, headerFile: opts.skipMoment === true ? 'templates/locale-header.js' : 'templates/default.js', skipLines: opts.skipMoment === true ? 7 : 5, }); } grunt.task.registerTask('transpile-raw', 'convert es6 to umd', function () { var done = this.async(); transpile({ base: 'src', entry: 'moment.js', umdName: 'moment', target: 'build/umd/moment.js', skipLines: 5, moveComments: true, }) .then(function () { grunt.log.ok('build/umd/moment.js'); }) .then(function () { return transpile({ base: 'src', entry: 'moment.js', umdName: 'moment', headerFile: 'templates/empty.js', target: 'build/esm/moment.js', format: 'es', skipLines: 0, moveComments: true, }); }) .then(function () { grunt.log.ok('build/esm/moment.js'); }) .then(function () { return transpileMany({ base: 'src', pattern: 'locale/*.js', headerFile: 'templates/locale-header.js', skipLines: 7, moveComments: true, targetDir: 'build/umd', skipMoment: true, }); }) .then(function () { grunt.log.ok('build/umd/locale/*.js'); }) .then(function () { return transpileMany({ base: 'src', pattern: 'test/moment/*.js', headerFile: 'templates/test-header.js', skipLines: 7, moveComments: true, targetDir: 'build/umd', skipMoment: true, }); }) .then(function () { grunt.log.ok('build/umd/test/moment/*.js'); }) .then(function () { return transpileMany({ base: 'src', pattern: 'test/locale/*.js', headerFile: 'templates/test-header.js', skipLines: 7, moveComments: true, targetDir: 'build/umd', skipMoment: true, }); }) .then(function () { grunt.log.ok('build/umd/test/locale/*.js'); }) .then(function () { return generateLocales( 'build/umd/min/locales.js', grunt.file.expand({ cwd: 'src' }, 'locale/*.js'), { skipMoment: true } ); }) .then(function () { grunt.log.ok('build/umd/min/locales.js'); }) .then(function () { return generateLocales( 'build/umd/min/moment-with-locales.js', grunt.file.expand({ cwd: 'src' }, 'locale/*.js'), { skipMoment: false } ); }) .then(function () { grunt.log.ok('build/umd/min/moment-with-locales.js'); }) .then(done, function (e) { grunt.log.error('error transpiling', e); done(e); }); }); grunt.task.registerTask( 'transpile-custom-raw', 'build just custom language bundles', function (locales) { var done = this.async(), localeFiles = locales.split(',').map(function (locale) { var file = grunt.file.expand( { cwd: 'src' }, 'locale/' + locale + '.js' ); if (file.length !== 1) { // we failed to find a locale done(new Error('could not find locale: ' + locale)); done = null; } else { return file[0]; } }); // There was an issue with a locale if (done == null) { return; } return generateLocales( 'build/umd/min/locales.custom.js', localeFiles, { skipMoment: true } ) .then(function () { grunt.log.ok('build/umd/min/locales.custom.js'); }) .then(function () { return generateLocales( 'build/umd/min/moment-with-locales.custom.js', localeFiles, { skipMoment: false } ); }) .then(function () { grunt.log.ok('build/umd/min/moment-with-locales.custom.js'); }) .then(function () { var moment = require('../build/umd/min/moment-with-locales.custom.js'); if ( moment.locales().filter(function (locale) { return locale !== 'en'; }).length !== localeFiles.length ) { throw new Error( 'You probably specified locales requiring ' + "parent locale, but didn't specify parent" ); } }) .then(done, function (e) { grunt.log.error('error transpiling-custom', e); done(e); }); } ); grunt.config('clean.build', ['build']); grunt.config('concat.tests', { src: 'build/umd/test/**/*.js', dest: 'build/umd/min/tests.js', }); grunt.task.registerTask( 'transpile', 'builds all es5 files, optinally creating custom locales', function (locales) { var tasks = ['clean:build', 'transpile-raw', 'concat:tests']; if (locales) { tasks.push('transpile-custom-raw:' + locales); } grunt.task.run(tasks); } ); };