| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- module.exports = function (grunt) {
- 'use strict';
- // Register the 'sync' task.
- grunt.registerTask('sync', 'Syncs necessary libraries for development purposes. Read more in: MAINTAINERS.md.', function () {
- var cwd = process.cwd();
- var force = grunt.option('force');
- var path = require('path');
- var pkg = require('../package');
- // Internal variables.
- var libraries = {};
- var librariesCache = path.join(cwd, pkg.caches.libraries);
- var librariesPath = path.join(cwd, pkg.paths.libraries);
- var exists = grunt.file.exists(librariesCache);
- var expired = false;
- // Determine the validity of any existing cached libraries file.
- if (!force && exists) {
- grunt.verbose.write('Cached library information detected, checking...');
- var fs = require('fs');
- var stat = fs.statSync(librariesCache);
- var now = new Date().getTime();
- var expire = new Date(stat.mtime);
- expire.setDate(expire.getDate() + 7); // 1 week
- expired = now > expire.getTime();
- grunt.verbose.writeln((expired ? 'EXPIRED' : 'VALID')[expired ? 'red' : 'green']);
- }
- // Register a private sub-task. Doing this inside the main task prevents
- // this private sub-task from being executed directly and also prevents it
- // from showing up on the list of available tasks on --help.
- grunt.registerTask('sync:api', function () {
- var done = this.async();
- var request = require('request');
- grunt.verbose.write(pkg.urls.jsdelivr + ' ');
- request(pkg.urls.jsdelivr, function (error, response, body) {
- if (!error && response.statusCode == 200) {
- grunt.verbose.ok();
- var json;
- grunt.verbose.write("\nParsing JSON response...");
- try {
- json = JSON.parse(body);
- grunt.verbose.ok();
- } catch (e) {
- grunt.verbose.error();
- throw grunt.util.error('Unable to parse the response value (' + e.message + ').', e);
- }
- grunt.verbose.write("\nExtracting versions and themes from libraries...");
- libraries = {};
- json.forEach(function (library) {
- if (library.name === 'bootstrap' || library.name === 'bootswatch') {
- library.assets.forEach(function (asset) {
- if (asset.version.match(/^3.\d\.\d$/)) {
- if (!libraries[library.name]) libraries[library.name] = {};
- if (!libraries[library.name][asset.version]) libraries[library.name][asset.version] = {};
- asset.files.forEach(function (file) {
- if (!file.match(/bootstrap\.min\.css$/)) return;
- if (library.name === 'bootstrap') {
- libraries[library.name][asset.version]['bootstrap'] = true;
- }
- else {
- libraries[library.name][asset.version][file.split(path.sep)[0]] = true;
- }
- });
- }
- });
- }
- });
- grunt.verbose.ok();
- // Flatten themes.
- for (var library in libraries) {
- grunt.verbose.header(library);
- if (!libraries.hasOwnProperty(library)) continue;
- var versions = Object.keys(libraries[library]);
- grunt.verbose.ok('Versions: ' + versions.join(', '));
- var themeCount = 0;
- for (var version in libraries[library]) {
- if (!libraries[library].hasOwnProperty(version)) continue;
- var themes = Object.keys(libraries[library][version]).sort();
- libraries[library][version] = themes;
- if (themes.length > themeCount) {
- themeCount = themes.length;
- }
- }
- grunt.verbose.ok(grunt.util.pluralize(themeCount, 'Themes: 1/Themes: ' + themeCount));
- }
- grunt.verbose.writeln();
- grunt.file.write(librariesCache, JSON.stringify(libraries, null, 2));
- grunt.log.ok('Synced');
- }
- else {
- grunt.verbose.error();
- if (error) grunt.verbose.error(error);
- grunt.verbose.error('Request URL: ' + pkg.urls.jsdelivr);
- grunt.verbose.error('Status Code: ' + response.statusCode);
- grunt.verbose.error('Response Headers: ' + JSON.stringify(response.headers, null, 2));
- grunt.verbose.error('Response:');
- grunt.verbose.error(body);
- grunt.fail.fatal('Unable to establish a connection. Run with --verbose to view the response received.');
- }
- return done(error);
- });
- });
- // Run API sync sub-task.
- if (!exists || force || expired) {
- if (!exists) grunt.verbose.writeln('No libraries cache detected, syncing libraries.');
- else if (force) grunt.verbose.writeln('Forced option detected, syncing libraries.');
- else if (expired) grunt.verbose.writeln('Libraries cache is over a week old, syncing libraries.');
- grunt.task.run(['sync:api']);
- }
- // Register another private sub-task.
- grunt.registerTask('sync:libraries', function () {
- var bower = require('bower');
- var done = this.async();
- var inquirer = require('inquirer');
- var queue = require('queue')({concurrency: 1, timeout: 60000});
- if (!grunt.file.exists(librariesCache)) {
- return grunt.fail.fatal('No libraries detected. Please run `grunt sync --force`.');
- }
- libraries = grunt.file.readJSON(librariesCache);
- var bowerJson = path.join(cwd, 'bower.json');
- if (!grunt.file.isDir(librariesPath)) grunt.file.mkdir(librariesPath);
- // Iterate over libraries.
- for (var library in libraries) {
- if (!libraries.hasOwnProperty(library)) continue;
- // Iterate over versions.
- for (var version in libraries[library]) {
- if (!libraries[library].hasOwnProperty(version)) continue;
- var endpoint = library + '#' + version;
- // Check if library is already installed. If so, skip.
- var versionPath = path.join(librariesPath, version);
- grunt.verbose.write('Checking ' + endpoint + '...');
- if (grunt.file.isDir(versionPath) && grunt.file.isDir(versionPath + '/' + library)) {
- grunt.verbose.writeln('INSTALLED'.green);
- continue;
- }
- grunt.verbose.writeln('MISSING'.red);
- grunt.file.mkdir(versionPath);
- grunt.file.copy(bowerJson, path.join(versionPath, 'bower.json'));
- var config = {
- cwd: versionPath,
- directory: '',
- interactive: true,
- scripts: {
- postinstall: 'rm -rf jquery && rm -rf font-awesome'
- }
- };
- // Enqueue bower installations.
- (function (endpoint, config) {
- queue.push(function (done) {
- bower.commands
- .install([endpoint], {saveDev: true}, config)
- .on('log', function (result) {
- if (result.level === 'action' && result.id !== 'validate' && !result.message.match(/(jquery|font-awesome)/)) {
- grunt.log.writeln(['bower', result.id.cyan, result.message.green].join(' '));
- }
- else if (result.level === 'action') {
- grunt.verbose.writeln(['bower', result.id.cyan, result.message.green].join(' '));
- }
- else {
- grunt.log.debug(['bower', result.id.cyan, result.message.green].join(' '));
- }
- })
- .on('prompt', function (prompts, callback) {
- inquirer.prompt(prompts, callback);
- })
- .on('end', function () { done() })
- ;
- });
- })(endpoint, config);
- }
- }
- // Start bower queue.
- queue.start(function (e) {
- return done(e);
- });
- });
- // Run private sub-task.
- grunt.task.run(['sync:libraries']);
- });
- }
|