<commit_before>'use strict'

// A Block is an svg group that do any behavior, this can contain other Blocks or Workspaces
BB.Block = function(name, workspace, options)  {
  this.name = name;
  this.id = null;
  this.children = [];
  this.x = 0;
  this.y = 0;
  this.width = 50;
  this.height = 20;
  this.container = null; // contains attached elements(border) and SVG document
  this.childContainer = null; // svg group that contains all childrens
  this.statement = true;
  this.nested = true; // Blocks are nested by default
  if (!options) {
  	return;
  }
  if (!workspace) {
    this.workspace = workspace;
  }
  if (options.x) {
    this.x = options.x;
  }
  if (options.y) {
    this.y = options.y;
  }
  if (options.stylingFunction) {
    this.stylingFunction = options.stylingFunction;
  }
  if (options.colorPalette) {
    this.colorPalette = options.colorPalette;
  }
  if (options.render) {
  	this.render();
  }
  };

// Block inerits from Object
BB.Block.prototype = new BB.Object("Block");
BB.Block.prototype.constructor = BB.Block;

BB.Block.prototype.append = function(obj) {
	//this.path = this.workspace;
};

BB.Block.prototype.render = function() {
  if (!this.workspace) {
    throw 'Blocks must have a workspace to be rendered';
    return;
  }
  if (!this.rendered) {
    this.container = this.workspace.root.group();
    this.container.move(this.x, this.y);
    if (!this.colorPalette) {
      this.colorPalette = BB.colorPalettes.block.light; //default palette
    }
    // styling
    this.bgColor = this.colorPalette.background;
    //this.borderColor = this.colorPalette.border[this.nested ? 'nested' : 'main'];
    if (this.stylingFunction) {
      this.stylingFunction();
    }
    // render elements
    this.root = this.workspace.root.rect(this.width, this.height).fill(this.bgColor).radius(5);
    this.childContainer = this.workspace.root.group();
    for (var i = 0; i < this.children.length; i++) {
      this.children[i].render();
      this.childContainer.add(this.children[i].container);
    }
    this.container.add(this.root);
    this.container.add(this.childContainer);
    this.container.draggable(this.workspace ,null ,[this.container]);
    var el = this; //for the next closure
    this.container.dragstart = function() {
      el.toTopPropagate(); //focus workspace
    };
    this.workspace.childContainer.add(this.container);
    this.workspace.childRendered(this);
    this.rendered = true;
  }
};<commit_msg>block prototype<commit_after>'use strict'

// A Block is an svg group that do any behavior, this can contain other Blocks or Workspaces
BB.Block = function(name, options)  {
  BB.Object.call(this, 'Block');
  this.name = name;
  this.id = null;
  this.children = [];
  this.x = 0;
  this.y = 0;
  this.width = 20;
  this.height = 20;
  this.container = null; // contains attached elements(border) and SVG document
  this.childContainer = null; // svg group that contains all children
  this.statement = true;
  this.root = null;
  this.rootDark = null; //shadow effect
  this.nested = true; // Blocks are nested by default, allows toTopPropagate
  this.fields = [];
  this.attachDraggable = [];
  this.metrics = {
    borderRadius: 5,
    borderWidth: 1,
    initialSpace: {x: 4, y: 0},
    finalSpace: {x: 4, y: 4},
    fieldSpace: 5,
    rowSpace: 5, // same as borderRadius is recommended
    widthType: 'globalWidth',
  };
  if (!options) {
  	return;
  }
  if (options.x) {
    this.x = options.x;
  }
  if (options.y) {
    this.y = options.y;
  }
  if (options.stylingFunction) {
    this.stylingFunction = options.stylingFunction;
  }
  if (options.colorPalette) {
    this.colorPalette = options.colorPalette;
  }
  if (options.metrics) {
  	this.metrics = options.metrics;
  }
  if (options.render) {
  	this.render();
  }
};

// Block inherits from Object
BB.Block.prototype = Object.create(BB.Object.prototype);

BB.Block.prototype.appendField = function(field) {
	this.fields.push(field);
};

BB.Block.prototype.newRow = function() {
	this.fields.push('newRow');
};

BB.Block.prototype.widthType = function(type) {
  if (type == 'grouped') {
	this.fields.push('groupedWidth');
  } else if (type == 'global') {
    this.fields.push('globalWidth');
  } else if (type == 'single') {
    this.fields.push('singleWidth');
  } else {
    throw 'Unknown width type';
  }
};

BB.Block.prototype.render = function() {
  if (!this.workspace) {
    throw 'Blocks must have a workspace to be rendered';
    return;
  }
  if (!this.rendered) {
    this.init(); // attributes of Block
    this.initSvg(); // compute graphics for rendering
    this.container = this.workspace.root.group();
    this.container.move(this.x, this.y);
    if (!this.colorPalette) {
      this.colorPalette = BB.colorPalettes.block.light; //default palette
    }
    // styling
    this.bgColor = this.colorPalette.background;
    this.shadowColor = this.colorPalette.shadowColor;
    this.lightColor = this.colorPalette.lightColor;
    this.borderColor = this.colorPalette.border;
    if (this.stylingFunction) {
      this.stylingFunction();
    }
    //render block - render fields and all block svg
    this.renderBlock_();
    // render children
    this.childContainer = this.workspace.root.group();
    for (var i = 0; i < this.children.length; i++) {
      this.children[i].render();
      this.childContainer.add(this.children[i].container);
    }
    this.container.add(this.rootDark);
    this.container.add(this.rootLight);
    this.container.add(this.root);
    this.container.add(this.childContainer);
    // add fields to container
    for (var i = 0; i < this.fields.length; i++) {
      if (typeof(this.fields[i]) == 'object') {
        this.container.add(this.fields[i]);
      }
    }
    this.attachDraggable.push(this.rootDark);
    this.attachDraggable.push(this.rootLight);
    this.attachDraggable.push(this.root);
    this.container.draggable(this.workspace, null, this.attachDraggable);
    var el = this; //for the next closure
    this.container.dragstart = function() {
      el.toTopPropagate(); //focus workspace
    };
    this.workspace.childContainer.add(this.container);
    this.workspace.childRendered(this);
    if (this.attach) {
      this.attach(); // attach additional svg elements to block
    }
    this.rendered = true;
  }
};

BB.Block.prototype.attachEvents = function(child) {
  this.attachDraggable.push(child);
  this.container.draggable(this.workspace, null, this.attachDraggable);
};

// calculate metrics
BB.Block.prototype.initSvg = function() {
  var globalWidth = this.metrics.initialSpace.x, box, maxHeight = 0;
  var metrics = {
    width: this.metrics.initialSpace.x,
    y: this.metrics.initialSpace.y
  };
  this.metrics.rows = [];
  for (var i = 0; i < this.fields.length; i++) {
    if (typeof(this.fields[i]) == 'string') { //field control commands
      switch (this.fields[i]) {
          case 'newRow':
            metrics.y += maxHeight + this.metrics.rowSpace + this.metrics.initialSpace.y;
            metrics.width  += this.metrics.finalSpace.x - this.metrics.fieldSpace;
            this.metrics.rows.push({width: metrics.width,
                                    y: metrics.y,
                                    height: maxHeight,
                                    widthType: this.metrics.widthType
                                   });
            globalWidth = Math.max(metrics.width, globalWidth);
            metrics.width = this.metrics.initialSpace.x;
            maxHeight = 0;
            break;
          case 'globalWidth':
            this.metrics.widthType = 'globalWidth';
            break;
          case 'groupedWidth':
            this.metrics.widthType = 'groupedWidth';
            break;
          case 'singleWidth':
            this.metrics.widthType = 'singleWidth';
            break;
          default:
          throw 'Unknown width type';
      }
    } else {
      box = this.fields[i].bbox();
      this.fields[i].move(metrics.width, metrics.y); // position of field
      metrics.width += box.width + this.metrics.fieldSpace;
      maxHeight = Math.max(maxHeight, box.height);
    }
  }
  metrics.width += this.metrics.finalSpace.x - this.metrics.fieldSpace;
  globalWidth = Math.max(metrics.width, globalWidth);
  metrics.y += box.height + this.metrics.finalSpace.y;
  this.metrics.rows.push({
    width: metrics.width,
    y: metrics.y,
    height: maxHeight,
    widthType: this.metrics.widthType
  });
  this.width = globalWidth;
  this.height = metrics.y;
  // compute widths
  var i, j, groupFound = false, maxWidth;
  for (i = 0; i < this.metrics.rows.length; i++) {
    if (this.metrics.rows[i].widthType == 'groupedWidth') {
      if (groupFound == false) {
        maxWidth = this.metrics.rows[i].width;
        for (j=i+1;j<this.metrics.rows.length && this.metrics.rows[j].widthType=='groupedWidth'; j++) {
          maxWidth = Math.max(maxWidth, this.metrics.rows[j].width);
        }
        groupFound = true;
      }
      this.metrics.rows[i].width = maxWidth; //uniforms width
    } else {
       if (this.metrics.rows[i].widthType == 'globalWidth') {
         this.metrics.rows[i].width = this.width; //global width
       }
       groupFound = false;
    }
  }
  // compute heights
  var height, lastWidth = this.metrics.rows[0].width;
  this.metrics.rows[0].lastRadius = 'convex';
  for (i = 1; i < this.metrics.rows.length; i++) {
    height = this.metrics.rows[i].height;
    if (lastWidth < this.metrics.rows[i].width) {
      this.metrics.rows[i].lastRadius = 'convex';
      this.metrics.rows[i-1].nextRadius = 'concave';
    }else if (lastWidth > this.metrics.rows[i].width) {
      this.metrics.rows[i].lastRadius = 'concave';
      this.metrics.rows[i-1].nextRadius = 'convex';
    } else {
      this.metrics.rows[i].lastRadius = 'plane';
      this.metrics.rows[i-1].nextRadius = 'plane';
    }
    lastWidth = this.metrics.rows[i].width;
  }
  this.metrics.rows[this.metrics.rows.length-1].nextRadius = 'convex';
};

BB.Block.prototype.renderBlock_ = function() {
  var radius = this.metrics.borderRadius; // for typing
  var rowSpace = this.metrics.rowSpace; // for typing
  this.root = this.workspace.root.path().M({x: radius, y: this.height})
              .q({x: -radius, y: 0}, {x: -radius, y: -radius})
              .v(-this.height + 2*radius) // left side
              .q({x: 0, y: -radius}, {x: radius, y: -radius});
  // top
  var row = this.metrics.rows[0]; //for typing
  var height = row.y;
  height -= radius;
  //first row
  this.root.H(row.width - radius)
            .q({x: radius, y: 0}, {x: radius, y: radius})
            .V(height);
  //render by row rigth line - middle
  for (var i = 1; i < this.metrics.rows.length - 1 ; i++) {
    row = this.metrics.rows[i];
    height = row.y;
    //height = substractRadius(height, row);
    height -= radius;
    if (row.lastRadius == 'convex') {
      this.root.q({x: 0, y: radius}, {x: radius, y: radius})
               .H(row.width - radius)
               .q({x: radius, y: 0}, {x: radius, y: radius})
               .V(height);
    } else if (row.lastRadius == 'concave') {
      this.root.q({x: 0, y: radius}, {x: -radius, y: radius})
               .H(row.width + radius)
               .q({x: -radius, y: 0}, {x: -radius, y: radius})
               .V(height);
    } else if (row.lastRadius == 'plane') {
      this.root.V(height);
    } else {
      throw 'Unsopported type of radius: ' + row.lastRadius;
    }
  }
  //last row
  row = this.metrics.rows[this.metrics.rows.length-1];
  if (row.lastRadius == 'plane') {
    this.root.V(row.y - radius);
  } else {
    this.root.q({x: 0, y: radius}, {x: radius, y: radius})
              .H(row.width - radius)
              .q({x: radius, y: 0}, {x: radius, y: radius})
              .V(row.y - radius);
  }
  var finalRow = this.metrics.rows[this.metrics.rows.length - 1]; //for typing
  var finalWidth = finalRow.width;
  // bottom line
  this.root.q({x: 0, y: radius}, {x: -radius, y: radius})
           .h(-finalWidth + 2*radius)
           // TODO: report border bug in svg, when drag a block with black border, this proyest dont use that, use svg rect
           /*.stroke({ color: this.borderColor,
                     opacity: 1,
                     width: this.metrics.borderWidth
            }).fill(this.bgColor);*/
  this.root.fill(this.bgColor);
  this.rootDark = this.root.clone();
  this.rootDark.fill(this.shadowColor);
  this.rootDark.dmove(1,1);
  this.rootLight = this.root.clone();
  this.rootLight.fill(this.lightColor);
  this.rootLight.dmove(-1,-1);
};<|endoftext|>


<commit_before>module.exports = function(grunt) {

    "use strict";

    grunt.initConfig({

        exec: {
            browserify: {
                //cmd: 'NODE_PATH=node_modules/buttercup/source node node_modules/browserify/bin/cmd.js -e node_modules/buttercup/source/module.js --insert-globals -o build/buttercup.js'
                cmd: 'node node_modules/browserify/bin/cmd.js -e source/index.js --ignore curlrequest -t brfs --insert-globals -o build/buttercup.js'
            }
        },

        jasmine: {
            buttercup: {
                src: "build/buttercup.min.js",
                options: {
                    specs: "tests/**/*.js"
                }
            }
        },

        uglify: {
            buttercup: {
                files: {
                    "build/buttercup.min.js": ["build/buttercup.js"]
                }
            }
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask("default", ["build"]);

    grunt.registerTask("build", [
        "exec:browserify",
        "uglify:buttercup"
    ]);

    grunt.registerTask("test", ["jasmine:buttercup"]);

};
<commit_msg>Build-then-test phase<commit_after>module.exports = function(grunt) {

    "use strict";

    grunt.initConfig({

        exec: {
            browserify: {
                //cmd: 'NODE_PATH=node_modules/buttercup/source node node_modules/browserify/bin/cmd.js -e node_modules/buttercup/source/module.js --insert-globals -o build/buttercup.js'
                cmd: 'node node_modules/browserify/bin/cmd.js -e source/index.js --ignore curlrequest -t brfs --insert-globals -o build/buttercup.js'
            }
        },

        jasmine: {
            buttercup: {
                src: "build/buttercup.min.js",
                options: {
                    specs: "tests/**/*.js"
                }
            }
        },

        uglify: {
            buttercup: {
                files: {
                    "build/buttercup.min.js": ["build/buttercup.js"]
                }
            }
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask("default", ["build"]);

    grunt.registerTask("build", [
        "exec:browserify",
        "uglify:buttercup"
    ]);

    grunt.registerTask("test", [
        "build",
        "jasmine:buttercup"
    ]);

};
<|endoftext|>


<commit_before>/**
 * This is an in-memory cache for models. Models are cached by local id (_id) and remote id (defined by the mapping).
 * Lookups are performed against the cache when mapping.
 * @module cache
 */
var log = require('./log')('cache'),
  InternalSiestaError = require('./error').InternalSiestaError,
  util = require('./util');

function Cache() {
  this.reset();
}

Cache.prototype = {
  reset: function() {
    this.remote = {};
    this.localById = {};
    this.local = {};
  },
  /**
   * Return the object in the cache given a local id (_id)
   * @param  {String|Array} localId
   * @return {ModelInstance}
   */
  getViaLocalId: function getViaLocalId(localId) {
    if (util.isArray(localId)) return localId.map(function(x) {return this.localById[x]}.bind(this));
    else return this.localById[localId];
  },
  /**
   * Given a remote identifier and an options object that describes mapping/collection,
   * return the model if cached.
   * @param  {String|Array} remoteId
   * @param  {Object} opts
   * @param  {Object} opts.model
   * @return {ModelInstance}
   */
  getViaRemoteId: function(remoteId, opts) {
    var c = (this.remote[opts.model.collectionName] || {})[opts.model.name] || {};
    return util.isArray(remoteId) ? remoteId.map(function(x) {return c[x]}) : c[remoteId];
  },
  /**
   * Return the singleton object given a singleton model.
   * @param  {Model} model
   * @return {ModelInstance}
   */
  getSingleton: function(model) {
    var modelName = model.name;
    var collectionName = model.collectionName;
    var collectionCache = this.local[collectionName];
    if (collectionCache) {
      var typeCache = collectionCache[modelName];
      if (typeCache) {
        var objs = [];
        for (var prop in typeCache) {
          if (typeCache.hasOwnProperty(prop)) {
            objs.push(typeCache[prop]);
          }
        }
        if (objs.length > 1) {
          var errStr = 'A singleton model has more than 1 object in the cache! This is a serious error. ' +
            'Either a model has been modified after objects have already been created, or something has gone' +
            'very wrong. Please file a bug report if the latter.';
          throw new InternalSiestaError(errStr);
        } else if (objs.length) {
          return objs[0];
        }
      }
    }
    return null;
  }
};

var cache = new Cache();

/**
 * Insert an object into the cache using a remote identifier defined by the mapping.
 * @param  {ModelInstance} obj
 * @param  {String} remoteId
 * @param  {String} previousRemoteId If remote id has been changed, this is the old remote identifier
 */
function remoteInsert(obj, remoteId, previousRemoteId) {
  if (obj) {
    var collectionName = obj.model.collectionName;
    if (collectionName) {
      if (!cache.remote[collectionName]) {
        cache.remote[collectionName] = {};
      }
      var type = obj.model.name;
      if (type) {
        if (!cache.remote[collectionName][type]) {
          cache.remote[collectionName][type] = {};
        }
        if (previousRemoteId) {
          cache.remote[collectionName][type][previousRemoteId] = null;
        }
        var cachedObject = cache.remote[collectionName][type][remoteId];
        if (!cachedObject) {
          cache.remote[collectionName][type][remoteId] = obj;
          log('Remote cache insert: ' + obj._dump(true));
        } else {
          // Something has gone really wrong. Only one object for a particular collection/type/remoteid combo
          // should ever exist.
          if (obj != cachedObject) {
            var message = 'Object ' + collectionName.toString() + ':' + type.toString() + '[' + obj.model.id + '="' + remoteId + '"] already exists in the cache.' +
              ' This is a serious error, please file a bug report if you are experiencing this out in the wild';
            log(message, {
              obj: obj,
              cachedObject: cachedObject
            });
            throw new InternalSiestaError(message);
          } else {
            log('Object has already been inserted: ' + obj._dump(true));
          }

        }
      } else {
        throw new InternalSiestaError('Model has no type', {
          model: obj.model,
          obj: obj
        });
      }
    } else {
      throw new InternalSiestaError('Model has no collection', {
        model: obj.model,
        obj: obj
      });
    }
  } else {
    var msg = 'Must pass an object when inserting to cache';
    log(msg);
    throw new InternalSiestaError(msg);
  }
}

function _remoteCache() {
  return cache.remote
}

function _localCache() {
  return cache.localById;
}

/**
 * Query the cache
 * @param  {Object} opts Object describing the query
 * @return {ModelInstance}
 * @example
 * ```js
 * cache.get({_id: '5'}); // Query by local id
 * cache.get({remoteId: '5', mapping: myMapping}); // Query by remote id
 * ```
 */
function get(opts) {
  log('get', opts);
  var obj, idField, remoteId;
  var localId = opts.localId;
  if (localId) {
    obj = cache.getViaLocalId(localId);
    if (obj) {
      return obj;
    } else {
      if (opts.model) {
        idField = opts.model.id;
        remoteId = opts[idField];
        log(idField + '=' + remoteId);
        return cache.getViaRemoteId(remoteId, opts);
      } else {
        return null;
      }
    }
  } else if (opts.model) {
    idField = opts.model.id;
    remoteId = opts[idField];
    if (remoteId) {
      return cache.getViaRemoteId(remoteId, opts);
    } else if (opts.model.singleton) {
      return cache.getSingleton(opts.model);
    }
  } else {
    log('Invalid opts to cache', {
      opts: opts
    });
  }
  return null;
}

/**
 * Insert an object into the cache.
 * @param  {ModelInstance} obj
 * @throws {InternalSiestaError} An object with _id/remoteId already exists. Not thrown if same obhect.
 */
function insert(obj) {
  var localId = obj.localId;
  if (localId) {
    var collectionName = obj.model.collectionName;
    var modelName = obj.model.name;
    if (!cache.localById[localId]) {
      cache.localById[localId] = obj;
      if (!cache.local[collectionName]) cache.local[collectionName] = {};
      if (!cache.local[collectionName][modelName]) cache.local[collectionName][modelName] = {};
      cache.local[collectionName][modelName][localId] = obj;
    } else {
      // Something has gone badly wrong here. Two objects should never exist with the same _id
      if (cache.localById[localId] != obj) {
        var message = 'Object with localId="' + localId.toString() + '" is already in the cache. ' +
          'This is a serious error. Please file a bug report if you are experiencing this out in the wild';
        log(message);
        throw new InternalSiestaError(message);
      }
    }
  }
  var idField = obj.idField;
  var remoteId = obj[idField];
  if (remoteId) {
    remoteInsert(obj, remoteId);
  } else {
    log('No remote id ("' + idField + '") so wont be placing in the remote cache', obj);
  }
}

/**
 * Returns true if object is in the cache
 * @param  {ModelInstance} obj
 * @return {boolean}
 */
function contains(obj) {
  var q = {
    localId: obj.localId
  };
  var model = obj.model;
  if (model.id) {
    if (obj[model.id]) {
      q.model = model;
      q[model.id] = obj[model.id];
    }
  }
  return !!get(q);
}

/**
 * Removes the object from the cache (if it's actually in the cache) otherwises throws an error.
 * @param  {ModelInstance} obj
 * @throws {InternalSiestaError} If object already in the cache.
 */
function remove(obj) {
  if (contains(obj)) {
    var collectionName = obj.model.collectionName;
    var modelName = obj.model.name;
    var localId = obj.localId;
    if (!modelName) throw InternalSiestaError('No mapping name');
    if (!collectionName) throw InternalSiestaError('No collection name');
    if (!localId) throw InternalSiestaError('No localId');
    delete cache.local[collectionName][modelName][localId];
    delete cache.localById[localId];
    if (obj.model.id) {
      var remoteId = obj[obj.model.id];
      if (remoteId) {
        delete cache.remote[collectionName][modelName][remoteId];
      }
    }
  }
}

exports._remoteCache = _remoteCache;
exports._localCache = _localCache;
Object.defineProperty(exports, '_localCacheByType', {
  get: function() {
    return cache.local;
  }
});
exports.get = get;
exports.insert = insert;
exports.remoteInsert = remoteInsert;
exports.reset = cache.reset.bind(cache);
exports.contains = contains;
exports.remove = remove;
exports.getSingleton = cache.getSingleton.bind(cache);
exports.getViaLocalId = cache.getViaLocalId.bind(cache);
exports.getViaRemoteId = cache.getViaRemoteId.bind(cache);
exports.count = function() {
  return Object.keys(cache.localById).length;
};<commit_msg>encapsulate cache<commit_after>/**
 * This is an in-memory cache for models. Models are cached by local id (_id) and remote id (defined by the mapping).
 * Lookups are performed against the cache when mapping.
 * @module cache
 */
var log = require('./log')('cache'),
  InternalSiestaError = require('./error').InternalSiestaError,
  util = require('./util');

function Cache() {
  this.reset();
  Object.defineProperty(this, '_localCacheByType', {
    get: function() {
      return this.local;
    }
  });
}

Cache.prototype = {
  reset: function() {
    this.remote = {};
    this.localById = {};
    this.local = {};
  },
  /**
   * Return the object in the cache given a local id (_id)
   * @param  {String|Array} localId
   * @return {ModelInstance}
   */
  getViaLocalId: function getViaLocalId(localId) {
    if (util.isArray(localId)) return localId.map(function(x) {return this.localById[x]}.bind(this));
    else return this.localById[localId];
  },
  /**
   * Given a remote identifier and an options object that describes mapping/collection,
   * return the model if cached.
   * @param  {String|Array} remoteId
   * @param  {Object} opts
   * @param  {Object} opts.model
   * @return {ModelInstance}
   */
  getViaRemoteId: function(remoteId, opts) {
    var c = (this.remote[opts.model.collectionName] || {})[opts.model.name] || {};
    return util.isArray(remoteId) ? remoteId.map(function(x) {return c[x]}) : c[remoteId];
  },
  /**
   * Return the singleton object given a singleton model.
   * @param  {Model} model
   * @return {ModelInstance}
   */
  getSingleton: function(model) {
    var modelName = model.name;
    var collectionName = model.collectionName;
    var collectionCache = this.local[collectionName];
    if (collectionCache) {
      var typeCache = collectionCache[modelName];
      if (typeCache) {
        var objs = [];
        for (var prop in typeCache) {
          if (typeCache.hasOwnProperty(prop)) {
            objs.push(typeCache[prop]);
          }
        }
        if (objs.length > 1) {
          var errStr = 'A singleton model has more than 1 object in the cache! This is a serious error. ' +
            'Either a model has been modified after objects have already been created, or something has gone' +
            'very wrong. Please file a bug report if the latter.';
          throw new InternalSiestaError(errStr);
        } else if (objs.length) {
          return objs[0];
        }
      }
    }
    return null;
  },
  /**
   * Insert an object into the cache using a remote identifier defined by the mapping.
   * @param  {ModelInstance} obj
   * @param  {String} remoteId
   * @param  {String} [previousRemoteId] If remote id has been changed, this is the old remote identifier
   */
  remoteInsert: function(obj, remoteId, previousRemoteId) {
    if (obj) {
      var collectionName = obj.model.collectionName;
      if (collectionName) {
        if (!this.remote[collectionName]) {
          this.remote[collectionName] = {};
        }
        var type = obj.model.name;
        if (type) {
          if (!this.remote[collectionName][type]) {
            this.remote[collectionName][type] = {};
          }
          if (previousRemoteId) {
            this.remote[collectionName][type][previousRemoteId] = null;
          }
          var cachedObject = this.remote[collectionName][type][remoteId];
          if (!cachedObject) {
            this.remote[collectionName][type][remoteId] = obj;
            log('Remote cache insert: ' + obj._dump(true));
          } else {
            // Something has gone really wrong. Only one object for a particular collection/type/remoteid combo
            // should ever exist.
            if (obj != cachedObject) {
              var message = 'Object ' + collectionName.toString() + ':' + type.toString() + '[' + obj.model.id + '="' + remoteId + '"] already exists in the cache.' +
                ' This is a serious error, please file a bug report if you are experiencing this out in the wild';
              log(message, {
                obj: obj,
                cachedObject: cachedObject
              });
              throw new InternalSiestaError(message);
            } else {
              log('Object has already been inserted: ' + obj._dump(true));
            }

          }
        } else {
          throw new InternalSiestaError('Model has no type', {
            model: obj.model,
            obj: obj
          });
        }
      } else {
        throw new InternalSiestaError('Model has no collection', {
          model: obj.model,
          obj: obj
        });
      }
    } else {
      var msg = 'Must pass an object when inserting to cache';
      log(msg);
      throw new InternalSiestaError(msg);
    }
  },
  /**
   * Query the cache
   * @param  {Object} opts Object describing the query
   * @return {ModelInstance}
   * @example
   * ```js
   * cache.get({_id: '5'}); // Query by local id
   * cache.get({remoteId: '5', mapping: myMapping}); // Query by remote id
   * ```
   */
  get: function(opts) {
    log('get', opts);
    var obj, idField, remoteId;
    var localId = opts.localId;
    if (localId) {
      obj = this.getViaLocalId(localId);
      if (obj) {
        return obj;
      } else {
        if (opts.model) {
          idField = opts.model.id;
          remoteId = opts[idField];
          log(idField + '=' + remoteId);
          return this.getViaRemoteId(remoteId, opts);
        } else {
          return null;
        }
      }
    } else if (opts.model) {
      idField = opts.model.id;
      remoteId = opts[idField];
      if (remoteId) {
        return this.getViaRemoteId(remoteId, opts);
      } else if (opts.model.singleton) {
        return this.getSingleton(opts.model);
      }
    } else {
      log('Invalid opts to cache', {
        opts: opts
      });
    }
    return null;
  },
  _remoteCache: function() {
    return this.remote
  },
  _localCache: function() {
    return this.localById;
  },
  /**
   * Insert an object into the cache.
   * @param  {ModelInstance} obj
   * @throws {InternalSiestaError} An object with _id/remoteId already exists. Not thrown if same obhect.
   */
  insert: function(obj) {
    var localId = obj.localId;
    if (localId) {
      var collectionName = obj.model.collectionName;
      var modelName = obj.model.name;
      if (!this.localById[localId]) {
        this.localById[localId] = obj;
        if (!this.local[collectionName]) this.local[collectionName] = {};
        if (!this.local[collectionName][modelName]) this.local[collectionName][modelName] = {};
        this.local[collectionName][modelName][localId] = obj;
      } else {
        // Something has gone badly wrong here. Two objects should never exist with the same _id
        if (this.localById[localId] != obj) {
          var message = 'Object with localId="' + localId.toString() + '" is already in the cache. ' +
            'This is a serious error. Please file a bug report if you are experiencing this out in the wild';
          log(message);
          throw new InternalSiestaError(message);
        }
      }
    }
    var idField = obj.idField;
    var remoteId = obj[idField];
    if (remoteId) {
      this.remoteInsert(obj, remoteId);
    } else {
      log('No remote id ("' + idField + '") so wont be placing in the remote cache', obj);
    }
  },
  /**
   * Returns true if object is in the cache
   * @param  {ModelInstance} obj
   * @return {boolean}
   */
  contains: function(obj) {
    var q = {
      localId: obj.localId
    };
    var model = obj.model;
    if (model.id) {
      if (obj[model.id]) {
        q.model = model;
        q[model.id] = obj[model.id];
      }
    }
    return !!this.get(q);
  },

  /**
   * Removes the object from the cache (if it's actually in the cache) otherwises throws an error.
   * @param  {ModelInstance} obj
   * @throws {InternalSiestaError} If object already in the cache.
   */
  remove: function(obj) {
    if (this.contains(obj)) {
      var collectionName = obj.model.collectionName;
      var modelName = obj.model.name;
      var localId = obj.localId;
      if (!modelName) throw InternalSiestaError('No mapping name');
      if (!collectionName) throw InternalSiestaError('No collection name');
      if (!localId) throw InternalSiestaError('No localId');
      delete this.local[collectionName][modelName][localId];
      delete this.localById[localId];
      if (obj.model.id) {
        var remoteId = obj[obj.model.id];
        if (remoteId) {
          delete this.remote[collectionName][modelName][remoteId];
        }
      }
    }
  },

  count: function() {
    return Object.keys(this.localById).length;
  }
};

module.exports = new Cache();<|endoftext|>


<commit_before>module.exports = function(grunt) {

    // Configuration goes here
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        banner: '/*!\n' +
        ' * Zest\n' +
        ' * A light-weight DOM library\n' +
        ' * v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
        ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
        ' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' +
        ' */\n\n',

        concat: {
            options: {
              banner: '<%= banner %>',
              separator: '\n\n',
            },
            dist: {
                src: ['src/zest.js'],
                dest: 'dist/zest.js'
            }
        },

        jshint: {
            files: ['src/**/*.js'],
            options: {
                strict: true,
                globals: {
                    console: true
                }
            }
        },

        qunit: {
            files: ['test/**/*.html']
        },

        uglify: {
            options: {
                banner: '<%= banner %>'
            },
            script: {
                files: {
                    'dist/zest.min.js': ['src/zest.js']
                }
            }
        },

        watch: {
            scripts: {
                files: ['src/**/*.js'],
                tasks: ['jshint', 'concat', 'uglify']
            }
        }

    });

    // Load plugins here
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    // Define your tasks here
    grunt.registerTask('default', ['jshint', 'concat', 'uglify']);

    // Build
    grunt.registerTask('build', ['jshint', 'concat', 'uglify']);

    // Test
    grunt.registerTask('test', ['qunit']);

    // Watch
    grunt.registerTask('watch', ['watch']);

};<commit_msg>Updated watch task to spy to bypass Grunt error<commit_after>module.exports = function(grunt) {

    // Configuration goes here
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        banner: '/*!\n' +
        ' * Zest\n' +
        ' * A light-weight DOM library\n' +
        ' * v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
        ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
        ' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' +
        ' */\n\n',

        concat: {
            options: {
              banner: '<%= banner %>',
              separator: '\n\n',
            },
            dist: {
                src: ['src/zest.js'],
                dest: 'dist/zest.js'
            }
        },

        jshint: {
            files: ['src/**/*.js'],
            options: {
                strict: true,
                globals: {
                    console: true
                }
            }
        },

        qunit: {
            files: ['test/**/*.html']
        },

        uglify: {
            options: {
                banner: '<%= banner %>'
            },
            script: {
                files: {
                    'dist/zest.min.js': ['src/zest.js']
                }
            }
        },

        watch: {
            scripts: {
                files: ['src/**/*.js'],
                tasks: ['jshint', 'concat', 'uglify']
            }
        }

    });

    // Load plugins here
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    // Define your tasks here
    grunt.registerTask('default', ['jshint', 'concat', 'uglify']);

    // Build
    grunt.registerTask('build', ['jshint', 'concat', 'uglify']);

    // Test
    grunt.registerTask('test', ['qunit']);

    // Watch
    grunt.registerTask('spy', ['watch']);

};<|endoftext|>


<commit_before>

module.exports = function(grunt) {

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-conventional-changelog');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-ngdocs');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    dist: 'dist',
    sources: 'src/**/*.js',
    tests: 'test/**/*.js',
    ngdocFiles: 'src/**/*.ngdoc',
    clean: {
      dist: ['<%= dist %>']
    },
    jshint: {
      files: ['Gruntfile.js','<%= sources %>'],
      options: {
        jshintrc: '.jshintrc'
      }
    },
    karma: {
      options: {
        configFile: 'karma.conf.js',
        singleRun: true
      },
      unit: {},
      travis: {
        browsers: ['Firefox', 'PhantomJS']
      },
      watch: {
        singleRun: false
      }
    },
    uglify: {
      options: {
        banner: '/** Componitor v. <%= pkg.version %> */\n'
      },
      dist: {
        options: {
          mangle: false,
          compress: false,
          beautify: true,
          wrap: true
        },
        src: ['<%= sources %>'],
        dest: '<%= dist %>/componitor.js'
      },
      minify: {
        options: {
          sourceMap: true
        },
        src: ['<%= uglify.dist.dest %>'],
        dest: '<%= dist %>/componitor.min.js'
      }
    },
    ngdocs: {
      options: {
        dest: '<%= dist %>/docs',
        scripts: [
          'angular.js',
          '<%= uglify.dist.dest %>'
        ],
        title: 'componitor',
        startPage: 'api/componitor',
        titleLink: '#/api/componitor',
        html5Mode: false
      },
      api: {
        src: ['<%= sources %>', '<%= ngdocFiles %>'],
        title: 'API Documentation'
      }
    },
    watch: {
      ngdocs: {
        files: ['Gruntfile.js', '<%= sources %>', '<%= ngdocFiles %>'],
        tasks: ['after-test']
      }
    }
  });

  grunt.registerTask('before-test', ['jshint']);
  grunt.registerTask('test', ['karma:unit']);
  grunt.registerTask('after-test', ['build']);
  grunt.registerTask('build', ['clean:dist', 'uglify', 'ngdocs:api']);
  grunt.registerTask('default', ['before-test','test','after-test']);

  grunt.registerTask('travis', ['before-test', 'karma:travis']);
};
<commit_msg>Add tests to jshint<commit_after>

module.exports = function(grunt) {

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-conventional-changelog');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-ngdocs');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    dist: 'dist',
    sources: 'src/**/*.js',
    tests: 'test/**/*.js',
    ngdocFiles: 'src/**/*.ngdoc',
    clean: {
      dist: ['<%= dist %>']
    },
    jshint: {
      files: ['Gruntfile.js','<%= sources %>','<%= tests %>'],
      options: {
        jshintrc: '.jshintrc'
      }
    },
    karma: {
      options: {
        configFile: 'karma.conf.js',
        singleRun: true
      },
      unit: {},
      travis: {
        browsers: ['Firefox', 'PhantomJS']
      },
      watch: {
        singleRun: false
      }
    },
    uglify: {
      options: {
        banner: '/** Componitor v. <%= pkg.version %> */\n'
      },
      dist: {
        options: {
          mangle: false,
          compress: false,
          beautify: true,
          wrap: true
        },
        src: ['<%= sources %>'],
        dest: '<%= dist %>/componitor.js'
      },
      minify: {
        options: {
          sourceMap: true
        },
        src: ['<%= uglify.dist.dest %>'],
        dest: '<%= dist %>/componitor.min.js'
      }
    },
    ngdocs: {
      options: {
        dest: '<%= dist %>/docs',
        scripts: [
          'angular.js',
          '<%= uglify.dist.dest %>'
        ],
        title: 'componitor',
        startPage: 'api/componitor',
        titleLink: '#/api/componitor',
        html5Mode: false
      },
      api: {
        src: ['<%= sources %>', '<%= ngdocFiles %>'],
        title: 'API Documentation'
      }
    },
    watch: {
      ngdocs: {
        files: ['Gruntfile.js', '<%= sources %>', '<%= ngdocFiles %>'],
        tasks: ['after-test']
      }
    }
  });

  grunt.registerTask('before-test', ['jshint']);
  grunt.registerTask('test', ['karma:unit']);
  grunt.registerTask('after-test', ['build']);
  grunt.registerTask('build', ['clean:dist', 'uglify', 'ngdocs:api']);
  grunt.registerTask('default', ['before-test','test','after-test']);

  grunt.registerTask('travis', ['before-test', 'karma:travis']);
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {

  'use strict';

  // prevent grunt failing by test errors
  grunt.option('force', true);

  // redirect mocha node tests to the given xml
  // @see https://github.com/peerigon/xunit-file/blob/master/lib/xunit-file.js
  process.env.JUNIT_REPORT_PATH = 'build/test-results/node.xml';

  var TEST = 'spec/{env.js,**/*.spec.js}';

  var orestesMessagePath = '../orestes/orestes-message';

  grunt.initConfig({
    /**
     * Building
     * ========
     */
    browserify: {
      options: {
        browserifyOptions: {
          builtins: ['_process'],
          insertGlobals: false,
          standalone: "jspa"
        }
      },

      debug: {
        files: {
          'build/baqend.js': ['lib/index.js']
        },
        options: {
          watch: true,
          keepAlive: true,
          browserifyOptions: {
            builtins: ['_process'],
            insertGlobals: false,
            standalone: "jspa",
            debug: true
          }
        }
      },

      test: {
        files: {
          'build/baqend.js': ['lib/index.js']
        }
      },

      dist: {
        files: {
          'dist/baqend.js': ['lib/index.js']
        }
      }
    },

    /**
     * Debugging
     * =========
     */
    template: {
      debug: {
        options: {
          data: {
            scripts: grunt.file.expand(TEST)
          }
        },
        files: {
          'build/debug.html': 'debug/debug.html'
        }
      }
    },

    connect: {
      debug: {
        options: {
          open: {
            target: 'http://localhost:8000/build/debug.html',
            appName: 'Chrome'
          }
        }
      }
    },

    /**
     * Testing
     * =======
     */
    unzip: {
      test: {
        src: "build/orestes-*.zip",
        dest: "build/"
      }
    },

    run: {
      server: {
        cmd: "java",
        options: {
          cwd: "build",
          wait: false,
          ready: 5000
        }
      },
      buildMsgProject: {
        cmd: 'gradle',
        args: [
          'installApp'
        ],
        options: {
          cwd: orestesMessagePath,
          wait: true
        }
      },
      buildMsg: {
        cmd: 'java',
        args: [
            '-jar',
            'build/install/orestes-message/lib/orestes-message-1.0-SNAPSHOT.jar',
            'templates/js.ftl',
            __dirname + '/lib/message'
        ],
        options: {
          wait: true,
          cwd: orestesMessagePath
        }
      }
    },

    clean: {
      msg: {
        src: [
          'lib/message/*',
          '!lib/message/Message.js'
        ]
      }
    },

    karma: {
      dev: {
        configFile: 'karma.conf.js'
      },
      test: {
        configFile: 'karma.conf.js',
        browsers: ['PhantomJS', 'Chrome', 'Firefox'],
        singleRun: true,
        logLevel: 'ERROR',
        junitReporter: {
          outputFile: 'build/test-results/karma-phantomjs.xml'
        }
      }
    },

    mochaTest: {
      test: {
        options: {
          reporter: 'mocha-jenkins-reporter'
        },
        src: [TEST]
      }
    },

    /**
     * Distribution
     * ============
     */
    uglify: {
      options: {
        preserveComments: 'some',
        banner: ''
      },

      dist: {
        src: 'dist/baqend.js',
        dest: 'dist/baqend.min.js'
      }
    },

    jsdoc: {
      dist: {
        src: ['lib/**/*.js'],
        options: {
          destination: 'dist/doc'
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-template');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-run');
  grunt.loadNpmTasks('grunt-zip');
  grunt.loadNpmTasks('grunt-jsdoc');

  grunt.registerTask('debug', [
    'template:debug',
    'connect:debug',
    'browserify:debug'
  ]);

  grunt.registerTask('dist', [
    'browserify:dist',
    'uglify:dist',
    'jsdoc:dist'
  ]);

  grunt.registerTask('test', [
    'browserify:test',
    'unzip:test',
    'prepare:server',
    'run:server',
    'karma:test',
    'mochaTest:test',
    'stop:server'
  ]);

  grunt.registerTask('build', [
      'clean:msg',
      'run:buildMsgProject',
      'run:buildMsg'
  ]);

  grunt.registerTask('default', 'debug');

  grunt.registerTask('prepare', 'Finds the executable server jar and configuration in build folder', function() {
    var jar = grunt.file.expand({cwd: 'build'}, 'orestes-mongo*.jar')[0];
    var config = grunt.file.expand({cwd: 'build'}, '*.json')[0];

    grunt.config('run.server.args', ['-jar', jar, config]);

    grunt.log.write('Executable Jar: ' + jar + ' Used config: ' + config);
  });

};<commit_msg>add junit reporter for jenkins<commit_after>module.exports = function (grunt) {

  'use strict';

  // prevent grunt failing by test errors
  grunt.option('force', true);

  // redirect mocha node tests to the given xml
  // @see https://github.com/peerigon/xunit-file/blob/master/lib/xunit-file.js
  process.env.JUNIT_REPORT_PATH = 'build/test-results/node.xml';

  var TEST = 'spec/{env.js,**/*.spec.js}';

  var orestesMessagePath = '../orestes/orestes-message';

  grunt.initConfig({
    /**
     * Building
     * ========
     */
    browserify: {
      options: {
        browserifyOptions: {
          builtins: ['_process'],
          insertGlobals: false,
          standalone: "jspa"
        }
      },

      debug: {
        files: {
          'build/baqend.js': ['lib/index.js']
        },
        options: {
          watch: true,
          keepAlive: true,
          browserifyOptions: {
            builtins: ['_process'],
            insertGlobals: false,
            standalone: "jspa",
            debug: true
          }
        }
      },

      test: {
        files: {
          'build/baqend.js': ['lib/index.js']
        }
      },

      dist: {
        files: {
          'dist/baqend.js': ['lib/index.js']
        }
      }
    },

    /**
     * Debugging
     * =========
     */
    template: {
      debug: {
        options: {
          data: {
            scripts: grunt.file.expand(TEST)
          }
        },
        files: {
          'build/debug.html': 'debug/debug.html'
        }
      }
    },

    connect: {
      debug: {
        options: {
          open: {
            target: 'http://localhost:8000/build/debug.html',
            appName: 'Chrome'
          }
        }
      }
    },

    /**
     * Testing
     * =======
     */
    unzip: {
      test: {
        src: "build/orestes-*.zip",
        dest: "build/"
      }
    },

    run: {
      server: {
        cmd: "java",
        options: {
          cwd: "build",
          wait: false,
          ready: 5000
        }
      },
      buildMsgProject: {
        cmd: 'gradle',
        args: [
          'installApp'
        ],
        options: {
          cwd: orestesMessagePath,
          wait: true
        }
      },
      buildMsg: {
        cmd: 'java',
        args: [
            '-jar',
            'build/install/orestes-message/lib/orestes-message-1.0-SNAPSHOT.jar',
            'templates/js.ftl',
            __dirname + '/lib/message'
        ],
        options: {
          wait: true,
          cwd: orestesMessagePath
        }
      }
    },

    clean: {
      msg: {
        src: [
          'lib/message/*',
          '!lib/message/Message.js'
        ]
      }
    },

    karma: {
      dev: {
        configFile: 'karma.conf.js'
      },
      test: {
        configFile: 'karma.conf.js',
        browsers: ['PhantomJS', 'Chrome', 'Firefox'],
        reporters: ['junit'],
        singleRun: true,
        logLevel: 'ERROR',
        junitReporter: {
          outputFile: 'build/test-results/karma-phantomjs.xml'
        }
      }
    },

    mochaTest: {
      test: {
        options: {
          reporter: 'mocha-jenkins-reporter'
        },
        src: [TEST]
      }
    },

    /**
     * Distribution
     * ============
     */
    uglify: {
      options: {
        preserveComments: 'some',
        banner: ''
      },

      dist: {
        src: 'dist/baqend.js',
        dest: 'dist/baqend.min.js'
      }
    },

    jsdoc: {
      dist: {
        src: ['lib/**/*.js'],
        options: {
          destination: 'dist/doc'
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-browserify');
  grunt.loadNpmTasks('grunt-template');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-run');
  grunt.loadNpmTasks('grunt-zip');
  grunt.loadNpmTasks('grunt-jsdoc');

  grunt.registerTask('debug', [
    'template:debug',
    'connect:debug',
    'browserify:debug'
  ]);

  grunt.registerTask('dist', [
    'browserify:dist',
    'uglify:dist',
    'jsdoc:dist'
  ]);

  grunt.registerTask('test', [
    'browserify:test',
    'unzip:test',
    'prepare:server',
    'run:server',
    'karma:test',
    'mochaTest:test',
    'stop:server'
  ]);

  grunt.registerTask('build', [
      'clean:msg',
      'run:buildMsgProject',
      'run:buildMsg'
  ]);

  grunt.registerTask('default', 'debug');

  grunt.registerTask('prepare', 'Finds the executable server jar and configuration in build folder', function() {
    var jar = grunt.file.expand({cwd: 'build'}, 'orestes-mongo*.jar')[0];
    var config = grunt.file.expand({cwd: 'build'}, '*.json')[0];

    grunt.config('run.server.args', ['-jar', jar, config]);

    grunt.log.write('Executable Jar: ' + jar + ' Used config: ' + config);
  });

};<|endoftext|>


<commit_before>"use strict"

var config = require('./app/config')
var _ = require('underscore')
var fs = require('fs')

module.exports = function (grunt) {
  // Config
  var external = ['react', 'react-dom', 'jquery', 'underscore'],
    scss_src = 'style/main.scss',
    static_src = 'static',
    module_src = 'app/modules',
    module_dest = 'modules',
    prod_dest = 'dist',
    dev_dest = 'public',
    css_dest = 'main.css',
    vendor_dest = 'vendor.js',
    asset_map_dest = 'assetMap.json',
    browserify_options_dev,
    browserify_options_prod,
    browserify_options_vendor_dev,
    browserify_options_vendor_prod,
    browserify_files_dev,
    browserify_files_prod,
    browserify_vendor_files_dev =  { [`${dev_dest}/${vendor_dest}`]: external },
    browserify_vendor_files_prod = { [`${prod_dest}/${vendor_dest}`]: external }

  browserify_options_dev =  {
    transform: [ ['babelify', {presets: ['es2015']}] ],
    watch: true,
    keepAlive: true,
    external: external,
    browserifyOptions: {
      debug: true,
      extensions: '.js'
    },
    watchifyOptions: {
      poll: 100,
      debug: true
    }
  }

  // extend dev options
  browserify_options_prod = {}
  _.extend(browserify_options_prod, browserify_options_dev, {
    watch: false,
    keepAlive: false,
    browserifyOptions: {
      debug: false
    },
    watchifyOptions: {}
  })
  // uglify prod build
  browserify_options_prod.transform.push('uglifyify')

  // vendor browserify options
  browserify_options_vendor_dev = {
    require: external
  }
  browserify_options_vendor_prod = {}
  _.extend(browserify_options_vendor_prod, browserify_options_vendor_dev, {
    transform: ['uglifyify']
  })

  // generate files from modules array
  browserify_files_dev = {}
  browserify_files_prod = {}

  for (let module of config.modules) {
    browserify_files_dev[`${dev_dest}/${module_dest}/${module}.js`] =
      browserify_files_prod[`${prod_dest}/${module_dest}/${module}.js`] =
      [`${module_src}/${module}/client.js`]
  }

  // Project configuration
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    browserify: {
      vendor_dev: {
        files: browserify_vendor_files_dev,
        options: browserify_options_vendor_dev
      },
      vendor_prod: {
        files: browserify_vendor_files_prod,
        options: browserify_options_vendor_prod
      },
      dev: {
        files: browserify_files_dev,
        options: browserify_options_dev
      },
      prod: {
        files: browserify_files_prod,
        options: browserify_options_prod
      }
    },
    sass: {
      dev: {
        files: {
          [`${dev_dest}/${css_dest}`]: scss_src
        }
      },
      prod: {
        files: {
          [`${prod_dest}/${css_dest}`]: scss_src
        }
      }
    },
    postcss: {
      options: {
        processors: [
          require('autoprefixer')({browsers: 'last 2 versions'}),
          require('cssnano')(),
        ]
      },
      dev: {
        src: `${dev_dest}/${css_dest}`,
        options: {
          map: true
        }
      },
      prod: {
        src: `${prod_dest}/${css_dest}`,
        options: {
          map: false
        },
      },
    },
    rsync: {
      options: {
        args: ["--verbose"],
        exclude: [".git*"],
        recursive: true
      },
      dev: {
        options: {
          src: static_src,
          dest: dev_dest
        }
      },
      prod: {
        options: {
          src: static_src,
          dest: prod_dest
        }
      },
    },
    filerev: {
      options: {},
      prod: {
        src: `${prod_dest}/**/*.{css,js,pdf,png,ico}`,
      },
    },
    watch: {
      style: {
        files: 'style/**/*.scss',
        tasks: ['sass:dev', 'postcss:dev']
      },
      rsync: {
        files: `${static_src}/**/*`,
        tasks: ['rsync:dev']
      },
    },
    s3: {
      options: {
        accessKeyId: process.env.S3_ACCESS_KEY_ID,
        secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
        bucket: process.env.S3_BUCKET,
        region: process.env.S3_REGION,
        headers: {
          CacheControl: 31536000 /* 1yr */
        }
      },
      prod: {
        cwd: prod_dest,
        src: '**'
      },
    },
    clean: {
      dev: [`${dev_dest}/**/*`],
      prod: [`${prod_dest}/**/*`]
    }
  })

  // Load plugins
  grunt.loadNpmTasks('grunt-browserify')
  grunt.loadNpmTasks('grunt-contrib-sass')
  grunt.loadNpmTasks('grunt-postcss')
  grunt.loadNpmTasks('grunt-contrib-watch')
  grunt.loadNpmTasks('grunt-rsync')
  grunt.loadNpmTasks('grunt-filerev')
  grunt.loadNpmTasks('grunt-contrib-clean')
  grunt.loadNpmTasks('grunt-aws')

  // Default is run and watch everything BUT browserify
  grunt.registerTask('default', [
    'clean:dev', 'sass:dev', 'postcss:dev', 'rsync:dev', 'watch'
  ])

  // TODO: break this out better
  grunt.registerTask('write_filerev', function() {
    var finalPaths = {}
    var substrIndex = prod_dest.length
    for (var orig in grunt.filerev.summary) {
      finalPaths[orig.substring(substrIndex)] = grunt.filerev.summary[orig].substring(substrIndex)
    }
    fs.writeFileSync(`${prod_dest}/${asset_map_dest}`, JSON.stringify(finalPaths))
  })

  // Build for production
  grunt.registerTask('production', [
    'clean:prod', 'sass:prod', 'postcss:prod', 'rsync:prod',
    'browserify:vendor_prod', 'browserify:prod', 'filerev:prod', 'write_filerev'
  ])
}
<commit_msg>Wrote custom filerev replacer (for now)<commit_after>"use strict"

var config = require('./app/config')
var _ = require('underscore')
var fs = require('fs')

module.exports = function (grunt) {
  // Config
  var external = ['react', 'react-dom', 'jquery', 'underscore'],
    scss_src = 'style/main.scss',
    static_src = 'static',
    module_src = 'app/modules',
    module_dest = 'modules',
    prod_dest = 'dist',
    dev_dest = 'public',
    css_dest = 'main.css',
    vendor_dest = 'vendor.js',
    asset_map_dest = 'assetMap.json',
    browserify_options_dev,
    browserify_options_prod,
    browserify_options_vendor_dev,
    browserify_options_vendor_prod,
    browserify_files_dev,
    browserify_files_prod,
    browserify_vendor_files_dev =  { [`${dev_dest}/${vendor_dest}`]: external },
    browserify_vendor_files_prod = { [`${prod_dest}/${vendor_dest}`]: external }

  browserify_options_dev =  {
    transform: [ ['babelify', {presets: ['es2015']}] ],
    watch: true,
    keepAlive: true,
    external: external,
    browserifyOptions: {
      debug: true,
      extensions: '.js'
    },
    watchifyOptions: {
      poll: 100,
      debug: true
    }
  }

  // extend dev options
  browserify_options_prod = {}
  _.extend(browserify_options_prod, browserify_options_dev, {
    watch: false,
    keepAlive: false,
    browserifyOptions: {
      debug: false
    },
    watchifyOptions: {}
  })
  // uglify prod build
  browserify_options_prod.transform.push('uglifyify')

  // vendor browserify options
  browserify_options_vendor_dev = {
    require: external
  }
  browserify_options_vendor_prod = {}
  _.extend(browserify_options_vendor_prod, browserify_options_vendor_dev, {
    transform: ['uglifyify']
  })

  // generate files from modules array
  browserify_files_dev = {}
  browserify_files_prod = {}

  for (let module of config.modules) {
    browserify_files_dev[`${dev_dest}/${module_dest}/${module}.js`] =
      browserify_files_prod[`${prod_dest}/${module_dest}/${module}.js`] =
      [`${module_src}/${module}/client.js`]
  }

  // Project configuration
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    browserify: {
      vendor_dev: {
        files: browserify_vendor_files_dev,
        options: browserify_options_vendor_dev
      },
      vendor_prod: {
        files: browserify_vendor_files_prod,
        options: browserify_options_vendor_prod
      },
      dev: {
        files: browserify_files_dev,
        options: browserify_options_dev
      },
      prod: {
        files: browserify_files_prod,
        options: browserify_options_prod
      }
    },
    sass: {
      dev: {
        files: {
          [`${dev_dest}/${css_dest}`]: scss_src
        }
      },
      prod: {
        files: {
          [`${prod_dest}/${css_dest}`]: scss_src
        }
      }
    },
    postcss: {
      options: {
        processors: [
          require('autoprefixer')({browsers: 'last 2 versions'}),
          require('cssnano')(),
        ]
      },
      dev: {
        src: `${dev_dest}/${css_dest}`,
        options: {
          map: true
        }
      },
      prod: {
        src: `${prod_dest}/${css_dest}`,
        options: {
          map: false
        },
      },
    },
    rsync: {
      options: {
        args: ["--verbose"],
        exclude: [".git*"],
        recursive: true
      },
      dev: {
        options: {
          src: static_src,
          dest: dev_dest
        }
      },
      prod: {
        options: {
          src: static_src,
          dest: prod_dest
        }
      },
    },
    filerev: {
      options: {},
      prod: {
        src: `${prod_dest}/**/*.{css,js,pdf,png,ico}`,
      },
    },
    watch: {
      style: {
        files: 'style/**/*.scss',
        tasks: ['sass:dev', 'postcss:dev']
      },
      rsync: {
        files: `${static_src}/**/*`,
        tasks: ['rsync:dev']
      },
    },
    s3: {
      options: {
        accessKeyId: process.env.S3_ACCESS_KEY_ID,
        secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
        bucket: process.env.S3_BUCKET,
        region: process.env.S3_REGION,
        headers: {
          CacheControl: 31536000 /* 1yr */
        }
      },
      prod: {
        cwd: prod_dest,
        src: '**'
      },
    },
    clean: {
      dev: [`${dev_dest}/**/*`],
      prod: [`${prod_dest}/**/*`]
    }
  })

  // Load plugins
  grunt.loadNpmTasks('grunt-browserify')
  grunt.loadNpmTasks('grunt-contrib-sass')
  grunt.loadNpmTasks('grunt-postcss')
  grunt.loadNpmTasks('grunt-contrib-watch')
  grunt.loadNpmTasks('grunt-rsync')
  grunt.loadNpmTasks('grunt-filerev')
  grunt.loadNpmTasks('grunt-contrib-clean')
  grunt.loadNpmTasks('grunt-aws')

  // Default is run and watch everything BUT browserify
  grunt.registerTask('default', [
    'clean:dev', 'sass:dev', 'postcss:dev', 'rsync:dev', 'watch'
  ])

  // TODO: break this out better
  grunt.registerTask('write_filerev', () => {
    var finalPaths = {}
    var substrIndex = prod_dest.length
    for (var orig in grunt.filerev.summary) {
      finalPaths[orig.substring(substrIndex)] = grunt.filerev.summary[orig].substring(substrIndex)
    }
    fs.writeFileSync(`${prod_dest}/${asset_map_dest}`, JSON.stringify(finalPaths))
  })

  // TODO: break this better
  grunt.registerTask('filerev_apply', () => {
    var fs = require('fs'),
      substrIndex = prod_dest.length,
      cssFile = grunt.filerev.summary[`${prod_dest}/main.css`],
      content = fs.readFileSync(cssFile, "utf8"),
      prefix = process.env.CDN_ROOT ? '//' + process.env.CDN_ROOT : ''

    content = content.replace(/url\(["']?([\w\@\.\-\/]+)["']?\)/gi, (match, p1) => {
      var rev_file = prefix + grunt.filerev.summary[`${prod_dest}${p1}`].substring(substrIndex)
      console.log(`Replaced ${p1} with ${rev_file}`)
      return `url(${rev_file})`
    })

    fs.writeFileSync(cssFile, content)
  })

  // Build for production
  grunt.registerTask('production', [
    'clean:prod', 'sass:prod', 'postcss:prod', 'rsync:prod',
    'browserify:vendor_prod', 'browserify:prod', 'filerev:prod', 'filerev_apply',
    'write_filerev'
  ])
}
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  require('time-grunt')(grunt);

  require('jit-grunt')(grunt);

  grunt.initConfig({
    autoprefixer: {
      options: {
        browsers: ['last 2 versions']
      },
      build: {
        src: 'assets/css/screen.css',
        dest: 'assets/css/screen.css'
      },
      jekyll: {
        src: '_site/assets/css/screen.css',
        dest: '_site/assets/css/screen.css'
      }
    },

    clean: {
      site_assets: [
        '_site/assets/images',
        '_site/assets/media'
      ],
      css_maps: [
        'assets/css/**/*.map'
      ]
    },

    copy: {
      css: {
        files: [{
          expand: true,
          src: ['assets/css/**'],
          dest: '_site/'
        }]
      },
      critical_css: {
        files: [{
          expand: true,
          flatten: true,
          src: ['_includes/critical/css/src/**'],
          dest: '_includes/critical/css/',
        }]
      },
      normalize: {
        expand: true,
        flatten: true,
        filter: 'isFile',
        src: 'bower_components/normalize-css/_normalize.css',
        dest: 'assets/sass/core/',
        rename: function(dest, src) {
          return dest + src.replace('.css', '.scss');
        }
      }
    },

    concat: {
      build: {
        files: {
          'assets/js/jonsuh.js': [
            'assets/js/vendor/promise.js',
            'bower_components/picturefill/dist/picturefill.js',
            'bower_components/fontfaceobserver/fontfaceobserver.js',
            'assets/js/src/utility.js',
            'assets/js/src/social.js',
            'assets/js/src/work.js',
            'assets/js/src/app.js'
          ],
          'assets/js/chart.js': [
            'bower_components/chartjs/src/Chart.Core.js',
            'bower_components/chartjs/src/Chart.Line.js',
            'assets/js/vendor/Chart.legend.js'
          ],
          'assets/js/flickity.js': ['bower_components/flickity/dist/flickity.pkgd.js'],
          'assets/js/blog/https-increased-organic-search-impressions-by-144-percent.js': ['assets/js/src/blog/https-increased-organic-search-impressions-by-144-percent.js'],
          '_includes/critical/js/jonsuh.js': [
            'bower_components/loadcss/loadCSS.js',
            'assets/js/src/critical.js'
          ],
        }
      }
    },

    criticalcss: {
      options: {
        filename: '/Users/jsuh/Work/jonsuh.com/assets/css/screen.css',
        width: 1025,
        height: 700,
        buffer: 800*1024
      },
      home: {
        options: {
          url: 'http://jonsuh.local/',
          outputfile: '_includes/critical/css/home.css',
        }
      },
      about: {
        options: {
          url: 'http://jonsuh.local/about/',
          outputfile: '_includes/critical/css/about.css',
        }
      },
      blog: {
        options: {
          url: 'http://jonsuh.local/blog/',
          outputfile: '_includes/critical/css/blog.css',
        }
      },
      blog_post: {
        options: {
          url: 'http://jonsuh.local/blog/font-loading-with-font-events/',
          outputfile: '_includes/critical/css/blog-post.css',
        }
      },
      contact: {
        options: {
          url: 'http://jonsuh.local/contact/',
          outputfile: '_includes/critical/css/contact.css',
        }
      },
      work: {
        options: {
          url: 'http://jonsuh.local/work/',
          outputfile: '_includes/critical/css/work.css',
        }
      }
    },

    jekyll: {
      options: {
        bundleExec: true
      },
      build: {
        options: {
          config: '_config.yml'
        }
      },
      watch: {
        options: {
          config: '_config.yml',
          watch: true
        }
      },
      staging: {
        options: {
          config: '_config.yml,_config.staging.yml'
        }
      },
      production: {
        options: {
          config: '_config.yml,_config.production.yml'
        }
      }
    },

    sass: {
      options: {
        includePaths: [
          'bower_components/bourbon/app/assets/stylesheets',
          'bower_components/mq-sass/stylesheets',
          'bower_components/neat/app/assets/stylesheets'
        ]
      },
      build: {
        files: [{
          expand: true,
          cwd: 'assets/sass/',
          src: ['*.scss', 'blog/*.scss'],
          dest: 'assets/css/',
          ext: '.css'
        }]
      },
      jekyll: {
        files: [{
          expand: true,
          cwd: 'assets/sass/',
          src: ['*.scss', 'blog/*.scss'],
          dest: '_site/assets/css/',
          ext: '.css'
        }]
      }
    },

    concurrent: {
      watch: {
        options: {
          logConcurrentOutput: true
        },
        tasks: ['jekyll:watch', 'watch'],
      }
    },

    cssmin: {
      options: {
        report: 'min'
      },
      critical: {
        files: [{
          expand: true,
          cwd: '_includes/critical/css/',
          src: ['*.css'],
          dest: '_includes/critical/css/',
          ext: '.css'
        }]
      },
      production: {
        files: [{
          expand: true,
          cwd: 'assets/css/',
          src: ['**/*.css'],
          dest: 'assets/css/',
          ext: '.css'
        }]
      }
    },

    uglify: {
      options: {
        report: 'gzip'
      },
      critical: {
        files: [{
          expand: true,
          cwd: '_includes/critical/js/',
          src: [
            '**/*.js'
          ],
          dest: '_includes/critical/js/',
          ext: '.js'
        }]
      },
      production: {
        files: [{
          expand: true,
          cwd: 'assets/js/',
          src: [
            '**/*.js',
            '!src/**/*.js',
            '!vendor/**/*.js'
          ],
          dest: 'assets/js/',
          ext: '.js'
        }]
      },
    },

    imagemin: {
      production: {
        options: {
          optimizationLevel: 7,
        },
        files: [{
          expand: true,
          cwd: 'assets/images',
          src: [
            '**/*.{gif,jpg,png}',
            '!_site'
          ],
          dest: 'assets/images'
        }]
      }
    },

    rsync: {
      options: {
        args: ["-a"],
        host: '' // PARTS OF THIS LINE HAVE BEEN REMOVED
      },
      images_staging: {
        options: {
          src: '_site/assets/images/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      },
      media_staging: {
        options: {
          src: '_site/assets/media/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      },
      images_production: {
        options: {
          src: '_site/assets/images/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      },
      media_production: {
        options: {
          src: '_site/assets/media/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      }
    },

    shell: {
      options: {
        stdout: true,
        stderr: true
      },
      caniuse: {
        command: 'npm update caniuse-db'
      },
      jekyll: {
        command: 'bundle exec jekyll build --watch'
      },
      deploy_staging: {
        command: 'bundle exec cap staging deploy'
      },
      deploy_production: {
        command: 'bundle exec cap production deploy'
      }
    },

    watch: {
      grunt: {
        files: ['Gruntfile.js'],
        tasks: ['concat:build']
      },
      js: {
        files: ['assets/js/src/**/*.js'],
        tasks: ['concat:build']
      },
      sass: {
        files: ['assets/sass/**/*.scss'],
        tasks: ['sass:jekyll', 'autoprefixer:jekyll']
      }
    },

    browserSync: {
      watch: {
        options: {
          watchTask: true,
          proxy: 'http://jonsuh.local'
        },
        bsFiles: {
          src: [
            '_site/assets/css/*.css'
          ]
        }
      }
    }
  });

  grunt.registerTask('build', [
    'newer:copy:normalize',
    'sass:build',
    'autoprefixer:build',
    'copy:critical_css',
    'concat:build',
    'jekyll:build'
  ]);

  grunt.registerTask('default', [
    'newer:copy:normalize',
    'sass:build',
    'autoprefixer:build',
    'copy:critical_css',
    'concat:build',
    'browserSync',
    'concurrent:watch'
  ]);

  grunt.registerTask('production', [
    'copy:normalize',
    'sass:build',
    'clean:css_maps',
    'autoprefixer:build',
    'concat:build',
    'cssmin:production',
    'copy:critical_css',
    'cssmin:critical',
    'uglify:production',
    'uglify:critical',
    'jekyll:production'
  ]);

  grunt.registerTask('deploy:staging', [
    'build',                  // Grunt build
    'jekyll:staging',         // Rebuild Jekyll for staging
    'rsync:images_staging',   // Rsync _site/assets/images to staging environment
    'rsync:media_staging',    // Rsync _site/assets/media to staging environment
    'clean:site_assets',      // Clean _site/assets/(images,media) to prep for deployment
    'shell:deploy_staging'    // Capistrano deploy to staging environment
  ]);

  grunt.registerTask('deploy:production', [
    'production',              // Grunt production
    'clean:site_assets',       // Clean _site/assets/(images,media) to prep for deployment
    'shell:deploy_production'  // Capistrano deploy to production environment
  ]);

  grunt.registerTask('deploy:production:all', [
    'production',              // Grunt production
    'rsync:images_production', // Rsync _site/assets/images to production environment
    'rsync:media_production',  // Rsync _site/assets/media to production environment
    'clean:site_assets',       // Clean _site/assets/(images,media) to prep for deployment
    'shell:deploy_production'  // Capistrano deploy to production environment
  ]);
};<commit_msg>Grunt copy robots.txt tasks.<commit_after>module.exports = function(grunt) {
  require('time-grunt')(grunt);

  require('jit-grunt')(grunt);

  grunt.initConfig({
    autoprefixer: {
      options: {
        browsers: ['last 2 versions']
      },
      build: {
        src: 'assets/css/screen.css',
        dest: 'assets/css/screen.css'
      },
      jekyll: {
        src: '_site/assets/css/screen.css',
        dest: '_site/assets/css/screen.css'
      }
    },

    clean: {
      site_assets: [
        '_site/assets/images',
        '_site/assets/media'
      ],
      css_maps: [
        'assets/css/**/*.map'
      ]
    },

    copy: {
      css: {
        files: [{
          expand: true,
          src: ['assets/css/**'],
          dest: '_site/'
        }]
      },
      critical_css: {
        files: [{
          expand: true,
          flatten: true,
          src: ['_includes/critical/css/src/**'],
          dest: '_includes/critical/css/',
        }]
      },
      normalize: {
        expand: true,
        flatten: true,
        filter: 'isFile',
        src: 'bower_components/normalize-css/_normalize.css',
        dest: 'assets/sass/core/',
        rename: function(dest, src) {
          return dest + src.replace('.css', '.scss');
        }
      },
      robots_staging: {
        src: 'robots.staging.txt',
        dest: 'robots.txt'
      },
      robots_production: {
        src: 'robots.production.txt',
        dest: 'robots.txt'
      }
    },

    concat: {
      build: {
        files: {
          'assets/js/jonsuh.js': [
            'assets/js/vendor/promise.js',
            'bower_components/picturefill/dist/picturefill.js',
            'bower_components/fontfaceobserver/fontfaceobserver.js',
            'assets/js/src/utility.js',
            'assets/js/src/social.js',
            'assets/js/src/work.js',
            'assets/js/src/app.js'
          ],
          'assets/js/chart.js': [
            'bower_components/chartjs/src/Chart.Core.js',
            'bower_components/chartjs/src/Chart.Line.js',
            'assets/js/vendor/Chart.legend.js'
          ],
          'assets/js/flickity.js': ['bower_components/flickity/dist/flickity.pkgd.js'],
          'assets/js/blog/https-increased-organic-search-impressions-by-144-percent.js': ['assets/js/src/blog/https-increased-organic-search-impressions-by-144-percent.js'],
          '_includes/critical/js/jonsuh.js': [
            'bower_components/loadcss/loadCSS.js',
            'assets/js/src/critical.js'
          ],
        }
      }
    },

    criticalcss: {
      options: {
        filename: '/Users/jsuh/Work/jonsuh.com/assets/css/screen.css',
        width: 1025,
        height: 700,
        buffer: 800*1024
      },
      home: {
        options: {
          url: 'http://jonsuh.local/',
          outputfile: '_includes/critical/css/home.css',
        }
      },
      about: {
        options: {
          url: 'http://jonsuh.local/about/',
          outputfile: '_includes/critical/css/about.css',
        }
      },
      blog: {
        options: {
          url: 'http://jonsuh.local/blog/',
          outputfile: '_includes/critical/css/blog.css',
        }
      },
      blog_post: {
        options: {
          url: 'http://jonsuh.local/blog/font-loading-with-font-events/',
          outputfile: '_includes/critical/css/blog-post.css',
        }
      },
      contact: {
        options: {
          url: 'http://jonsuh.local/contact/',
          outputfile: '_includes/critical/css/contact.css',
        }
      },
      work: {
        options: {
          url: 'http://jonsuh.local/work/',
          outputfile: '_includes/critical/css/work.css',
        }
      }
    },

    jekyll: {
      options: {
        bundleExec: true
      },
      build: {
        options: {
          config: '_config.yml'
        }
      },
      watch: {
        options: {
          config: '_config.yml',
          watch: true
        }
      },
      staging: {
        options: {
          config: '_config.yml,_config.staging.yml'
        }
      },
      production: {
        options: {
          config: '_config.yml,_config.production.yml'
        }
      }
    },

    sass: {
      options: {
        includePaths: [
          'bower_components/bourbon/app/assets/stylesheets',
          'bower_components/mq-sass/stylesheets',
          'bower_components/neat/app/assets/stylesheets'
        ]
      },
      build: {
        files: [{
          expand: true,
          cwd: 'assets/sass/',
          src: ['*.scss', 'blog/*.scss'],
          dest: 'assets/css/',
          ext: '.css'
        }]
      },
      jekyll: {
        files: [{
          expand: true,
          cwd: 'assets/sass/',
          src: ['*.scss', 'blog/*.scss'],
          dest: '_site/assets/css/',
          ext: '.css'
        }]
      }
    },

    concurrent: {
      watch: {
        options: {
          logConcurrentOutput: true
        },
        tasks: ['jekyll:watch', 'watch'],
      }
    },

    cssmin: {
      options: {
        report: 'min'
      },
      critical: {
        files: [{
          expand: true,
          cwd: '_includes/critical/css/',
          src: ['*.css'],
          dest: '_includes/critical/css/',
          ext: '.css'
        }]
      },
      production: {
        files: [{
          expand: true,
          cwd: 'assets/css/',
          src: ['**/*.css'],
          dest: 'assets/css/',
          ext: '.css'
        }]
      }
    },

    uglify: {
      options: {
        report: 'gzip'
      },
      critical: {
        files: [{
          expand: true,
          cwd: '_includes/critical/js/',
          src: [
            '**/*.js'
          ],
          dest: '_includes/critical/js/',
          ext: '.js'
        }]
      },
      production: {
        files: [{
          expand: true,
          cwd: 'assets/js/',
          src: [
            '**/*.js',
            '!src/**/*.js',
            '!vendor/**/*.js'
          ],
          dest: 'assets/js/',
          ext: '.js'
        }]
      },
    },

    imagemin: {
      production: {
        options: {
          optimizationLevel: 7,
        },
        files: [{
          expand: true,
          cwd: 'assets/images',
          src: [
            '**/*.{gif,jpg,png}',
            '!_site'
          ],
          dest: 'assets/images'
        }]
      }
    },

    rsync: {
      options: {
        args: ["-a"],
        host: '' // PARTS OF THIS LINE HAVE BEEN REMOVED
      },
      images_staging: {
        options: {
          src: '_site/assets/images/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      },
      media_staging: {
        options: {
          src: '_site/assets/media/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      },
      images_production: {
        options: {
          src: '_site/assets/images/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      },
      media_production: {
        options: {
          src: '_site/assets/media/',
          dest: '', // PARTS OF THIS LINE HAVE BEEN REMOVED
        }
      }
    },

    shell: {
      options: {
        stdout: true,
        stderr: true
      },
      caniuse: {
        command: 'npm update caniuse-db'
      },
      jekyll: {
        command: 'bundle exec jekyll build --watch'
      },
      deploy_staging: {
        command: 'bundle exec cap staging deploy'
      },
      deploy_production: {
        command: 'bundle exec cap production deploy'
      }
    },

    watch: {
      grunt: {
        files: ['Gruntfile.js'],
        tasks: ['concat:build']
      },
      js: {
        files: ['assets/js/src/**/*.js'],
        tasks: ['concat:build']
      },
      sass: {
        files: ['assets/sass/**/*.scss'],
        tasks: ['sass:jekyll', 'autoprefixer:jekyll']
      }
    },

    browserSync: {
      watch: {
        options: {
          watchTask: true,
          proxy: 'http://jonsuh.local'
        },
        bsFiles: {
          src: [
            '_site/assets/css/*.css'
          ]
        }
      }
    }
  });

  grunt.registerTask('build', [
    'newer:copy:normalize',
    'sass:build',
    'autoprefixer:build',
    'copy:critical_css',
    'concat:build',
    'jekyll:build'
  ]);

  grunt.registerTask('default', [
    'newer:copy:normalize',
    'sass:build',
    'autoprefixer:build',
    'copy:critical_css',
    'concat:build',
    'browserSync',
    'concurrent:watch'
  ]);

  grunt.registerTask('production', [
    'copy:normalize',
    'sass:build',
    'clean:css_maps',
    'autoprefixer:build',
    'concat:build',
    'cssmin:production',
    'copy:critical_css',
    'cssmin:critical',
    'uglify:production',
    'uglify:critical',
    'jekyll:production'
  ]);

  grunt.registerTask('deploy:staging', [
    'build',                  // Grunt build
    'jekyll:staging',         // Rebuild Jekyll for staging
    'rsync:images_staging',   // Rsync _site/assets/images to staging environment
    'rsync:media_staging',    // Rsync _site/assets/media to staging environment
    'clean:site_assets',      // Clean _site/assets/(images,media) to prep for deployment
    'copy:robots_staging',    // Copy the staging version of robots.txt for deployment
    'shell:deploy_staging'    // Capistrano deploy to staging environment
  ]);

  grunt.registerTask('deploy:production', [
    'production',              // Grunt production
    'clean:site_assets',       // Clean _site/assets/(images,media) to prep for deployment
    'copy:robots_production',  // Copy the production version of robots.txt for deployment
    'shell:deploy_production'  // Capistrano deploy to production environment
  ]);

  grunt.registerTask('deploy:production:all', [
    'production',              // Grunt production
    'rsync:images_production', // Rsync _site/assets/images to production environment
    'rsync:media_production',  // Rsync _site/assets/media to production environment
    'clean:site_assets',       // Clean _site/assets/(images,media) to prep for deployment
    'copy:robots_production',  // Copy the production version of robots.txt for deployment
    'shell:deploy_production'  // Capistrano deploy to production environment
  ]);
};<|endoftext|>


<commit_before>const STABLE = new Set([
  'claimsParameter',
  'clientCredentials',
  'deviceFlow',
  'devInteractions',
  'encryption',
  'introspection',
  'jwtUserinfo',
  'mTLS',
  'registration',
  'registrationManagement',
  'requestObjects',
  'revocation',
  'rpInitiatedLogout',
  'userinfo',
]);

const DRAFTS = new Map(Object.entries({
  backchannelLogout: {
    name: 'OpenID Connect Back-Channel Logout 1.0 - draft 06',
    type: 'OIDF AB/Connect Working Group draft',
    url: 'https://openid.net/specs/openid-connect-backchannel-1_0-06.html',
    version: [4, 'draft-04', 'draft-05', 'draft-06'],
  },
  ietfJWTAccessTokenProfile: {
    name: 'JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens - draft 05',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-05',
    version: [2, 'draft-02', 'draft-03', 'draft-04', 'draft-05'],
  },
  fapiRW: {
    name: 'Financial-grade API - Part 2: Read and Write API Security Profile',
    type: 'OIDF FAPI Working Group draft',
    url: 'https://openid.net/specs/openid-financial-api-part-2-ID2.html',
    version: ['id02-rev.3', 'implementers-draft-02'],
  },
  dPoP: {
    name: 'OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-dpop-01',
    version: ['draft-01'],
  },
  frontchannelLogout: {
    name: 'OpenID Connect Front-Channel Logout 1.0 - draft 04',
    type: 'OIDF AB/Connect Working Group draft',
    url: 'https://openid.net/specs/openid-connect-frontchannel-1_0-04.html',
    version: [2, 'draft-02', 'draft-03', 'draft-04'],
  },
  jwtIntrospection: {
    name: 'JWT Response for OAuth Token Introspection - draft 09',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-jwt-introspection-response-09',
    version: ['draft-09'],
  },
  jwtResponseModes: {
    name: 'JWT Secured Authorization Response Mode for OAuth 2.0 - Implementer's Draft 01',
    type: 'OIDF FAPI WG Implementer's Draft',
    url: 'https://openid.net/specs/openid-financial-api-jarm-ID1.html',
    version: [1, 2, 'draft-02', 'implementers-draft-01'],
  },
  pushedAuthorizationRequests: {
    name: 'OAuth 2.0 Pushed Authorization Requests - draft 03',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-par-03',
    version: [0, 'individual-draft-01', 'draft-00', 'draft-01', 'draft-02', 'draft-03'],
  },
  resourceIndicators: {
    name: 'Resource Indicators for OAuth 2.0 - draft 08',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-resource-indicators-08',
    version: [2, 3, 4, 5, 6, 7, 'draft-07', 'draft-08'],
  },
  sessionManagement: {
    name: 'OpenID Connect Session Management 1.0 - draft 30',
    type: 'OIDF AB/Connect Working Group draft',
    url: 'https://openid.net/specs/openid-connect-session-1_0-30.html',
    version: [28, 'draft-28', 'draft-29', 'draft-30'],
  },
  webMessageResponseMode: {
    name: 'OAuth 2.0 Web Message Response Mode - draft 00',
    type: 'Individual draft',
    url: 'https://tools.ietf.org/html/draft-sakimura-oauth-wmrm-00',
    version: [0, 'id-00', 'individual-draft-00'],
  },
  issAuthResp: {
    name: 'OAuth 2.0 Authorization Server Issuer Identifier in Authorization Response - draft 00',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-iss-auth-resp-00',
    version: ['draft-00'],
  },
}));

module.exports = {
  DRAFTS,
  STABLE,
};
<commit_msg>fix: botched 6.30.0 release with a syntax error<commit_after>const STABLE = new Set([
  'claimsParameter',
  'clientCredentials',
  'deviceFlow',
  'devInteractions',
  'encryption',
  'introspection',
  'jwtUserinfo',
  'mTLS',
  'registration',
  'registrationManagement',
  'requestObjects',
  'revocation',
  'rpInitiatedLogout',
  'userinfo',
]);

const DRAFTS = new Map(Object.entries({
  backchannelLogout: {
    name: 'OpenID Connect Back-Channel Logout 1.0 - draft 06',
    type: 'OIDF AB/Connect Working Group draft',
    url: 'https://openid.net/specs/openid-connect-backchannel-1_0-06.html',
    version: [4, 'draft-04', 'draft-05', 'draft-06'],
  },
  ietfJWTAccessTokenProfile: {
    name: 'JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens - draft 05',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-05',
    version: [2, 'draft-02', 'draft-03', 'draft-04', 'draft-05'],
  },
  fapiRW: {
    name: 'Financial-grade API - Part 2: Read and Write API Security Profile',
    type: 'OIDF FAPI Working Group draft',
    url: 'https://openid.net/specs/openid-financial-api-part-2-ID2.html',
    version: ['id02-rev.3', 'implementers-draft-02'],
  },
  dPoP: {
    name: 'OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-dpop-01',
    version: ['draft-01'],
  },
  frontchannelLogout: {
    name: 'OpenID Connect Front-Channel Logout 1.0 - draft 04',
    type: 'OIDF AB/Connect Working Group draft',
    url: 'https://openid.net/specs/openid-connect-frontchannel-1_0-04.html',
    version: [2, 'draft-02', 'draft-03', 'draft-04'],
  },
  jwtIntrospection: {
    name: 'JWT Response for OAuth Token Introspection - draft 09',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-jwt-introspection-response-09',
    version: ['draft-09'],
  },
  jwtResponseModes: {
    name: 'JWT Secured Authorization Response Mode for OAuth 2.0 - Implementer\'s Draft 01',
    type: 'OIDF FAPI WG Implementer\'s Draft',
    url: 'https://openid.net/specs/openid-financial-api-jarm-ID1.html',
    version: [1, 2, 'draft-02', 'implementers-draft-01'],
  },
  pushedAuthorizationRequests: {
    name: 'OAuth 2.0 Pushed Authorization Requests - draft 03',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-par-03',
    version: [0, 'individual-draft-01', 'draft-00', 'draft-01', 'draft-02', 'draft-03'],
  },
  resourceIndicators: {
    name: 'Resource Indicators for OAuth 2.0 - draft 08',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-resource-indicators-08',
    version: [2, 3, 4, 5, 6, 7, 'draft-07', 'draft-08'],
  },
  sessionManagement: {
    name: 'OpenID Connect Session Management 1.0 - draft 30',
    type: 'OIDF AB/Connect Working Group draft',
    url: 'https://openid.net/specs/openid-connect-session-1_0-30.html',
    version: [28, 'draft-28', 'draft-29', 'draft-30'],
  },
  webMessageResponseMode: {
    name: 'OAuth 2.0 Web Message Response Mode - draft 00',
    type: 'Individual draft',
    url: 'https://tools.ietf.org/html/draft-sakimura-oauth-wmrm-00',
    version: [0, 'id-00', 'individual-draft-00'],
  },
  issAuthResp: {
    name: 'OAuth 2.0 Authorization Server Issuer Identifier in Authorization Response - draft 00',
    type: 'IETF OAuth Working Group draft',
    url: 'https://tools.ietf.org/html/draft-ietf-oauth-iss-auth-resp-00',
    version: ['draft-00'],
  },
}));

module.exports = {
  DRAFTS,
  STABLE,
};
<|endoftext|>


<commit_before>
var fs = require('fs');
var util = require('util');

module.exports = function(grunt) {

    var semverUtils = require('semver-utils');

    var getBuildVersion = function() {
	var package = grunt.file.readJSON('package.json');
	var semver = semverUtils.parse(package.version);

	var release = semver.release.split('.');

	release = +release[release.length-1];

	return release;
    }

    // Do grunt-related things in here
    require('load-grunt-tasks')(grunt);
    grunt.initConfig({
	package: grunt.file.readJSON('package.json'),
	gitcheckout: {
    	    default: {
      		options: {
		    create: false
		}
   	    }
  	},
	changelog: {
	    'ios-library': {
		options: {
            	    featureRegex: /^(.*)implements (IOSSDK-\d+)(.*)/gi,
            	    fixRegex: /^(.*)fixes (IOSSDK-\d+)(.*)/gi,
            	    dest: 'CHANGELOG.md',
            	    template: '## SDK Version <%= package.version %> / {{date}}\n\n{{> features}}{{> fixes}}',
            	    partials: {
                	features: '{{#each features}}{{> feature}}{{/each}}',
                	feature: '- [NEW] {{this}}\n',
                	fixes: '{{#each fixes}}{{> fix}}{{/each}}',
                	fix: "- [FIX] {{this}}\n"
            	    }
        	}
	    }
	},
	replace: {
	    changelog: {
		options: {
		    patterns: [ {
			match: /(IOSSDK-\d+)/g,
			replacement: '[$1](https://jira.qwasi.com/browse/$1)'
		    }]
		},
		files: [
		    { expand: true, flatten: true, src: ['CHANGELOG.md'] }
		]
	    }
	},
	bump: {
	    options: {
		files: ['package.json'],
		updateConfigs: [],
		commit: true,
		commitMessage: '#bump v%VERSION%',
		commitFiles: ['package.json'],
		createTag: true,
		tagName: 'v%VERSION%',
		tagMessage: 'Version %VERSION%',
		push: false,
		pushTo: 'origin',
		prereleaseName: false,
		gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d',
		globalReplace: false
	    }
	},
	shell: {
	    bump_pod: {
		command: function() {
		    var package = grunt.file.readJSON('package.json');
		    var semver = semverUtils.parse(package.version);

		    return 'podspec-bump -w ' + semver;
		}
	    }
	}
    });

    grunt.registerTask('changeLog', 'Build changelog and add jira links', ['changelog', 'replace']);

    grunt.registerTask('bump-all', ['bump-only:patch', 'shell', 'writeVersionHeader', 'changelog']);

    grunt.registerTask('writeVersionHeader', function() {
	var package = grunt.file.readJSON('package.json');
	var semver = semverUtils.parse(package.version);

	var header = util.format('\/\/ Version Header\n' +
				 '#define SHORT_VERSION @"%s"\n' +
				 '#define BUILD_VERSION %d\n' +
				 '#define VERSION_STRING @"%s-%d" \n'
				 , semver.version, getBuildVersion(), semver.version, getBuildVersion());

	fs.writeFileSync('Pod/Classes/Version.h', header);

    });

};
<commit_msg>fixing bump prerelease<commit_after>
var fs = require('fs');
var util = require('util');

module.exports = function(grunt) {

    var semverUtils = require('semver-utils');

    var getBuildVersion = function() {
	var package = grunt.file.readJSON('package.json');
	var semver = semverUtils.parse(package.version);

	var release = semver.release.split('.');

	release = +release[release.length-1];

	return release;
    }

    // Do grunt-related things in here
    require('load-grunt-tasks')(grunt);
    grunt.initConfig({
	package: grunt.file.readJSON('package.json'),
	gitcheckout: {
    	    default: {
      		options: {
		    create: false
		}
   	    }
  	},
	changelog: {
	    'ios-library': {
		options: {
            	    featureRegex: /^(.*)implements (IOSSDK-\d+)(.*)/gi,
            	    fixRegex: /^(.*)fixes (IOSSDK-\d+)(.*)/gi,
            	    dest: 'CHANGELOG.md',
            	    template: '## SDK Version <%= package.version %> / {{date}}\n\n{{> features}}{{> fixes}}',
            	    partials: {
                	features: '{{#each features}}{{> feature}}{{/each}}',
                	feature: '- [NEW] {{this}}\n',
                	fixes: '{{#each fixes}}{{> fix}}{{/each}}',
                	fix: "- [FIX] {{this}}\n"
            	    }
        	}
	    }
	},
	replace: {
	    changelog: {
		options: {
		    patterns: [ {
			match: /(IOSSDK-\d+)/g,
			replacement: '[$1](https://jira.qwasi.com/browse/$1)'
		    }]
		},
		files: [
		    { expand: true, flatten: true, src: ['CHANGELOG.md'] }
		]
	    }
	},
	bump: {
	    options: {
		files: ['package.json'],
		updateConfigs: [],
		commit: true,
		commitMessage: '#bump v%VERSION%',
		commitFiles: ['package.json'],
		createTag: true,
		tagName: 'v%VERSION%',
		tagMessage: 'Version %VERSION%',
		push: false,
		pushTo: 'origin',
		prereleaseName: dev,
		gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d',
		globalReplace: false
	    }
	},
	shell: {
	    bump_pod: {
		command: function() {
		    var package = grunt.file.readJSON('package.json');
		    var semver = semverUtils.parse(package.version);

		    return 'podspec-bump -w ' + semver;
		}
	    }
	}
    });

    grunt.registerTask('changeLog', 'Build changelog and add jira links', ['changelog', 'replace']);

    grunt.registerTask('bump-all', ['bump-only:prerelease', 'shell', 'writeVersionHeader', 'changelog']);

    grunt.registerTask('writeVersionHeader', function() {
	var package = grunt.file.readJSON('package.json');
	var semver = semverUtils.parse(package.version);

	var header = util.format('\/\/ Version Header\n' +
				 '#define SHORT_VERSION @"%s"\n' +
				 '#define BUILD_VERSION %d\n' +
				 '#define VERSION_STRING @"%s-%d" \n'
				 , semver.version, getBuildVersion(), semver.version, getBuildVersion());

	fs.writeFileSync('Pod/Classes/Version.h', header);

    });

};
<|endoftext|>