<commit_before>/*
 * grunt-cdn-switch
 * https://github.com/alistair/grunt-cdn-switch
 *
 * Copyright (c) 2015 Alistair MacDonald
 * Licensed under the MIT license.
 */

'use strict';

var Promise = require('bluebird')
  , cheerio = require('cheerio')
  , http = require('http')
  , fs = require('fs')
  , mkdirp = require('mkdirp')
  ;

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks
  grunt.registerMultiTask('cdn_switch', 'Insert switchable Script and Style tags into your HTML that automatically link to Local or CDN resources.', function() {

    var target = this.target;

    // Go async (fetching and waiting on remote servers)
    var done = this.async();

    // Reference options
    var options = this.options({
      punctuation: '.',
      separator: ', '
    });

    var mode = options.cdn ? 'CDN' : 'Local';

    function checkFileExists(file){
      var path = file.path;
      return new Promise(function(resolve, reject){
        fs.exists(path, function(exists) {

          resolve({
            path: path,
            origin: file.origin,
            exists: exists
          });

        });

      });
    }

    function checkFileModifiedDate(file){
      var path = file.path;
      return new Promise(function(resolve, reject){

        if (file.exists) {

          fs.stat(path, function(err, stats){
            resolve({
              path: path,
              origin: file.origin,
              modified: stats.mtime,
              exists: true
            });
          });

        } else {

          resolve({
            path: path,
            origin: file.origin,
            modified: null,
            exists: false
         });

        }
      });
    }

    // Request a new file from the server, handle date-modified, error and end
    // events. Don't fetch file if you already have it locally.
    function requestHandler(file){
      return new Promise(function(resolve, reject){
        var path = file.path
          , url = file.origin
          , exists = file.exists
          , localModified = file.modified
          ;

        // Beging the request. Alias for cancellation (end).
        var request = http.get(url, function(response) {
          var remoteModified = response.headers['last-modified']
            , localTime = new Date(localModified).getTime()
            , remoteTime = new Date(remoteModified).getTime()
            ;

          // If the remote file is newer than the local file...
          // Or the local file does not exist...
          if (remoteTime > localTime || !exists) {

            // Write the file.
            var file = fs.createWriteStream(path);
            response.pipe(file);

          // Duck out if there are HTTP Status code errors
          } else {
            request.end();
            resolve({
              notmodified: true,
              path: path
            });
          }

          // Duck out if there are HTTP Status code errors
          if (response.statusCode.toString()[0] === '4'){
            var error = {};
            error[response.statusCode] = url;
            reject(error);
          }

        // Handle other events
        }).on('error', function(e){
          reject(e);
        }).on('end', function(){
          resolve(path);
        }).on('close', function(){
          resolve(path);
        });

      });
    }

    // Begin the fetch and date-modified check for a single fetch promise
    function fetch(fetchobj){
      var block = fetchobj.block
      , filename = fetchobj.url.slice(fetchobj.url.lastIndexOf('/') + 1)
      , local_filepath = block.local_path + '/' + filename
      ;

      grunt.log.writeln('Checking: ' + fetchobj.url);

      return checkFileExists({
        path: local_filepath,
        origin: fetchobj.url
      })
      .then(checkFileModifiedDate)
      .then(requestHandler);
    }

    // Build a stack of promises based on the resource list
    function fetch_new (block) {
      var fetchPromises = [];

      // Create a promise for each fle
      block.resources.forEach(function(url){

        // Push the new promise onto the stack
        fetchPromises.push(fetch({
          block:block,
          url: url

        }).then(function (response){

          if (response.notmodified) {
            grunt.log.writeln('Not modified: ' + response.path);
          } else {
            grunt.log.ok('Got: ' + response);
          }
          return response.path;
        }));

      });

      // Wait until all the promises are resolved, then settle
      Promise.settle(fetchPromises).then(function(results){
        grunt.log.writeln('Done fetching/checking resources.');
        var errorCount = 0;

        // Log errors when things are not fetched...
        results.forEach(function(result){
          if (!result.isFulfilled()) {
            errorCount+=1;

            grunt.log.warn('Fetch Error in resources for block: \''+block.name+'\', in target \''+target+'\'.');
            try{
              console.log(result.reason());
            }catch(e){
              console.log(e);
            }
          }
        });

        // Count errors and notify user
        if (errorCount === 0) {
          grunt.log.ok('\''+block.name+'\' files checked-with/fetched-to: \''+block.local_path+'\'');
        } else {
          grunt.log.warn('CDN-Switch: Things did not go well for you :(');
        }
      });
    }

    // Build HTML block with reource links pointing at CDN
    function buildHtmlBlockCDN(block){
      var parts = block.html.split('{{resource}}')
        , html = ''
        ;

      block.resources.forEach(function(resource){
        html += parts[0] + resource + parts[1] + '\n';
      });

      if (block.injections) {
        block.injections.forEach(function(injection){
          // html += parts[0] + injection + parts[1] + '\n';
          html += injection + '\n';
          return injection;
        });
      }

      // Remove trailling newline
      html = html.slice(0, html.length-1);
      return html;
    }

    // Build HTML block with reource links pointing to Local
    // versions of CDN files that were fetched
    function buildHtmlBlockLocal(block){
      var parts = block.html.split('{{resource}}')
        , html = ''
        ;

      block.resources.forEach(function(url){
        var filename = url.slice(url.lastIndexOf('/')+1);
        html += parts[0] + block.local_path+'/'+filename + parts[1] + '\n';
      });

      if (block.injections) {
        block.injections.forEach(function(injection){
          html += injection + '\n';
          // html += parts[0] + injection + parts[1] + '\n';
          return injection;
        });
      }

      // Remove trailling newline
      html = html.slice(0, html.length-1);
      return html;
    }

    // Filter HTML files in the Grunt files list
    function filterHtml(obj){
      obj.node.children.forEach(function(child){

        if (child.type === 'comment'){
          var splits = child.data.split('=');

          // Scan an HTML file for comment nodes that contain "cdn-switch"
          // and a target name for the grunt task.
          // Eg: <!--cdn-switch:tagert-name-->

          // When found...
          if (splits[0]==='cdn-switch' && splits[1]===obj.block.name) {

            // Build new HTML blockdepending on mode...
            var html = options.cdn ?
              buildHtmlBlockCDN(obj.block) :
              buildHtmlBlockLocal(obj.block) ;

            // Write new block into DOM and notify
            obj.$(child).replaceWith(html);

            grunt.log.ok(mode+' \''+obj.block.name+'\' comment block written to: \''+obj.dest+'\'');
          }
        }

        // If this node has children, recursively filter
        if (child.hasOwnProperty('children')){
          filterHtml({
            $: obj.$,
            dest: obj.dest,
            node: child,
            block: obj.block
          });
        }
      });
    }

    // BEGIN HERE
    ////////////////////////////////////////////////////////////////////////////

    // Iterate over all specified fi groups.
    this.files.forEach(function(f) {

      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).map(function(filepath) {
        // Read file source.
        return grunt.file.read(filepath);
      }).join(grunt.util.normalizelf(options.separator));

      var insertedBlocks = false;

      // For each block in the target...
      for (var blockName in options.blocks){
        var block = options.blocks[blockName];
        block.name = blockName;

        // Decide whether to fetch for resources...
        if (options.fetch_new) {
          mkdirp(block.local_path);
          grunt.log.writeln('Block \''+blockName+'\', fetch_new=true: checking CDN resources...');
          fetch_new(block);
        } else {
          grunt.log.writeln('Block \''+blockName+'\', fetch_new=false: not checking CDN resources.');
        }

        // Load the HTML file into Cheerio DOM parser
        var $ = cheerio.load(src);

        //Scan the DOM for places to switch CDN/Local resources
        filterHtml({
          $: $,
          dest: f.dest,
          node: $._root,
          block: block
        });

        // Flatten the DOM back to a string
        src = $.html();
        insertedBlocks = true;
      }

      // Write out the HTML string to the destination file
      if (insertedBlocks) {
        grunt.file.write(f.dest, src);
      }

      // Print a success message.
      grunt.log.writeln('File "' + f.dest + '" created.');

      done();
    });

  });

};<commit_msg>Better handling of done(), CDN, fetch_new and adding fetch_once.<commit_after>/*
 * grunt-cdn-switch
 * https://github.com/alistair/grunt-cdn-switch
 *
 * Copyright (c) 2015 Alistair MacDonald
 * Licensed under the MIT license.
 */

'use strict';

var Promise = require('bluebird')
  , cheerio = require('cheerio')
  , http = require('http')
  , fs = require('fs')
  , mkdirp = require('mkdirp')
  ;

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks
  grunt.registerMultiTask('cdn_switch', 'Insert switchable Script and Style tags into your HTML that automatically link to Local or CDN resources.', function() {

    var target = this.target;

    // Go async (fetching and waiting on remote servers)
    var done = this.async();

    // Reference options
    var options = this.options({
      punctuation: '.',
      separator: ', '
    });

    var mode = options.cdn ? 'CDN' : 'Local';

    function checkFileExists(file){
      var path = file.path;
      return new Promise(function(resolve, reject){
        fs.exists(path, function(exists) {

          resolve({
            path: path,
            origin: file.origin,
            exists: exists
          });

        });

      });
    }

    function checkFileModifiedDate(file){
      var path = file.path;

      return new Promise(function(resolve, reject){

        if (file.exists) {

          fs.stat(path, function(err, stats){
            resolve({
              path: path,
              origin: file.origin,
              modified: stats.mtime,
              exists: true
            });
          });

        } else {

          resolve({
            path: path,
            origin: file.origin,
            modified: null,
            exists: false
         });

        }
      });
    }

    // Request a new file from the server, handle date-modified, error and end
    // events. Don't fetch file if you already have it locally.
    function requestHandler(file){
      return new Promise(function(resolve, reject){

        var request = http.get(file.origin, function(response) {

          var localTime = new Date(file.modified).getTime()
            , remoteTime = new Date(response.headers['last-modified']).getTime()
            ;

          // If the remote file is newer than the local file...
          // Or the local file does not exist...
          if (remoteTime > localTime || !file.exists) {

            // Write the file.
            var local_file = fs.createWriteStream(file.path);
            response.pipe(local_file);

          // Duck out if there are HTTP Status code errors
          } else {
            request.end();
            resolve({
              notmodified: true,
              path: file.path
            });
          }

          // Duck out if there are HTTP Status code errors
          if (response.statusCode.toString()[0] === '4'){
            var error = {};
            error[response.statusCode] = file.url;
            reject(error);
          }

        // Handle other events
        }).on('error', function(e){
          reject(e);
        }).on('end', function(){
          resolve(file.origin);
        }).on('close', function(){
          resolve(file.origin);
        });

      });
    }

    // Begin the fetch and date-modified check for a single fetch promise
    function fetch(fetchobj){
      var block = fetchobj.block
      , filename = fetchobj.url.slice(fetchobj.url.lastIndexOf('/') + 1)
      , local_filepath = block.local_path + '/' + filename
      ;

      if (options.fetch_new) {
        grunt.log.writeln('Check: ' + fetchobj.url);
      } else if (options.fetch_once) {
        grunt.log.writeln('Check: ' + local_filepath);
      }

      return checkFileExists({
        path: local_filepath,
        origin: fetchobj.url
      })
      .then(checkFileModifiedDate)
      .then(requestHandler);
    }

    // Build a stack of promises based on the resource list
    function fetch_new (block) {
      return new Promise(function (resolve, reject) {

        var fetchPromises = [];

        // Create a promise for each fle
        block.resources.forEach(function(url){
          // Push the new promise onto the stack
          fetchPromises.push(fetch({
            block:block,
            url: url

          }).then(function (response){

            if (response.notmodified) {
              grunt.log.writeln('Nomod: ' + response.path);
            } else {
              grunt.log.writeln('Saved: ' + response);
            }
            return response.path;
          }));

          return fetchPromises;

        });

        // Wait until all the promises are resolved, then settle
        Promise.settle(fetchPromises).then(function(results){
          grunt.log.writeln('Done fetching/checking resources.');
          var errorCount = 0;

          // Log errors when things are not fetched...
          results.forEach(function(result){
            if (!result.isFulfilled()) {
              errorCount+=1;

              grunt.log.warn('Fetch Error in resources for block: \''+block.name+'\', in target \''+target+'\'.');
              try{
                console.log(result.reason());
              }catch(e){
                console.log(e);
              }
            }
          });

          // Count errors and notify user
          if (errorCount === 0) {
            var success_msg = '\''+block.name+'\' files checked-with/fetched-to: \''+block.local_path+'\'';
            grunt.log.ok(success_msg);
            resolve(success_msg);
          } else {
            var error_msg = 'CDN-Switch: Things did not go well for you :\'(';
            grunt.log.warn(error_msg);
            reject(error_msg);
          }
        });

      });
    }

    // Build HTML block with reource links pointing at CDN
    function buildHtmlBlockCDN(block){
      var parts = block.html.split('{{resource}}')
        , html = ''
        ;

      block.resources.forEach(function(resource){
        html += parts[0] + resource + parts[1] + '\n';
      });

      if (block.injections) {
        block.injections.forEach(function(injection){
          // html += parts[0] + injection + parts[1] + '\n';
          html += injection + '\n';
          return injection;
        });
      }

      // Remove trailling newline
      html = html.slice(0, html.length-1);
      return html;
    }

    // Build HTML block with reource links pointing to Local
    // versions of CDN files that were fetched
    function buildHtmlBlockLocal(block){
      var parts = block.html.split('{{resource}}')
        , html = ''
        ;

      block.resources.forEach(function(url){
        var filename = url.slice(url.lastIndexOf('/')+1);
        html += parts[0] + block.local_path+'/'+filename + parts[1] + '\n';
      });

      if (block.injections) {
        block.injections.forEach(function(injection){
          html += injection + '\n';
          // html += parts[0] + injection + parts[1] + '\n';
          return injection;
        });
      }

      // Remove trailling newline
      html = html.slice(0, html.length-1);
      return html;
    }

    // Filter HTML files in the Grunt files list
    function filterHtml(obj){
      obj.node.children.forEach(function(child){

        if (child.type === 'comment'){
          var splits = child.data.split('=');

          // Scan an HTML file for comment nodes that contain "cdn-switch"
          // and a target name for the grunt task.
          // Eg: <!--cdn-switch:tagert-name-->

          // When found...
          if (splits[0]==='cdn-switch' && splits[1]===obj.block.name) {

            // Build new HTML blockdepending on mode...
            var html = options.cdn ?
              buildHtmlBlockCDN(obj.block) :
              buildHtmlBlockLocal(obj.block) ;

            // Write new block into DOM and notify
            obj.$(child).replaceWith(html);

            grunt.log.ok(mode+' \''+obj.block.name+'\' comment block written to: \''+obj.dest+'\'');
          }
        }

        // If this node has children, recursively filter
        if (child.hasOwnProperty('children')){
          filterHtml({
            $: obj.$,
            dest: obj.dest,
            node: child,
            block: obj.block
          });
        }
      });
    }

    // BEGIN HERE
    ////////////////////////////////////////////////////////////////////////////

    // Iterate over all specified fi groups.
    this.files.forEach(function(f) {

      // Concat specified files.
      var src = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files (if nonull was set).
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).map(function(filepath) {
        // Read file source.
        return grunt.file.read(filepath);
      }).join(grunt.util.normalizelf(options.separator));

      function compileHTML (block, src) {
        // Load the HTML file into Cheerio DOM parser
        var $ = cheerio.load(src);

        //Scan the DOM for places to switch CDN/Local resources
        filterHtml({
          $: $,
          dest: f.dest,
          node: $._root,
          block: block
        });

        // Flatten the DOM back to a string
        src = $.html();

        insertedBlocks = true;

        return src;
      }

      var insertedBlocks = false
        , blockPromises = []
        ;

      // For each block in the target...
      for (var blockName in options.blocks){

        var block = options.blocks[blockName];
        block.name = blockName;
        mkdirp(block.local_path);

        // Decide whether to fetch for resources...
        if (options.fetch_new && !options.fetch_once) {
          grunt.log.writeln('Block: \''+blockName+'\', fetch_new: checking CDN resources:');
          blockPromises.push(fetch_new(block));

        } else if (options.fetch_once && !options.fetch_new) {
          grunt.log.writeln('Block: \''+blockName+'\', fetch_once: checking Local resources:');
          blockPromises.push(fetch_new(block));

        } else {
          grunt.log.writeln('Block: \''+blockName+'\', no_fetch: not checking resources.');
        }

        src = compileHTML(block, src);
      }

      Promise.settle(blockPromises).then(function () {

        // Write out the HTML string to the destination file
        if (insertedBlocks) {
          grunt.file.write(f.dest, src);
        }

        // Print a success message.
        grunt.log.writeln('File "' + f.dest + '" created.');

        done();
      });

    });

  });

};<|endoftext|>


<commit_before>module.exports = function(grunt) {
  var cf = require('pkgcloud'),
    path = require('path'),
    util = require('util'),
    _ = grunt.util._;

  _.mixin(require('underscore.deferred'));

  var cfAuth = {},
    client, cf_container_name, config, cfConfig;

  function stripComponents(path, num, sep) {
    if(sep === undefined) sep = '/';
    var aString = path.split(sep)
    if(aString.length <= num) {
      return aString[aString.length - 1];
    } else {
      aString.splice(0, num);
      return aString.join(sep);
    }
  }

  grunt.registerMultiTask('cloudfiles', 'Move stuff to the cloud', function() {
    var done = this.async(),
      errors = 0;

    config = this.data;

    client = cf.storage.createClient({
      'provider': 'rackspace',
      'username': config.user,
      'apiKey': config.key
    })

    var cfActivity = [];

   // _.when(cf_init()).done(function(init) {
      // grunt.log.debug(init + "\n  " + util.inspect(cfConfig));
      config.upload.forEach(function(upload) {
        grunt.log.subhead('Uploading into ' + upload.container);
        var files = grunt.file.expand(upload.src);

        files.forEach(function(file) {
          if (grunt.file.isFile(file)) {
            var ufile = file;
            if(upload.stripcomponents !== undefined) {
              ufile = stripComponents(ufile, upload.stripcomponents);
            }
            cfActivity.push(cf_addFile(upload.container, file, ufile));
          }
        })
      });

      var total = cfActivity.length;
      var errors = 0;

      cfActivity.forEach(function(activity) {
        activity.done(function(msg) {});
        activity.fail(function(msg) {
          grunt.log.error(msg);
          ++errors;
        });
        activity.always(function() {
          // If this was the last transfer to complete, we're all done.
          if(--total === 0) {
            grunt.log.write('Finished uploading ' + cfActivity.length + ' item(s)')
            done(!errors);
          }
        });
      });
    //}).fail(function(err) {
    //  grunt.log.error('Error with intiallization of Cloudfiles ::\n\t' + err);
    //});

  });

  function cf_init() {
    var dfd = _.Deferred();
    var async

    grunt.log.debug('Authenticating on Cloudfiles');
    client.setAuth(function(err, res, config) {
      if(err) {
        dfd.reject(err);
      } else {
        cfConfig = config;
        dfd.resolve('Authentication Complete');
      }
    });

    return dfd;
  }

  function cf_addFile(container, src, dest) {
    grunt.log.debug('Starting an upload');
    var dfd = _.Deferred();

    client.upload({
      'container': container,
      'remote': dest,
      'local': src
    }, function(err, uploaded, res) {
      if(err) {
        dfd.reject(err);
      } else {
        dfd.resolve(uploaded);
      }
    });

    return dfd;
  }
}
<commit_msg>allow and upload to specificy a folder to upload into<commit_after>module.exports = function(grunt) {
  var cf = require('pkgcloud'),
    path = require('path'),
    util = require('util'),
    _ = grunt.util._;

  _.mixin(require('underscore.deferred'));

  var cfAuth = {},
    client, cf_container_name, config, cfConfig;

  function stripComponents(path, num, sep) {
    if(sep === undefined) sep = '/';
    var aString = path.split(sep)
    if(aString.length <= num) {
      return aString[aString.length - 1];
    } else {
      aString.splice(0, num);
      return aString.join(sep);
    }
  }

  grunt.registerMultiTask('cloudfiles', 'Move stuff to the cloud', function() {
    var done = this.async(),
      errors = 0;

    config = this.data;

    client = cf.storage.createClient({
      'provider': 'rackspace',
      'username': config.user,
      'apiKey': config.key
    })

    var cfActivity = [];

   // _.when(cf_init()).done(function(init) {
      // grunt.log.debug(init + "\n  " + util.inspect(cfConfig));
      config.upload.forEach(function(upload) {
        grunt.log.subhead('Uploading into ' + upload.container);
        var files = grunt.file.expand(upload.src);

        if (upload.dest === undefined) { upload.dest = '' }

        files.forEach(function(file) {
          if (grunt.file.isFile(file)) {
            var ufile = file;
            if(upload.stripcomponents !== undefined) {
              ufile = stripComponents(ufile, upload.stripcomponents);
            }
            cfActivity.push(cf_addFile(upload.container, file, upload.dest + ufile));
          }
        })
      });

      var total = cfActivity.length;
      var errors = 0;

      cfActivity.forEach(function(activity) {
        activity.done(function(msg) {});
        activity.fail(function(msg) {
          grunt.log.error(msg);
          ++errors;
        });
        activity.always(function() {
          // If this was the last transfer to complete, we're all done.
          if(--total === 0) {
            grunt.log.write('Finished uploading ' + cfActivity.length + ' item(s)')
            done(!errors);
          }
        });
      });
    //}).fail(function(err) {
    //  grunt.log.error('Error with intiallization of Cloudfiles ::\n\t' + err);
    //});

  });

  function cf_init() {
    var dfd = _.Deferred();
    var async

    grunt.log.debug('Authenticating on Cloudfiles');
    client.setAuth(function(err, res, config) {
      if(err) {
        dfd.reject(err);
      } else {
        cfConfig = config;
        dfd.resolve('Authentication Complete');
      }
    });

    return dfd;
  }

  function cf_addFile(container, src, dest) {
    grunt.log.debug('Starting an upload');
    var dfd = _.Deferred();

    client.upload({
      'container': container,
      'remote': dest,
      'local': src
    }, function(err, uploaded, res) {
      if(err) {
        dfd.reject(err);
      } else {
        dfd.resolve(uploaded);
      }
    });

    return dfd;
  }
}
<|endoftext|>


<commit_before>var assert = require("../util/assert");

suite("astMatch", function() {
  test("variable binding", function() {
    assert.astMatch(
      "(function(a, b) { console.log(a + b); })(1, 3);",
      "(function(__AMDCLEAN0__,   __AMDCLEAN1__)  {" +
        "console.log(__AMDCLEAN0__ + __AMDCLEAN1__);    " +
      "}) (1,3);"
    );
  });

  suite("expected failures", function() {
    var astMatchFail = function(inputSrc, expectedSrc) {
      assert.throws(function() {
        assert.astMatch(inputSrc, expectedSrc);
      });
    };

    test("name change", function() {
      astMatchFail("(function(a) {});", "(function(b) {});");
    });

    test("double binding", function() {
      astMatchFail(
        "(function(a, b) { console.log(a); });",
        "(function(__AMDCLEAN0__, __AMDCLEAN1__) { console.log(__AMDCLEAN1__); });"
      );
    });
  });
});
<commit_msg>Ensure that parenthesis placement for IIFEs is lax<commit_after>var assert = require("../util/assert");

suite("astMatch", function() {
  test("variable binding", function() {
    assert.astMatch(
      "(function(a, b) { console.log(a + b); })(1, 3);",
      "(function(__AMDCLEAN0__,   __AMDCLEAN1__)  {" +
        "console.log(__AMDCLEAN0__ + __AMDCLEAN1__);    " +
      "}) (1,3);"
    );
  });

  test("lax IIFE parenthesis placement", function() {
    assert.astMatch(
      "(function() {}());",
      "(function() {})();"
    );
  });

  suite("expected failures", function() {
    var astMatchFail = function(inputSrc, expectedSrc) {
      assert.throws(function() {
        assert.astMatch(inputSrc, expectedSrc);
      });
    };

    test("name change", function() {
      astMatchFail("(function(a) {});", "(function(b) {});");
    });

    test("double binding", function() {
      astMatchFail(
        "(function(a, b) { console.log(a); });",
        "(function(__AMDCLEAN0__, __AMDCLEAN1__) { console.log(__AMDCLEAN1__); });"
      );
    });
  });
});
<|endoftext|>


<commit_before>/*
 * grunt-require-gettext
 * https://github.com/open-xchange-frontend/grunt-require-gettext
 *
 * Copyright (c) 2014 Julian Bäume
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {
    var esprima = require('esprima');
    var _ = require('lodash');
    var getComment = require('../lib/comments.js').getComment;

    function extractStrings(fileName) {
        function walkTree(node, fn) {
            fn(node);

            for (var key in node) {
                var obj = node[key];
                if (typeof obj === 'object') {
                    walkTree(obj, fn);
                }
            }
        }

        function tryEval(code) {
            var val;
            try {
                val = eval(code);
            } catch (e) {
                grunt.verbose.warn(e + ' - while statically evaluating code: ' + code);
            }
            return val;
        }

        var code = grunt.file.read(fileName);
        var syntax = esprima.parse(code, {comment: true, loc: true, tokens: true, range: true});
        var items;
        var handleGtCall = function (node, gtName, module) {
            if (node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.name === gtName &&
                node['arguments'] !== null &&
                node['arguments'].length
            ) {
                var msgId = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                if (!msgId) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgId: msgId.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            } else if (
                node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object.name === gtName &&
                node.callee.property.name === 'pgettext' &&
                node['arguments'] !== null &&
                node['arguments'].length === 2
            ) {
                var msgId = node['arguments'][1].value || tryEval(code.slice(node['arguments'][1].range[0], node['arguments'][1].range[1]));
                var msgContext = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                if (!msgId || !msgContext) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgId: msgId.trim(),
                    msgContext: msgContext.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            } else if (
                node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object.name === gtName &&
                node.callee.property.name === 'ngettext' &&
                node['arguments'] !== null &&
                node['arguments'].length === 3
            ) {
                var msgId = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                var msgIdPlural = node['arguments'][1].value || tryEval(code.slice(node['arguments'][1].range[0], node['arguments'][1].range[1]));
                if (!msgId || !msgIdPlural || !node['arguments'][2]) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node  in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgId: msgId.trim(),
                    msgIdPlural: msgIdPlural.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            } else if (
                node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object.name === gtName &&
                node.callee.property.name === 'npgettext' &&
                node['arguments'] !== null &&
                node['arguments'].length === 4
            ) {
                var msgContext = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                var msgId = node['arguments'][1].value || tryEval(code.slice(node['arguments'][1].range[0], node['arguments'][1].range[1]));
                var msgIdPlural = node['arguments'][2].value || tryEval(code.slice(node['arguments'][2].range[0], node['arguments'][2].range[1]));
                if (!msgContext || !msgId || !msgIdPlural || !node['arguments'][3]) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgContext: msgContext.trim(),
                    msgId: msgId.trim(),
                    msgIdPlural: msgIdPlural.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            }
        };

        walkTree(syntax, function (node) {
            if (node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.name === 'define' &&
                node['arguments'] !== null &&
                node['arguments'].length > 2)
            {
                node['arguments'][1].elements.map(function (el, index) {
                    if (el.value.substr(0, 8) === 'gettext!') {
                        var param = node['arguments'][2].params[index];
                        if (!param) {
                            grunt.log.warn('Unused require-gettext module call in', fileName);
                            return;
                        }
                        return {
                            name: param.name,
                            module: el.value.substr(8)
                        };
                    }
                }).filter(function (arg) {
                    return arg !== undefined;
                }).forEach(function (obj) {
                    var gtName = obj.name;
                    var module = obj.module;

                    if (node['arguments'][2].type === 'FunctionExpression') {
                        walkTree(node['arguments'][2], function (node) {
                            handleGtCall(node, gtName, module);
                        });
                    }
                });
            } else if (node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object !== null &&
                node.callee.object.name === 'define' &&
                node.callee.property.name === 'async' &&
                node['arguments'] !== null &&
                node['arguments'].length > 2)
            {
                node['arguments'][1].elements.map(function (el, index) {
                    if (el.value.substr(0, 8) === 'gettext!') {
                        var param = node['arguments'][2].params[index];
                        if (!param) {
                            grunt.log.warn('Unused require-gettext module call in', fileName);
                            return;
                        }
                        return {
                            name: param.name,
                            module: el.value.substr(8)
                        };
                    }
                }).filter(function (arg) {
                    return arg !== undefined;
                }).forEach(function (obj) {
                    var gtName = obj.name;
                    var module = obj.module;

                    if (node['arguments'][2].type === 'FunctionExpression') {
                        walkTree(node['arguments'][2], function (node) {
                            handleGtCall(node, gtName, module);
                        });
                    }
                });
            }
        });
        return items;
    }

    grunt.registerMultiTask('create_pot', 'Extract calls to gettext that is used with a requirejs gettext module.', function () {
        var PO = require('pofile');
        var options = this.options();

        this.files.forEach(function (file) {
            var poItems;

            poItems = file.src.filter(function (srcFile) {
                return srcFile.substr(-3) === '.js';
            }).map(function (srcFile) {
                return {srcFile: srcFile, items: extractStrings(srcFile)};
            }).reduce(function (acc, result) {
                if (!acc) {
                    return;
                }
                var items = result.items;
                if (!items) {
                    items = [];
                    grunt.log.debug('No strings extracted from file ' + result.srcFile);
                }
                items.forEach(function (item) {
                    var key = item.msgId;
                    if (item.msgContext) {
                        key += '_' + item.msgContext;
                    }
                    if (!acc[key]) {
                        acc[key] = new PO.Item();
                    }
                    var poItem = acc[key];
                    poItem.msgid = item.msgId;
                    poItem.msgid_plural = item.msgIdPlural;
                    poItem.msgctxt = item.msgContext;
                    if (poItem.references.indexOf(item.fileName + ':' + item.line) < 0) {
                        poItem.references.push(item.fileName + ':' + item.line);
                    }
                    if (poItem.references.indexOf('module:' + item.module) < 0) {
                        poItem.references.push('module:' + item.module);
                    }
                    if (poItem.msgid_plural) {
                        //FIXME: may be, this should be handled by pofile library
                        poItem.msgstr = ['', ''];
                    }
                    if (item.comment) {
                        var commentItem = PO.parse('msgid ""\nmsgstr ""\n\n' + item.comment + '\nmsgid "temp"\nmsgstr""\n').items[0];
                        _(poItem.flags).extend(commentItem.flags);
                        poItem.extractedComments = _.uniq([].concat(poItem.extractedComments, commentItem.extractedComments));
                    }
                });
                return acc;
            }, {});

            if (poItems) {
                var catalog = new PO();
                for (var key in poItems) {
                    catalog.items.push(poItems[key]);
                }
                if (options.headers) {
                    grunt.verbose.writeln('Writing custom headers: ' + JSON.stringify(options.headers, null, 4));
                }
                catalog.headers = options.headers || {
                    'Content-Type': 'text/plain; charset=UTF-8',
                    'Content-Transfer-Encoding': '8bit'
                };
                grunt.file.write(file.dest, catalog.toString());
            }
        });
    });
};
<commit_msg>be more DRY<commit_after>/*
 * grunt-require-gettext
 * https://github.com/open-xchange-frontend/grunt-require-gettext
 *
 * Copyright (c) 2014 Julian Bäume
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {
    var esprima = require('esprima');
    var _ = require('lodash');
    var getComment = require('../lib/comments.js').getComment;

    function extractStrings(fileName) {
        function walkTree(node, fn) {
            fn(node);

            for (var key in node) {
                var obj = node[key];
                if (typeof obj === 'object') {
                    walkTree(obj, fn);
                }
            }
        }

        function tryEval(code) {
            var val;
            try {
                val = eval(code);
            } catch (e) {
                grunt.verbose.warn(e + ' - while statically evaluating code: ' + code);
            }
            return val;
        }

        var code = grunt.file.read(fileName);
        var syntax = esprima.parse(code, {comment: true, loc: true, tokens: true, range: true});
        var items;
        var handleGtCall = function (node, gtName, module) {
            if (node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.name === gtName &&
                node['arguments'] !== null &&
                node['arguments'].length
            ) {
                var msgId = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                if (!msgId) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgId: msgId.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            } else if (
                node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object.name === gtName &&
                node.callee.property.name === 'pgettext' &&
                node['arguments'] !== null &&
                node['arguments'].length === 2
            ) {
                var msgId = node['arguments'][1].value || tryEval(code.slice(node['arguments'][1].range[0], node['arguments'][1].range[1]));
                var msgContext = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                if (!msgId || !msgContext) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgId: msgId.trim(),
                    msgContext: msgContext.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            } else if (
                node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object.name === gtName &&
                node.callee.property.name === 'ngettext' &&
                node['arguments'] !== null &&
                node['arguments'].length === 3
            ) {
                var msgId = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                var msgIdPlural = node['arguments'][1].value || tryEval(code.slice(node['arguments'][1].range[0], node['arguments'][1].range[1]));
                if (!msgId || !msgIdPlural || !node['arguments'][2]) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node  in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgId: msgId.trim(),
                    msgIdPlural: msgIdPlural.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            } else if (
                node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                node.callee.type === 'MemberExpression' &&
                node.callee.object.name === gtName &&
                node.callee.property.name === 'npgettext' &&
                node['arguments'] !== null &&
                node['arguments'].length === 4
            ) {
                var msgContext = node['arguments'][0].value || tryEval(code.slice(node['arguments'][0].range[0], node['arguments'][0].range[1]));
                var msgId = node['arguments'][1].value || tryEval(code.slice(node['arguments'][1].range[0], node['arguments'][1].range[1]));
                var msgIdPlural = node['arguments'][2].value || tryEval(code.slice(node['arguments'][2].range[0], node['arguments'][2].range[1]));
                if (!msgContext || !msgId || !msgIdPlural || !node['arguments'][3]) {
                    if (getComment(syntax, node).indexOf('#, dynamic') >= 0) {
                        grunt.verbose.warn('Ignoring gt.pgettext call with dynamic flag set.');
                        return;
                    }
                    grunt.verbose.warn(JSON.stringify(node['arguments'], null, 4));
                    grunt.log.error('Override this by adding a "dynamic" flag to the translator comments');
                    grunt.fail.warn('Could not read node in file: ' + fileName + ' use --verbose for more info');
                    return;
                }
                items = items || [];
                items.push({
                    msgContext: msgContext.trim(),
                    msgId: msgId.trim(),
                    msgIdPlural: msgIdPlural.trim(),
                    module: module,
                    fileName: fileName,
                    line: node.loc.start.line,
                    comment: getComment(syntax, node)
                });
            }
        };

        walkTree(syntax, function (node) {
            if (node !== null &&
                node.type === 'CallExpression' &&
                node.callee !== null &&
                (node.callee.name === 'define' ||
                (node.callee.type === 'MemberExpression' &&
                node.callee.object !== null &&
                node.callee.object.name === 'define' &&
                node.callee.property.name === 'async')) &&
                node['arguments'] !== null &&
                node['arguments'].length > 2)
            {
                node['arguments'][1].elements.map(function (el, index) {
                    if (el.value.substr(0, 8) === 'gettext!') {
                        var param = node['arguments'][2].params[index];
                        if (!param) {
                            grunt.log.warn('Unused require-gettext module call in', fileName);
                            return;
                        }
                        return {
                            name: param.name,
                            module: el.value.substr(8)
                        };
                    }
                }).filter(function (arg) {
                    return arg !== undefined;
                }).forEach(function (obj) {
                    var gtName = obj.name;
                    var module = obj.module;

                    if (node['arguments'][2].type === 'FunctionExpression') {
                        walkTree(node['arguments'][2], function (node) {
                            handleGtCall(node, gtName, module);
                        });
                    }
                });
            }
        });
        return items;
    }

    grunt.registerMultiTask('create_pot', 'Extract calls to gettext that is used with a requirejs gettext module.', function () {
        var PO = require('pofile');
        var options = this.options();

        this.files.forEach(function (file) {
            var poItems;

            poItems = file.src.filter(function (srcFile) {
                return srcFile.substr(-3) === '.js';
            }).map(function (srcFile) {
                return {srcFile: srcFile, items: extractStrings(srcFile)};
            }).reduce(function (acc, result) {
                if (!acc) {
                    return;
                }
                var items = result.items;
                if (!items) {
                    items = [];
                    grunt.log.debug('No strings extracted from file ' + result.srcFile);
                }
                items.forEach(function (item) {
                    var key = item.msgId;
                    if (item.msgContext) {
                        key += '_' + item.msgContext;
                    }
                    if (!acc[key]) {
                        acc[key] = new PO.Item();
                    }
                    var poItem = acc[key];
                    poItem.msgid = item.msgId;
                    poItem.msgid_plural = item.msgIdPlural;
                    poItem.msgctxt = item.msgContext;
                    if (poItem.references.indexOf(item.fileName + ':' + item.line) < 0) {
                        poItem.references.push(item.fileName + ':' + item.line);
                    }
                    if (poItem.references.indexOf('module:' + item.module) < 0) {
                        poItem.references.push('module:' + item.module);
                    }
                    if (poItem.msgid_plural) {
                        //FIXME: may be, this should be handled by pofile library
                        poItem.msgstr = ['', ''];
                    }
                    if (item.comment) {
                        var commentItem = PO.parse('msgid ""\nmsgstr ""\n\n' + item.comment + '\nmsgid "temp"\nmsgstr""\n').items[0];
                        _(poItem.flags).extend(commentItem.flags);
                        poItem.extractedComments = _.uniq([].concat(poItem.extractedComments, commentItem.extractedComments));
                    }
                });
                return acc;
            }, {});

            if (poItems) {
                var catalog = new PO();
                for (var key in poItems) {
                    catalog.items.push(poItems[key]);
                }
                if (options.headers) {
                    grunt.verbose.writeln('Writing custom headers: ' + JSON.stringify(options.headers, null, 4));
                }
                catalog.headers = options.headers || {
                    'Content-Type': 'text/plain; charset=UTF-8',
                    'Content-Transfer-Encoding': '8bit'
                };
                grunt.file.write(file.dest, catalog.toString());
            }
        });
    });
};
<|endoftext|>


<commit_before>/***********************************************
 * This is a task to cross-build our extensions
 * from 'one' common source code
 */

const fs = require('fs-extra');

const extPath = process.cwd() + "/extensions";

/***********************************************
 * Create our Chrome and Firefox folders if they
 * don't exist already
 */
[ 'Chrome',
  'Chrome/icons',
  'Chrome/scripts',
  'Firefox',
  'Firefox/icons',
  'Firefox/scripts'
].forEach(function(dir){
  fs.ensureDir(`${extPath}/${dir}`, function (err) {
    console.log(err); // => null
  });
});

function copyCommonStatic(what) {
  ['Chrome','Firefox'].forEach(function(dir){
    fs.copySync(
        `${extPath}/common/${what}`,
        `${extPath}/${dir}/`,
        function (err) {
          if (err) { return console.error(err); }
          console.log(`Success copying ${what} to ${dir} folder`);
        }
      );
  });
}

/**********************************************
 * First, copy static files from common into
 * both the Chrome and Firefox folder
 */

console.log('Copying subfolders to each build destination (/Chrome and /Firefox)');
copyCommonStatic('icons');
copyCommonStatic('scripts');

/**********************************************
 * Make Manifest.json for each browser
 */

function parseJSONfile(filename) {
  var jsonfile = extPath + "/common/"+ filename;
  var obj = {};

  try {
    obj = JSON.parse(fs.readFileSync(jsonfile, 'utf8'));
  } catch (e) {
    console.log ("Error in file: " + jsonfile);
    console.log(e + "\n");
  }

  return obj;
}

function combine(obj1, obj2, dest) {
  var finalObj = Object.assign(obj1, obj2);
  var fileContents = JSON.stringify(finalObj, null, 2);
  fs.writeFileSync(extPath + "/"+ dest + "/manifest.json", fileContents);
}

console.log("Parsing manifest files and building to appropriate folder");
var mCore = parseJSONfile("manifest.core.json");
var mChrome = parseJSONfile("manifest.chrome.json");
var mFF = parseJSONfile("manifest.firefox.json");
combine(mCore, mChrome, "Chrome");
combine(mCore, mFF, "Firefox");<commit_msg>forgot to use a sync func<commit_after>/***********************************************
 * This is a task to cross-build our extensions
 * from 'one' common source code
 */

const fs = require('fs-extra');

const extPath = process.cwd() + "/extensions";

/***********************************************
 * Create our Chrome and Firefox folders if they
 * don't exist already
 */
[ 'Chrome','Firefox'].forEach(function(dir){
  fs.ensureDirSync(`${extPath}/${dir}`, function (err) {
    if (err) { return console.error(err); }
  });
});

function copyCommonStatic(what) {
  ['Chrome','Firefox'].forEach(function(dir){
    fs.copy(
      `${extPath}/common/${what}`,
      `${extPath}/${dir}/${what}`,
      function (err) {
        if (err) { return console.error(err); }
        console.log(`Success copying ${what} to ${dir} folder`);
      }
    );
  });
}

/**********************************************
 * First, copy static files from common into
 * both the Chrome and Firefox folder
 */

console.log('Copying subfolders to each build destination (/Chrome and /Firefox)');
copyCommonStatic('icons');
copyCommonStatic('scripts');

/**********************************************
 * Make Manifest.json for each browser
 */

function parseJSONfile(filename) {
  var jsonfile = extPath + "/common/"+ filename;
  var obj = {};

  try {
    obj = JSON.parse(fs.readFileSync(jsonfile, 'utf8'));
  } catch (e) {
    console.log ("Error in file: " + jsonfile);
    console.log(e + "\n");
  }

  return obj;
}

function combine(obj1, obj2, dest) {
  var finalObj = Object.assign(obj1, obj2);
  var fileContents = JSON.stringify(finalObj, null, 2);
  fs.writeFileSync(extPath + "/"+ dest + "/manifest.json", fileContents);
}

console.log("Parsing manifest files and building to appropriate folder");
var mCore = parseJSONfile("manifest.core.json");
var mChrome = parseJSONfile("manifest.chrome.json");
var mFF = parseJSONfile("manifest.firefox.json");
combine(mCore, mChrome, "Chrome");
combine(mCore, mFF, "Firefox");<|endoftext|>


<commit_before>define(['jquery'], function ($) {

  var fileLoader = function() {
      var _name = "fileLoader";
      this.getName = function() {
        return _name;
      }

      this.handleFileSelect = function(event){
        var files = event.target.files;
        console.log('File with track successfully loaded: '+files[0].name);
        //TODO parse tcx and use osm service to draw route
      }

      if (window.File && window.FileReader && window.FileList && window.Blob) {
        // Great success! All the File APIs are supported.
        console.log("File API supported");
      } else {
        alert('The File APIs are not fully supported in this browser.');
      }

      this.registerTrackFileLoadEvenHandler = function(fileLoaderInputId){

          var input = $('#'+fileLoaderInputId);
          if(input.size()==1){
            input[0].addEventListener('change', this.handleFileSelect, false);
          }else{
            console.log(fileLoaderInputId+' element not found');
          }

      }
  };

  return fileLoader;

});
<commit_msg>loaded track converted from string to xml<commit_after>define(['jquery'], function ($) {

  var fileLoader = function() {
      var _name = "fileLoader";
      this.getName = function() {
        return _name;
      }

      this.handleFileSelect = function(event){
        var files = event.target.files;
        console.log('File with track successfully loaded: '+files[0].name);
        var reader = new FileReader();
        reader.onload = function(e){
            console.log(e.target.result);
            var xml = $(e.target.result);

            //TODO use parser to extract trackpoints

        }
        reader.readAsText(files[0]);

      }

      if (window.File && window.FileReader && window.FileList && window.Blob) {
        // Great success! All the File APIs are supported.
        console.log("File API supported");
      } else {
        alert('The File APIs are not fully supported in this browser.');
      }

      this.registerTrackFileLoadEvenHandler = function(fileLoaderInputId){

          var input = $('#'+fileLoaderInputId);
          if(input.size()==1){
            input[0].addEventListener('change', this.handleFileSelect, false);
          }else{
            console.log(fileLoaderInputId+' element not found');
          }

      }
  };

  return fileLoader;

});
<|endoftext|>


<commit_before>const MongoClient = require('mongodb').MongoClient
const Telegraf = require('telegraf')
const env = require('./env.json')

var plotly = require('plotly')(env.plotly.username, env.plotly.token)
var fs = require('fs')

const app = new Telegraf(env.TOKEN)

// UTILITY FUNCTIONS
function storeBP(_id, _datetime, _sys, _dist) {
        MongoClient.connect('mongodb://localhost/bp', function (err, db) {

                if (err) throw err

                db.collection("data").insertOne({
			id: _id,
			datetime: _datetime,
			sys: _sys,
			dist: _dist
		})
        })
}

function validBP(sys, dist) {

  if (sys < 50 || sys > 300 || dist < 20 || dist > 150) {
    return false
  }

  return true
}

function getBPs(id, success, failure) {
   MongoClient.connect('mongodb://localhost/bp', function (err, db) {
      if (err) {
         failure()
         return
      }

      db.collection("data").find({id: id}).toArray((err, res) => {

      if (err) {
         failure()
         return
      }

      success(res)

     db.close()
     })
   })

}

// COMMANDS AND RESPONSES

// HI
const hiEmojiArray = ["👏", "👌", "👋", "🙌", "✌", "✋", "🖖", "🤗"]
app.hears(/^hi$/i, (ctx) => ctx.reply("Hey there! " + hiEmojiArray[parseInt((Date.now()/1000) % hiEmojiArray.length)] ))

// RULE BP ALONE (ASSUMES DATE AND TIME)
const getBP = /^[0-9.]+ [0-9.]+/i

// LISTEN BP
app.hears(getBP, ctx => {

  console.log(ctx.message)

  const tokens = ctx.message.text.split(/\s+/)

  var sys = parseFloat(tokens[0])
  var dist = parseFloat(tokens[1])
  var datetime = new Date(parseInt(ctx.message.date) * 1000)
  var id = ctx.message.from.id

  if (sys < dist) {
    var temp = sys
    sys = dist
    dist = temp
  }

  if (validBP(sys, dist)) {
    ctx.reply('Thank you for providing your BP readings')
    ctx.reply('You have entered ' + sys + '/' + dist)
    storeBP(id, datetime, sys, dist)
  } else {
    ctx.reply('It seems like you have entered an invalid BP reading. Try again.')
  }
})

// RULE BP WITH DATE
const getBP_date = /^[0-9.]+ [0-9.]+ [0-9.]+\/[0-9.]+\/[0-9.]+/i

// LISTEN BP WITH DATE
app.hears(getBP_date, ctx => {

  console.log(ctx.message)

  const tokens = ctx.message.text.split(/\s+/)

  var sys = parseFloat(tokens[0])
  var dist = parseFloat(tokens[1])
  var datetime = new Date(tokens[2])
  var id = ctx.message.from.id

  if (sys < dist) {
    var temp = sys
    sys = dist
    dist = temp
  }

  if (validBP(sys, dist)) {
    ctx.reply('Thank you for providing your BP readings')
    ctx.reply('You have entered ' + sys + '/' + dist)
    storeBP(id, datetime, sys, dist)
  } else {
    ctx.reply('It seems like you have entered an invalid BP reading. Try again.')
  }
})

// RULE BP WITH DATE
const getBP_date_time = /^[0-9.]+ [0-9.]+ [0-9.]+\/[0-9.]+\/[0-9.]+ [0-9.]+:+[0-9.]+/i

// LISTEN BP WITH DATE
app.hears(getBP_date_time, ctx => {

  console.log(ctx.message)

  const tokens = ctx.message.text.split(/\s+/)

  var sys = parseFloat(tokens[0])
  var dist = parseFloat(tokens[1])
  var datetime = new Date(tokens[2] + " " + tokens[3])
  var id = ctx.message.from.id

  if (sys < dist) {
    var temp = sys
    sys = dist
    dist = temp
  }

  if (validBP(sys, dist)) {
    ctx.reply('Thank you for providing your BP readings')
    ctx.reply('You have entered ' + sys + '/' + dist)
    storeBP(id, datetime, sys, dist)
  } else {
    ctx.reply('It seems like you have entered an invalid BP reading. Try again.')
  }
})

// HISTORY
app.command('/history', (ctx) => {

   getBPs(ctx.message.from.id,
   (res)=>{
      const strings = res.map((e) => e.datetime.toLocaleString('en-GB') + " " + e.sys + "/" + e.dist)

      if (typeof(strings) == 'Object') {
         ctx.reply(strings)
      } else {
         console.log(strings)
         const stringList = strings.join("\n")
         ctx.reply(stringList)
      }
   },
   () => {
      console.log("Error occurred")
   })
})

// GRAPH
app.command('/graph', (ctx) => {

   getBPs(ctx.message.from.id,
   (res)=>{
      const x = res.map((e) => e.datetime)
      const sys = res.map((e) => e.sys)
      const dist = res.map((e) => e.dist)

      var trace1 = {
          x: x,
          y: sys,
          type: "scatter",
          name: "Systolic"
      }

      var trace2 = {
          x: x,
          y: dist,
          type: "scatter",
          name: "Diastolic"
      }

      var layout = {
         title: "Blood pressure values",
         xaxis: {title: "Date"},
         yaxis: {title: "BP [mmHg]"}
      }

      var figure = { data: [trace1, trace2], layout: layout }

      var imgOpts = {
          format: 'png',
          width: 1000,
          height: 500
      }

     plotly.getImage(figure, imgOpts, function (error, imageStream) {
        if (error) return console.log (error)
        const nameImg = ctx.message.from.id + "-" + Date.now() + ".png"

        ctx.replyWithPhoto({source: imageStream})

     })

   },
   () => {
      console.log("Error occurred")
   })

})

// START COMMAND
app.command('start', (ctx) => {
   ctx.reply("Hello. Thank you for joining. ☺\n"+
   "You can send me new blood pressure readings directly as numbers.\n"+
   "For example, if you need to send 120 Systolic and 60 Diastolic, you can send:\n"+
   "120 60⏎\n\n"+
   "I will store that for you and eventually provide you with the history of your values as graph or list.\n"+
   "You can request these using the two buttons provided (/graph and /history).",
   Telegraf.Extra.markup((markup) => {return markup.keyboard(['/graph', '/history'])}))
})

// HELP COMMAND
const seekHelp = /^[help|\?]/i
app.hears(seekHelp, (ctx) => {
   ctx.reply("Hello, here is some help:\n"+
   "You can send me new blood pressure readings directly as numbers.\n"+
   "For example, if you need to send 120 Systolic and 60 Diastolic, you can send:\n"+
   "120 60⏎\n\n"+
   "I will store that for you and eventually provide you with the history of your values as graph or list.\n"+
   "You can request these using the two buttons provided (/graph and /history).",
   Telegraf.Extra.markup((markup) => {return markup.keyboard(['/graph', '/history'])}))
})

// IN CASE OF STICKERS
app.on('sticker', (ctx) => ctx.reply('Thank you for the sticker 👍'))

// STARTING THE APP
app.startPolling()
<commit_msg>Changed the regexes<commit_after>const MongoClient = require('mongodb').MongoClient
const Telegraf = require('telegraf')
const env = require('./env.json')

var plotly = require('plotly')(env.plotly.username, env.plotly.token)
var fs = require('fs')

const app = new Telegraf(env.TOKEN)

// UTILITY FUNCTIONS
function storeBP(_id, _datetime, _sys, _dist) {
        MongoClient.connect('mongodb://localhost/bp', function (err, db) {

                if (err) throw err

                db.collection("data").insertOne({
			id: _id,
			datetime: _datetime,
			sys: _sys,
			dist: _dist
		})
        })
}

function validBP(sys, dist) {

  if (sys < 50 || sys > 300 || dist < 20 || dist > 150) {
    return false
  }

  return true
}

function getBPs(id, success, failure) {
   MongoClient.connect('mongodb://localhost/bp', function (err, db) {
      if (err) {
         failure()
         return
      }

      db.collection("data").find({id: id}).toArray((err, res) => {

      if (err) {
         failure()
         return
      }

      success(res)

     db.close()
     })
   })

}

// COMMANDS AND RESPONSES

// HI
const hiEmojiArray = ["👏", "👌", "👋", "🙌", "✌", "✋", "🖖", "🤗"]
app.hears(/^hi$/i, (ctx) => ctx.reply("Hey there! " + hiEmojiArray[parseInt((Date.now()/1000) % hiEmojiArray.length)] ))

// RULE BP ALONE (ASSUMES DATE AND TIME)
const getBP = /^[0-9.]+ [0-9.]+$/i

// LISTEN BP
app.hears(getBP, ctx => {

  console.log(ctx.message)

  const tokens = ctx.message.text.split(/\s+/)

  var sys = parseFloat(tokens[0])
  var dist = parseFloat(tokens[1])
  var datetime = new Date(parseInt(ctx.message.date) * 1000)
  var id = ctx.message.from.id

  if (sys < dist) {
    var temp = sys
    sys = dist
    dist = temp
  }

  if (validBP(sys, dist)) {
    ctx.reply('Thank you for providing your BP readings')
    ctx.reply('You have entered ' + sys + '/' + dist)
    storeBP(id, datetime, sys, dist)
  } else {
    ctx.reply('It seems like you have entered an invalid BP reading. Try again.')
  }
})

// RULE BP WITH DATE
const getBP_date = /^[0-9.]+ [0-9.]+ [0-9.]+\/[0-9.]+\/[0-9.]+$/i

// LISTEN BP WITH DATE
app.hears(getBP_date, ctx => {

  console.log(ctx.message)

  const tokens = ctx.message.text.split(/\s+/)

  var sys = parseFloat(tokens[0])
  var dist = parseFloat(tokens[1])
  var datetime = new Date(tokens[2])
  var id = ctx.message.from.id

  if (sys < dist) {
    var temp = sys
    sys = dist
    dist = temp
  }

  if (validBP(sys, dist)) {
    ctx.reply('Thank you for providing your BP readings')
    ctx.reply('You have entered ' + sys + '/' + dist)
    storeBP(id, datetime, sys, dist)
  } else {
    ctx.reply('It seems like you have entered an invalid BP reading. Try again.')
  }
})

// RULE BP WITH DATE
const getBP_date_time = /^[0-9.]+ [0-9.]+ [0-9.]+\/[0-9.]+\/[0-9.]+ [0-9.]+:+[0-9.]+$/i

// LISTEN BP WITH DATE
app.hears(getBP_date_time, ctx => {

  console.log(ctx.message)

  const tokens = ctx.message.text.split(/\s+/)

  var sys = parseFloat(tokens[0])
  var dist = parseFloat(tokens[1])
  var datetime = new Date(tokens[2] + " " + tokens[3])
  var id = ctx.message.from.id

  if (sys < dist) {
    var temp = sys
    sys = dist
    dist = temp
  }

  if (validBP(sys, dist)) {
    ctx.reply('Thank you for providing your BP readings')
    ctx.reply('You have entered ' + sys + '/' + dist)
    storeBP(id, datetime, sys, dist)
  } else {
    ctx.reply('It seems like you have entered an invalid BP reading. Try again.')
  }
})

// HISTORY
app.command('/history', (ctx) => {

   getBPs(ctx.message.from.id,
   (res)=>{
      const strings = res.map((e) => e.datetime.toLocaleString('en-GB') + " " + e.sys + "/" + e.dist)

      if (typeof(strings) == 'Object') {
         ctx.reply(strings)
      } else {
         console.log(strings)
         const stringList = strings.join("\n")
         ctx.reply(stringList)
      }
   },
   () => {
      console.log("Error occurred")
   })
})

// GRAPH
app.command('/graph', (ctx) => {

   getBPs(ctx.message.from.id,
   (res)=>{
      const x = res.map((e) => e.datetime)
      const sys = res.map((e) => e.sys)
      const dist = res.map((e) => e.dist)

      var trace1 = {
          x: x,
          y: sys,
          type: "scatter",
          name: "Systolic"
      }

      var trace2 = {
          x: x,
          y: dist,
          type: "scatter",
          name: "Diastolic"
      }

      var layout = {
         title: "Blood pressure values",
         xaxis: {title: "Date"},
         yaxis: {title: "BP [mmHg]"}
      }

      var figure = { data: [trace1, trace2], layout: layout }

      var imgOpts = {
          format: 'png',
          width: 1000,
          height: 500
      }

     plotly.getImage(figure, imgOpts, function (error, imageStream) {
        if (error) return console.log (error)
        const nameImg = ctx.message.from.id + "-" + Date.now() + ".png"

        ctx.replyWithPhoto({source: imageStream})

     })

   },
   () => {
      console.log("Error occurred")
   })

})

// START COMMAND
app.command('start', (ctx) => {
   ctx.reply("Hello. Thank you for joining. ☺\n"+
   "You can send me new blood pressure readings directly as numbers.\n"+
   "For example, if you need to send 120 Systolic and 60 Diastolic, you can send:\n"+
   "120 60⏎\n\n"+
   "I will store that for you and eventually provide you with the history of your values as graph or list.\n"+
   "You can request these using the two buttons provided (/graph and /history).",
   Telegraf.Extra.markup((markup) => {return markup.keyboard(['/graph', '/history'])}))
})

// HELP COMMAND
const seekHelp = /^[help|\?]/i
app.hears(seekHelp, (ctx) => {
   ctx.reply("Hello, here is some help:\n"+
   "You can send me new blood pressure readings directly as numbers.\n"+
   "For example, if you need to send 120 Systolic and 60 Diastolic, you can send:\n"+
   "120 60⏎\n\n"+
   "I will store that for you and eventually provide you with the history of your values as graph or list.\n"+
   "You can request these using the two buttons provided (/graph and /history).",
   Telegraf.Extra.markup((markup) => {return markup.keyboard(['/graph', '/history'])}))
})

// IN CASE OF STICKERS
app.on('sticker', (ctx) => ctx.reply('Thank you for the sticker 👍'))

// STARTING THE APP
app.startPolling()
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 * @providesModule GraphQLCompilerContext
 * @format
 */

'use strict';

const immutable = require('immutable');
const invariant = require('invariant');

const {createUserError} = require('./GraphQLCompilerUserError');

import type {Fragment, Root} from './GraphQLIR';
import type {GraphQLSchema} from 'graphql';

const {
  List: ImmutableList,
  OrderedMap: ImmutableOrderedMap,
  Record,
} = immutable;

const Document = Record({
  errors: null,
  name: null,
  node: null,
});

/**
 * An immutable representation of a corpus of documents being compiled together.
 * For each document, the context stores the IR and any validation errors.
 */
class GraphQLCompilerContext {
  _documents: ImmutableOrderedMap<string, Document>;
  schema: GraphQLSchema;

  constructor(schema: GraphQLSchema) {
    this._documents = new ImmutableOrderedMap();
    this.schema = schema;
  }

  /**
   * Returns the documents for the context in the order they were added.
   */
  documents(): Array<Fragment | Root> {
    return this._documents.valueSeq().map(doc => doc.get('node')).toJS();
  }

  updateSchema(schema: GraphQLSchema): GraphQLCompilerContext {
    const context = new GraphQLCompilerContext(schema);
    context._documents = this._documents;
    return context;
  }

  add(node: Fragment | Root): GraphQLCompilerContext {
    invariant(
      !this._documents.has(node.name),
      'GraphQLCompilerContext: Duplicate document named `%s`. GraphQL ' +
        'fragments and roots must have unique names.',
      node.name,
    );
    return this._update(
      (this._documents.set(
        node.name,
        new Document({
          name: node.name,
          node,
        }),
      ): $FlowFixMe),
    );
  }

  addAll(nodes: Array<Fragment | Root>): GraphQLCompilerContext {
    return nodes.reduce(
      (ctx: GraphQLCompilerContext, definition: Fragment | Root) =>
        ctx.add(definition),
      this,
    );
  }

  addError(name: string, error: Error): GraphQLCompilerContext {
    const record = this._get(name);
    let errors = record.get('errors');
    if (errors) {
      errors = errors.push(error);
    } else {
      errors = ImmutableList([error]);
    }
    return this._update(
      (this._documents.set(name, record.set('errors', errors)): $FlowFixMe),
    );
  }

  get(name: string): ?(Fragment | Root) {
    const record = this._documents.get(name);
    return record && record.get('node');
  }

  getFragment(name: string): Fragment {
    const record = this._documents.get(name);
    const node = record && record.get('node');
    if (!(node && node.kind === 'Fragment')) {
      const childModule = name.substring(0, name.lastIndexOf('_'));
      throw createUserError(
        'Relay cannot find fragment `%s`.' +
          ' Please make sure the fragment exists in `%s`',
        name,
        childModule,
      );
    }
    return node;
  }

  getRoot(name: string): Root {
    const record = this._documents.get(name);
    const node = record && record.get('node');
    invariant(
      node && node.kind === 'Root',
      'GraphQLCompilerContext: Expected `%s` to be a root, got `%s`.',
      name,
      node && node.kind,
    );
    return node;
  }

  getErrors(name: string): ?ImmutableList<Error> {
    return this._get(name).get('errors');
  }

  remove(name: string): GraphQLCompilerContext {
    return this._update(this._documents.delete(name));
  }

  _get(name: string): Document {
    const record = this._documents.get(name);
    invariant(record, 'GraphQLCompilerContext: Unknown document `%s`.', name);
    return record;
  }

  _update(
    documents: ImmutableOrderedMap<string, Document>,
  ): GraphQLCompilerContext {
    const context = new GraphQLCompilerContext(this.schema);
    context._documents = documents;
    return context;
  }
}

module.exports = GraphQLCompilerContext;
<commit_msg>Remove a straggling reference to "Relay" from an error message<commit_after>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 * @providesModule GraphQLCompilerContext
 * @format
 */

'use strict';

const immutable = require('immutable');
const invariant = require('invariant');

const {createUserError} = require('./GraphQLCompilerUserError');

import type {Fragment, Root} from './GraphQLIR';
import type {GraphQLSchema} from 'graphql';

const {
  List: ImmutableList,
  OrderedMap: ImmutableOrderedMap,
  Record,
} = immutable;

const Document = Record({
  errors: null,
  name: null,
  node: null,
});

/**
 * An immutable representation of a corpus of documents being compiled together.
 * For each document, the context stores the IR and any validation errors.
 */
class GraphQLCompilerContext {
  _documents: ImmutableOrderedMap<string, Document>;
  schema: GraphQLSchema;

  constructor(schema: GraphQLSchema) {
    this._documents = new ImmutableOrderedMap();
    this.schema = schema;
  }

  /**
   * Returns the documents for the context in the order they were added.
   */
  documents(): Array<Fragment | Root> {
    return this._documents.valueSeq().map(doc => doc.get('node')).toJS();
  }

  updateSchema(schema: GraphQLSchema): GraphQLCompilerContext {
    const context = new GraphQLCompilerContext(schema);
    context._documents = this._documents;
    return context;
  }

  add(node: Fragment | Root): GraphQLCompilerContext {
    invariant(
      !this._documents.has(node.name),
      'GraphQLCompilerContext: Duplicate document named `%s`. GraphQL ' +
        'fragments and roots must have unique names.',
      node.name,
    );
    return this._update(
      (this._documents.set(
        node.name,
        new Document({
          name: node.name,
          node,
        }),
      ): $FlowFixMe),
    );
  }

  addAll(nodes: Array<Fragment | Root>): GraphQLCompilerContext {
    return nodes.reduce(
      (ctx: GraphQLCompilerContext, definition: Fragment | Root) =>
        ctx.add(definition),
      this,
    );
  }

  addError(name: string, error: Error): GraphQLCompilerContext {
    const record = this._get(name);
    let errors = record.get('errors');
    if (errors) {
      errors = errors.push(error);
    } else {
      errors = ImmutableList([error]);
    }
    return this._update(
      (this._documents.set(name, record.set('errors', errors)): $FlowFixMe),
    );
  }

  get(name: string): ?(Fragment | Root) {
    const record = this._documents.get(name);
    return record && record.get('node');
  }

  getFragment(name: string): Fragment {
    const record = this._documents.get(name);
    const node = record && record.get('node');
    if (!(node && node.kind === 'Fragment')) {
      const childModule = name.substring(0, name.lastIndexOf('_'));
      throw createUserError(
        'GraphQLCompilerContext: Cannot find fragment `%s`.' +
          ' Please make sure the fragment exists in `%s`.',
        name,
        childModule,
      );
    }
    return node;
  }

  getRoot(name: string): Root {
    const record = this._documents.get(name);
    const node = record && record.get('node');
    invariant(
      node && node.kind === 'Root',
      'GraphQLCompilerContext: Expected `%s` to be a root, got `%s`.',
      name,
      node && node.kind,
    );
    return node;
  }

  getErrors(name: string): ?ImmutableList<Error> {
    return this._get(name).get('errors');
  }

  remove(name: string): GraphQLCompilerContext {
    return this._update(this._documents.delete(name));
  }

  _get(name: string): Document {
    const record = this._documents.get(name);
    invariant(record, 'GraphQLCompilerContext: Unknown document `%s`.', name);
    return record;
  }

  _update(
    documents: ImmutableOrderedMap<string, Document>,
  ): GraphQLCompilerContext {
    const context = new GraphQLCompilerContext(this.schema);
    context._documents = documents;
    return context;
  }
}

module.exports = GraphQLCompilerContext;
<|endoftext|>


<commit_before>/**
 * Date functions and classes
 */

import { leadingZeroes } from './format';

export const yearMonthDifference = (ym1, ym2) => {
  return 12 * (ym2[0] - ym1[0]) + ym2[1] - ym1[1];
};

const monthDays = (month, year) => {
  const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
  const days = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  return days[month - 1];
};

// year-month-date class
export class YMD {
  constructor(value) {
    let year;
    let month;
    let date;
    this.valid = true;

    if (typeof value === 'string') {
      if (value.match(/^[0-9]{1,2}\/[0-9]{1,2}(\/[0-9]{2,4})?$/)) {
        // parse string initialiser
        const parts = value.split('/').map(item => parseInt(item, 10));
        if (parts.length === 3) {
          year = parts[2];
          if (year < 100) {
            year += 2000;
          }
        }
        else {
          year = new Date().getFullYear();
        }
        month = parts[1];
        date = parts[0];
      }
      else if (value.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)) { // ISO-format
        const parts = value.split('-').map(item => parseInt(item, 10));
        year = parts[0];
        month = parts[1];
        date = parts[2];
      }
      else {
        this.valid = false;
      }
    }
    else if (typeof value === 'object') {
      year = value[0];
      month = value[1];
      date = value[2];
    }
    else if (typeof value === 'undefined' || typeof value === 'number') {
      const dateObj = value ? new Date(value) : new Date();
      year = dateObj.getFullYear();
      month = dateObj.getMonth() + 1;
      date = dateObj.getDate();
    }
    else {
      this.valid = false;
    }

    if (month < 1 || month > 12 || date < 1 || date > monthDays(month, year)) {
      this.valid = false;
    }

    this.year = year;
    this.month = month;
    this.date = date;
  }
  formatNumbers() {
    return [
      leadingZeroes(this.year, 4),
      leadingZeroes(this.month, 2),
      leadingZeroes(this.date, 2)
    ];
  }
  format() {
    const numbers = this.formatNumbers();
    return `${numbers[2]}/${numbers[1]}/${numbers[0]}`;
  }
  formatISO() {
    const numbers = this.formatNumbers();
    return `${numbers[0]}-${numbers[1]}-${numbers[2]}`;
  }
  toString() {
    // this format gets passed to API POST requests (for e.g. updating)
    return `${this.year},${this.month},${this.date}`;
  }
  timestamp() {
    return new Date(`${this.year}-${this.month}-${this.date}`).getTime();
  }
  isAfter(ymd) {
    return this.year > ymd.year ||
      (this.year === ymd.year &&
       (this.month > ymd.month || (this.month === ymd.month && this.date > ymd.date)));
  }
}

<commit_msg>Compare dates using valueOf<commit_after>/**
 * Date functions and classes
 */

import { leadingZeroes } from './format';

export const yearMonthDifference = (ym1, ym2) => {
  return 12 * (ym2[0] - ym1[0]) + ym2[1] - ym1[1];
};

const monthDays = (month, year) => {
  const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
  const days = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  return days[month - 1];
};

// year-month-date class
export class YMD {
  constructor(value) {
    let year;
    let month;
    let date;
    this.valid = true;

    if (typeof value === 'string') {
      if (value.match(/^[0-9]{1,2}\/[0-9]{1,2}(\/[0-9]{2,4})?$/)) {
        // parse string initialiser
        const parts = value.split('/').map(item => parseInt(item, 10));
        if (parts.length === 3) {
          year = parts[2];
          if (year < 100) {
            year += 2000;
          }
        }
        else {
          year = new Date().getFullYear();
        }
        month = parts[1];
        date = parts[0];
      }
      else if (value.match(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)) { // ISO-format
        const parts = value.split('-').map(item => parseInt(item, 10));
        year = parts[0];
        month = parts[1];
        date = parts[2];
      }
      else {
        this.valid = false;
      }
    }
    else if (typeof value === 'object') {
      year = value[0];
      month = value[1];
      date = value[2];
    }
    else if (typeof value === 'undefined' || typeof value === 'number') {
      const dateObj = value ? new Date(value) : new Date();
      year = dateObj.getFullYear();
      month = dateObj.getMonth() + 1;
      date = dateObj.getDate();
    }
    else {
      this.valid = false;
    }

    if (month < 1 || month > 12 || date < 1 || date > monthDays(month, year)) {
      this.valid = false;
    }

    this.year = year;
    this.month = month;
    this.date = date;
  }
  formatNumbers() {
    return [
      leadingZeroes(this.year, 4),
      leadingZeroes(this.month, 2),
      leadingZeroes(this.date, 2)
    ];
  }
  format() {
    const numbers = this.formatNumbers();
    return `${numbers[2]}/${numbers[1]}/${numbers[0]}`;
  }
  valueOf() {
    const numbers = this.formatNumbers();
    return `${numbers[0]}-${numbers[1]}-${numbers[2]}`;
  }
  toString() {
    // this format gets passed to API POST requests (for e.g. updating)
    return `${this.year},${this.month},${this.date}`;
  }
  timestamp() {
    return new Date(`${this.year}-${this.month}-${this.date}`).getTime();
  }
  isAfter(ymd) {
    return this.year > ymd.year ||
      (this.year === ymd.year &&
       (this.month > ymd.month || (this.month === ymd.month && this.date > ymd.date)));
  }
}

<|endoftext|>


<commit_before>(function() {
  function buildQuiz() {
    // we'll need a place to store the HTML output
    const output = [];

    // for each question...
    myQuestions.forEach((currentQuestion, questionNumber) => {
      // we'll want to store the list of answer choices
      const answers = [];

      // and for each available answer...
      for (letter in currentQuestion.answers) {
        // ...add an HTML radio button
        answers.push(
          `
            <input type="radio" name="question${questionNumber}" value="${letter}">
            ${letter} :
            ${currentQuestion.answers[letter]}
          `
        );
      }

      // add this question and its answers to the output
      output.push(
        `
 ${currentQuestion.question}

 ${answers.join("")}
`
      );
    });

    // finally combine our output list into one string of HTML and put it on the page
    quizContainer.innerHTML = output.join("");
  }

  function showResults() {
    // gather answer containers from our quiz
    const answerContainers = quizContainer.querySelectorAll(".answers");

    // keep track of user's answers
    let numCorrect = 0;

    // for each question...
    myQuestions.forEach((currentQuestion, questionNumber) => {
      // find selected answer
      const answerContainer = answerContainers[questionNumber];
      const selector = `input[name=question${questionNumber}]:checked`;
      const userAnswer = (answerContainer.querySelector(selector) || {}).value;

      // if answer is correct
      if (userAnswer === currentQuestion.correctAnswer) {
        // add to the number of correct answers
        numCorrect++;

        // color the answers green
        answerContainers[questionNumber].style.color = "lightgreen";
      } else {
        // if answer is wrong or blank
        // color the answers red
        answerContainers[questionNumber].style.color = "red";
      }
    });

    // show number of correct answers out of total
    resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.length}`;
  }

  const quizContainer = document.getElementById("quiz");
  const resultsContainer = document.getElementById("results");
  const submitButton = document.getElementById("submit");
  const myQuestions = [
    {
      question: "Who is the strongest?",
      answers: {
        a: "Superman",
        b: "The Terminator",
        c: "Waluigi, obviously"
      },
      correctAnswer: "c"
    },
    {
      question: "What is the best site ever created?",
      answers: {
        a: "SitePoint",
        b: "Simple Steps Code",
        c: "Trick question; they're both the best"
      },
      correctAnswer: "c"
    },
    {
      question: "Where is Waldo really?",
      answers: {
        a: "Antarctica",
        b: "Exploring the Pacific Ocean",
        c: "Sitting in a tree",
        d: "Minding his own business, so stop asking"
      },
      correctAnswer: "d"
    }
  ];

  // display quiz right away
  buildQuiz();

  // on submit, show results
  submitButton.addEventListener("click", showResults);
})();
<commit_msg>Delete script.js<commit_after><|endoftext|>


<commit_before>'use strict';

var ensureObject = require('es5-ext/object/valid-object')
  , _           = require('mano').i18n;

module.exports = function (result, config) {
	ensureObject(config);
	var data;

	data = [
		[_("Rejection reasons"), "", "",
			_("Operator"), _("Role"), _("Date"), _("File")
			].join(',')
	];

	data.push.apply(data, result.map(function (row) {
		row[0] = '\"' + row[0].join(' ').replace(/\r?\n|\r/g, ' ').replace(/"/g, "'") + '\"';
		row[row.length - 1] = '\"' + row[row.length - 1].replace(/"/g, "'") + '\"';
		return row;
	}));

	return data.join('\n');
};
<commit_msg>applied the same row sanitation for all rows<commit_after>'use strict';

var ensureObject = require('es5-ext/object/valid-object')
  , _           = require('mano').i18n;

module.exports = function (result, config) {
	ensureObject(config);
	var data;

	data = [
		[_("Rejection reasons"), "", "",
			_("Operator"), _("Role"), _("Date"), _("File")
			].join(',')
	];

	data.push.apply(data, result.map(function (row) {
		row.forEach(function (column, index) {
			if (column.constructor === Array) column = column.join(' ');
			row[index] = '\"' + column.replace(/\r?\n|\r/g, ' ').replace(/"/g, "'") + '\"';
		});
		return row;
	}));

	return data.join('\n');
};
<|endoftext|>