<commit_before>"use strict";

/*global N, _*/
/*jshint maxparams:8*/

// stdlib
var http = require('http');

// 3rd-party
var treeGet = require('nlib').Support.tree.cache.get;

// internal
var env         = require('../../env');
var compression = require('./compression');

////////////////////////////////////////////////////////////////////////////////

function log(req, res, code, env, err) {
  var // FIXME: env might not be yet defined (when router didn't matched)
      logger  = N.logger.getLogger(env ? ('server.' + env.request.method) : 'server'),
      message = http.STATUS_CODES[code], level;

  if (err || (N.io.APP_ERROR <= code)) {
    message = err ? (err.stack || err.message || err) : message;
    level   = 'fatal';
  } else if (N.io.BAD_REQUEST <= code && N.io.APP_ERROR > code) {
    level = 'error';
  } else {
    level = 'info';
  }

  // FIXME: Do not forget to filter-out sensitive params upon logging
  // if (req.params.password) req.params.password = '***';
  // if (req.params.password_confirmation) req.params.password_confirmation = '***';

  logger[level]('%s - "%s %s HTTP/%s" %d "%s" - %s',
                req.connection.remoteAddress,
                req.method,
                req.url,
                req.httpVersion,
                code,
                req.headers['user-agent'],
                message);
}

// Ends response with given `code`, `head`ers and `body`.
// Rejects body if request method was HEAD
//
function end(req, res, code, head, body, env, err) {
  // set headers
  _.each(head || {}, function (value, name) {
    if (null === value) {
      this.removeHeader(name);
      return;
    }

    this.setHeader(name, value);
  }, res);

  // Remove Accept-Ranges if it wasn't explicitly set
  if (!(head || {})['Accept-Ranges']) {
    res.removeHeader('Accept-Ranges');
  }

  if ('HEAD' === req.method) {
    // remove body, when it's not supposed to be sent
    body = null;
  } else if (!body) {
    // auto-set body based on status code
    body = http.STATUS_CODES[code];
  }

  if (!res.getHeader('Content-Type')) {
    N.logger.warn('Required header Content-Type was not set in ' +
                       env.request.method);
  }

  //
  // Set some obligatory headers
  //

  res.setHeader('Server', 'Sansung Calakci');
  res.setHeader('Date',   (new Date).toUTCString());

  log(req, res, code, env, err);

  //
  // Set Content-Length header
  //

  if (Buffer.isBuffer(body)) {
    res.setHeader('Content-Length', body.length);
  } else {
    // *** body MUST be a Buffer or a String.
    //
    // Buffer.byteLength() and Response#write() (that is internally called
    // by Response#end()) throws TypeError when it's argument is not a String
    // or a Buffer.
    res.setHeader('Content-Length', Buffer.byteLength(body));
  }

  // set status code and send body (if any)
  res.statusCode = code;
  res.end(body);
}

////////////////////////////////////////////////////////////////////////////////

// Handles errors.
//
function process_error(req, res, err, env) {
  var body;

  // Scenario: next(404);
  if (err === +err) {
    err = { code: err };
  }

  //
  // user asks for request termination providing:
  //
  //    - code  (Number)
  //    - head  (Object)  Optional
  //    - data  (Mixed)   Optional
  //

  if (err.code) {
    err.head = _.defaults(err.head || {}, {
      'Content-Type': 'text/plain; charset=utf-8'
    });

    if (err.data && 'object' === typeof err.data) {
      err.data = JSON.stringify(err.data);
    }

    end(req, res, err.code, err.head, err.data, env);
    return;
  }

  //
  // exceptions or fatal fuckup happened
  //

  body = ('development' !== N.runtime.env) ? 'Application error'
       : (err.stack || err.toString());
  end(req, res, N.io.APP_ERROR, {'Content-Type': 'text/plain; charset=utf-8'}, body, env, err);
}

// Final callback of the Hooker#run
//
function finalize(err) {
  var env, http, resp, type, compressor;

  /*jshint validthis:true*/

  if (err) {
    process_error(this.origin.http.req, this.origin.http.res, err, this);
    return;
  }

  //
  // Shorten some vars
  //

  env  = this;
  http = this.origin.http;
  resp = this.response;

  //
  // Check whenever compression is allowed by client or not
  //

  type = resp.headers['Content-Type'] || http.res.getHeader('Content-Type');
  compressor = /json|text|javascript/.test(type) && compression.is_allowed(http.req);

  //
  // Mark for proxies, that we can return different content (plain & gzipped),
  // depending on specified (comma-separated) headers
  //

  resp.headers['Vary'] = 'Accept-Encoding';

  //
  // Return raw response, if compression is not allowed or body is too small
  //

  if (false === compressor || 500 > Buffer.byteLength(resp.body || '')) {
    end(http.req, http.res, resp.statusCode || N.io.OK, resp.headers, resp.body, env);
    return;
  }

  //
  // Compression is allowed, set Content-Encoding
  //

  resp.headers['Content-Encoding'] = compressor;

  //
  // Compress body
  //

  compression.process(compressor, resp.body, function (err, buffer) {
    if (err) {
      process_error(http.req, http.res, err, env);
      return;
    }

    end(http.req, http.res, resp.statusCode || N.io.OK, resp.headers, buffer, env);
  });
}

////////////////////////////////////////////////////////////////////////////////

module.exports = function handle_http(req, res) {
  var match = N.runtime.router.match(req.fullUrl),
      // mix GET QUERY params (part after ? in URL) and params from router
      // params from router take precedence
      params = _.extend({}, req.query, (match || {}).params),
      func, validation;

  // Save params reference for logs
  req.params = params;

  if (!match) {
    // Route not found
    process_error(req, res, { code: N.io.NOT_FOUND });
    return;
  }

  validation = N.validate.test(match.meta, params);

  // when method has no validation schema,
  // test() returns `null`, object with `valid` property otherwise
  if (!validation) {
    process_error(req, res, "Params schema is missing for " + match.meta);
    return;
  }

  if (!validation.valid) {
    // FIXME: do not list "bad" params on production?
    process_error(req, res, {
      code: N.io.BAD_REQUEST,
      message: "Invalid params:\n" + validation.errors.map(function (err) {
        return "- " + err.property + ' ' + err.message;
      }).join('\n')
    });
    return;
  }

  func = treeGet(N.server, match.meta);
  N.filters.run(match.meta, params, func, finalize, env({
    http:   { req: req, res: res },
    method: match.meta
  }));
};
<commit_msg>Fix ContentLength header setter<commit_after>"use strict";

/*global N, _*/
/*jshint maxparams:8*/

// stdlib
var http = require('http');

// 3rd-party
var treeGet = require('nlib').Support.tree.cache.get;

// internal
var env         = require('../../env');
var compression = require('./compression');

////////////////////////////////////////////////////////////////////////////////

function log(req, res, code, env, err) {
  var // FIXME: env might not be yet defined (when router didn't matched)
      logger  = N.logger.getLogger(env ? ('server.' + env.request.method) : 'server'),
      message = http.STATUS_CODES[code], level;

  if (err || (N.io.APP_ERROR <= code)) {
    message = err ? (err.stack || err.message || err) : message;
    level   = 'fatal';
  } else if (N.io.BAD_REQUEST <= code && N.io.APP_ERROR > code) {
    level = 'error';
  } else {
    level = 'info';
  }

  // FIXME: Do not forget to filter-out sensitive params upon logging
  // if (req.params.password) req.params.password = '***';
  // if (req.params.password_confirmation) req.params.password_confirmation = '***';

  logger[level]('%s - "%s %s HTTP/%s" %d "%s" - %s',
                req.connection.remoteAddress,
                req.method,
                req.url,
                req.httpVersion,
                code,
                req.headers['user-agent'],
                message);
}

// Ends response with given `code`, `head`ers and `body`.
// Rejects body if request method was HEAD
//
function end(req, res, code, head, body, env, err) {
  // set headers
  _.each(head || {}, function (value, name) {
    if (null === value) {
      this.removeHeader(name);
      return;
    }

    this.setHeader(name, value);
  }, res);

  // Remove Accept-Ranges if it wasn't explicitly set
  if (!(head || {})['Accept-Ranges']) {
    res.removeHeader('Accept-Ranges');
  }

  if ('HEAD' === req.method) {
    // remove body, when it's not supposed to be sent
    body = null;
  } else if (!body) {
    // auto-set body based on status code
    body = http.STATUS_CODES[code];
  }

  if (!res.getHeader('Content-Type')) {
    N.logger.warn('Required header Content-Type was not set in ' +
                       env.request.method);
  }

  //
  // Set some obligatory headers
  //

  res.setHeader('Server', 'Sansung Calakci');
  res.setHeader('Date',   (new Date).toUTCString());

  log(req, res, code, env, err);

  //
  // Set Content-Length header
  //

  if (Buffer.isBuffer(body)) {
    res.setHeader('Content-Length', body.length);
  } else if (body) {
    // Buffer.byteLength() and Response#write() (that is internally called
    // by Response#end()) throws TypeError when it's argument is not a String
    // or a Buffer.
    res.setHeader('Content-Length', Buffer.byteLength(body));
  }

  // set status code and send body (if any)
  res.statusCode = code;
  res.end(body);
}

////////////////////////////////////////////////////////////////////////////////

// Handles errors.
//
function process_error(req, res, err, env) {
  var body;

  // Scenario: next(404);
  if (err === +err) {
    err = { code: err };
  }

  //
  // user asks for request termination providing:
  //
  //    - code  (Number)
  //    - head  (Object)  Optional
  //    - data  (Mixed)   Optional
  //

  if (err.code) {
    err.head = _.defaults(err.head || {}, {
      'Content-Type': 'text/plain; charset=utf-8'
    });

    if (err.data && 'object' === typeof err.data) {
      err.data = JSON.stringify(err.data);
    }

    end(req, res, err.code, err.head, err.data, env);
    return;
  }

  //
  // exceptions or fatal fuckup happened
  //

  body = ('development' !== N.runtime.env) ? 'Application error'
       : (err.stack || err.toString());
  end(req, res, N.io.APP_ERROR, {'Content-Type': 'text/plain; charset=utf-8'}, body, env, err);
}

// Final callback of the Hooker#run
//
function finalize(err) {
  var env, http, resp, type, compressor;

  /*jshint validthis:true*/

  if (err) {
    process_error(this.origin.http.req, this.origin.http.res, err, this);
    return;
  }

  //
  // Shorten some vars
  //

  env  = this;
  http = this.origin.http;
  resp = this.response;

  //
  // Check whenever compression is allowed by client or not
  //

  type = resp.headers['Content-Type'] || http.res.getHeader('Content-Type');
  compressor = /json|text|javascript/.test(type) && compression.is_allowed(http.req);

  //
  // Mark for proxies, that we can return different content (plain & gzipped),
  // depending on specified (comma-separated) headers
  //

  resp.headers['Vary'] = 'Accept-Encoding';

  //
  // Return raw response, if compression is not allowed or body is too small
  //

  if (false === compressor || 500 > Buffer.byteLength(resp.body || '')) {
    end(http.req, http.res, resp.statusCode || N.io.OK, resp.headers, resp.body, env);
    return;
  }

  //
  // Compression is allowed, set Content-Encoding
  //

  resp.headers['Content-Encoding'] = compressor;

  //
  // Compress body
  //

  compression.process(compressor, resp.body, function (err, buffer) {
    if (err) {
      process_error(http.req, http.res, err, env);
      return;
    }

    end(http.req, http.res, resp.statusCode || N.io.OK, resp.headers, buffer, env);
  });
}

////////////////////////////////////////////////////////////////////////////////

module.exports = function handle_http(req, res) {
  var match = N.runtime.router.match(req.fullUrl),
      // mix GET QUERY params (part after ? in URL) and params from router
      // params from router take precedence
      params = _.extend({}, req.query, (match || {}).params),
      func, validation;

  // Save params reference for logs
  req.params = params;

  if (!match) {
    // Route not found
    process_error(req, res, { code: N.io.NOT_FOUND });
    return;
  }

  validation = N.validate.test(match.meta, params);

  // when method has no validation schema,
  // test() returns `null`, object with `valid` property otherwise
  if (!validation) {
    process_error(req, res, "Params schema is missing for " + match.meta);
    return;
  }

  if (!validation.valid) {
    // FIXME: do not list "bad" params on production?
    process_error(req, res, {
      code: N.io.BAD_REQUEST,
      message: "Invalid params:\n" + validation.errors.map(function (err) {
        return "- " + err.property + ' ' + err.message;
      }).join('\n')
    });
    return;
  }

  func = treeGet(N.server, match.meta);
  N.filters.run(match.meta, params, func, finalize, env({
    http:   { req: req, res: res },
    method: match.meta
  }));
};
<|endoftext|>


<commit_before>"use strict";

const IBase = require("./IBase");
const IUser = require("./IUser");
const GuildMember = require("../models/GuildMember");
const Utils = require("../core/Utils");

const rest = require("../networking/rest");

class IGuildMember extends IUser {
  constructor(discordie, userId, guildId) {
    super(discordie, userId, guildId);
    this._guildId = guildId;
    this._inherit(GuildMember, (key) =>
      this._discordie._members.getMember(this._guildId, this._userId)[key]
    );
    Utils.privatify(this);
    Object.freeze(this);
  }
  get guild() {
    return this._discordie.Guilds.get(this._guildId);
  }
  get roles() {

  }
  kick() {
    return rest(this._discordie).guilds.members.kickMember(this._guildId, this.id);
  }
  ban(deleteMessageForDays) {
    return rest(this._discordie).guilds.bans.banMember(this._guildId, this.id, deleteMessageForDays);
  }
  unban() {
    return this.guild.unban(this.id);
  }
  mute(mute) {
    //check mute?
    if (typeof mute === "undefined") mute = true;
    return rest(this._discordie).guilds.members.setMute(this._guildId, this.id, mute);
  }
  unmute() {
    this.mute(false);
  }
  deafen(deaf) {
    //check permissions?
    if (typeof deaf === "undefined") deaf = true;
    return rest(this._discordie).guilds.members.setDeaf(this._guildId, this.id, deaf);
  }
  undeafen() {
    //check permissions?
    this.deaf(false);
  }
  isMuted() {
    // todo: voice_state_update handling
    //return this._discordie._members.getMember(this._guildId, this.id).mute;
  }
  isDeafened() {
    //return this._discordie._members.getMember(this._guildId, this.id).deaf;
  }
  get joined_at() {
    return this._discordie._members.getMember(this._guildId, this.id).joined_at;
  }
  can(channel, permission) {
    channel = channel.valueOf();

  }
  hasRole(role) {
    role = role.valueOf();
    //role->IRole
  }
}

module.exports = IGuildMember;
<commit_msg>Fix IGuildMember.serverMute/serverDeafen<commit_after>"use strict";

const IBase = require("./IBase");
const IUser = require("./IUser");
const GuildMember = require("../models/GuildMember");
const Utils = require("../core/Utils");

const rest = require("../networking/rest");

class IGuildMember extends IUser {
  constructor(discordie, userId, guildId) {
    super(discordie, userId, guildId);
    this._guildId = guildId;
    this._inherit(GuildMember, (key) =>
      this._discordie._members.getMember(this._guildId, this._userId)[key]
    );
    Utils.privatify(this);
    Object.freeze(this);
  }
  get guild() {
    return this._discordie.Guilds.get(this._guildId);
  }
  get roles() {

  }
  kick() {
    return rest(this._discordie).guilds.members.kickMember(this._guildId, this.id);
  }
  ban(deleteMessageForDays) {
    return rest(this._discordie).guilds.bans.banMember(this._guildId, this.id, deleteMessageForDays);
  }
  unban() {
    return this.guild.unban(this.id);
  }
  serverMute(mute) {
    if (typeof mute === "undefined") mute = true;
    if (mute == this.mute) return Promise.resolve();
    return rest(this._discordie).guilds.members.setMute(this._guildId, this.id, mute);
  }
  serverUnmute() {
    return this.serverMute(false);
  }
  serverDeafen(deaf) {
    if (typeof deaf === "undefined") deaf = true;
    if (deaf == this.deaf) return Promise.resolve();
    return rest(this._discordie).guilds.members.setDeaf(this._guildId, this.id, deaf);
  }
  serverUndeafen() {
    return this.serverDeafen(false);
  }
  can(channel, permission) {
    channel = channel.valueOf();

  }
  hasRole(role) {
    role = role.valueOf();
    //role->IRole
  }
}

module.exports = IGuildMember;
<|endoftext|>


<commit_before>var fakeAjax = function(options) {
  jasmine.FakeAjax.initContext({urls: options.urls});
};

var loadTestData = function(selector, url) {
  var fixture;
  jasmine.FakeAjax.originalAjax({
    url: url,
    async: false,
    success: function(data) {
      fixture = data;
    },
    error: function() {
      jasmine.FakeAjax.log.error("Failed loading test data by url '" + url + "'.");
    }
  });
  var testDataContainer = $(fixture).find(selector);
  if (testDataContainer.length > 0) {
    return testDataContainer.html();
  } else {
    jasmine.FakeAjax.log.error("Failed loading test data by selector: '" + selector + "' from url: '" + url + "'. Whole fixture: " + fixture);
    return undefined;
  }
};

var latestAjaxUrlMatching = function(partialUrl) {
  var matchingUrls = jasmine.FakeAjax.getRecordedSession().ajaxUrls().filter(function(url) {
    return url.match(partialUrl);
  });
  return $.URLDecode(matchingUrls[matchingUrls.length - 1]);
};

var latestAjaxUrl = function() {
    var urls = jasmine.FakeAjax.getRecordedSession().ajaxUrls();
    return $.URLDecode(urls[urls.length - 1]);
};

(function($, jasmine) {
  var context = null;

  jasmine.FakeAjax = {
    originalAjax: $.ajax,
    initContext: initContext,
    getUrls: getUrls,
    getRecordedSession: getRecordedSession,
    log: new Logger()
  };

  jQuery.ajax = function(ajaxOptions) {
    if (!jasmine.FakeAjax) {
      jasmine.FakeAjax.log.error("Fake ajax is not initialized. Create it by calling .fakeAjax in .beforeEach");
    }
    jasmine.FakeAjax.getRecordedSession().addAjaxCall(ajaxOptions);
    if (!jasmine.FakeAjax.getUrls()) {
      jasmine.FakeAjax.log.warn("There are no ajax url mappings defined.");
    } else if (!jasmine.FakeAjax.getUrls()[ajaxOptions.url]) {
      jasmine.FakeAjax.log.warn("Applying default success data for url '" + ajaxOptions.url + "'");
      if (!ajaxOptions.success) {
        jasmine.FakeAjax.log.error("Ajax success handler is not defined in system under test for url '" + ajaxOptions.url + "' See firebug script stack for more info.");
      } else {
        ajaxOptions.success("default success data");
      }
    } else if (jasmine.FakeAjax.getUrls()[ajaxOptions.url].successData) {
      ajaxOptions.success(jasmine.FakeAjax.getUrls()[ajaxOptions.url].successData);
    } else if (jasmine.FakeAjax.getUrls()[ajaxOptions.url].errorMessage) {
      ajaxOptions.error({responseText: jasmine.FakeAjax.getUrls()[ajaxOptions.url].errorMessage});
    } else {
      jasmine.FakeAjax.log.error("Unknown fake ajax configuration.");
    }
  };

  function initContext(con) {
    context = con;
    context.RecordedSession = new RecordedSession();
  }

  function getUrls() {
    return context.urls;
  }

  function getRecordedSession() {
    return context.RecordedSession;
  }

  function RecordedSession() {
    this.ajaxCalls = [];

    this.addAjaxCall = function(ajaxOptions) {
      this.ajaxCalls.push(ajaxOptions);
    }

    this.ajaxUrls = function() {
      return this.ajaxCalls.map(function(ajaxOptions) {
        return ajaxOptions.url;
      });
    }
  }

  function Logger() {
    this.error = function(message) {
      if (window.console) {
        console.error(message);
        debugger;
      }
    }

    this.warn = function(message) {
      if (window.console) {
        console.warn(message);
      }
    }
  }
})(jQuery, jasmine);
<commit_msg>Try to simplify a bit.<commit_after>var fakeAjax = function(options) {
  jasmine.FakeAjax.initContext(options);
};

var loadTestData = function(selector, url) {
  var fixture;
  jasmine.FakeAjax.originalAjax({
    url: url,
    async: false,
    success: function(data) {
      fixture = data;
    },
    error: function() {
      jasmine.FakeAjax.log.error("Failed loading test data by url '" + url + "'.");
    }
  });
  var testDataContainer = $(fixture).find(selector);
  if (testDataContainer.length > 0) {
    return testDataContainer.html();
  } else {
    jasmine.FakeAjax.log.error("Failed loading test data by selector: '" + selector + "' from url: '" + url + "'. Whole fixture: " + fixture);
    return undefined;
  }
};

var latestAjaxUrlMatching = function(partialUrl) {
  var matchingUrls = jasmine.FakeAjax.recordedSession.ajaxUrls().filter(function(url) {
    return url.match(partialUrl);
  });
  return $.URLDecode(matchingUrls[matchingUrls.length - 1]);
};

var latestAjaxUrl = function() {
    var urls = jasmine.FakeAjax.recordedSession.ajaxUrls();
    return $.URLDecode(urls[urls.length - 1]);
};

(function($, jasmine) {
  jasmine.FakeAjax = {
    originalAjax: $.ajax,
    initContext: function(options) {
      this.urls = options.urls;
      this.recordedSession = new RecordedSession();
    },
    log: new Logger()
  };

  $.ajax = function(ajaxOptions) {
    jasmine.FakeAjax.recordedSession.addAjaxCall(ajaxOptions);
    if (!jasmine.FakeAjax.urls) {
      jasmine.FakeAjax.log.warn("There are no ajax url mappings defined.");
    } else if (!jasmine.FakeAjax.urls[ajaxOptions.url]) {
      jasmine.FakeAjax.log.warn("Applying default success data for url '" + ajaxOptions.url + "'");
      if (!ajaxOptions.success) {
        jasmine.FakeAjax.log.error("Ajax success handler is not defined in system under test for url '" + ajaxOptions.url + "' See firebug script stack for more info.");
      } else {
        ajaxOptions.success("default success data");
      }
    } else if (jasmine.FakeAjax.urls[ajaxOptions.url].successData) {
      ajaxOptions.success(jasmine.FakeAjax.urls[ajaxOptions.url].successData);
    } else if (jasmine.FakeAjax.urls[ajaxOptions.url].errorMessage) {
      ajaxOptions.error({responseText: jasmine.FakeAjax.urls[ajaxOptions.url].errorMessage});
    } else {
      jasmine.FakeAjax.log.error("Unknown fake ajax configuration.");
    }
  };

  function RecordedSession() {
    this.ajaxCalls = [];

    this.addAjaxCall = function(ajaxOptions) {
      this.ajaxCalls.push(ajaxOptions);
    }

    this.ajaxUrls = function() {
      return this.ajaxCalls.map(function(ajaxOptions) {
        return ajaxOptions.url;
      });
    }
  }

  function Logger() {
    this.error = function(message) {
      if (window.console) {
        console.error(message);
        debugger;
      }
    }

    this.warn = function(message) {
      if (window.console) {
        console.warn(message);
      }
    }
  }
})(jQuery, jasmine);
<|endoftext|>


<commit_before>// classList polyfill for old browsers
require('classlist-polyfill')
// Object.assign polyfill
require('es6-object-assign').polyfill()

// String to DOM function
var domify = require('domify')

// Detect CSS Animation End Support
// https://github.com/limonte/sweetalert2/blob/99bd539f85e15ac170f69d35001d12e092ef0054/src/utils/dom.js#L194
var animationEndEvent = (function detectAnimationEndEvent () {
  var el = document.createElement('div')
  var eventNames = {
    'WebkitAnimation': 'webkitAnimationEnd',
    'MozAnimation': 'animationend',
    'OAnimation': 'oanimationend',
    'msAnimation': 'MSAnimationEnd',
    'animation': 'animationend'
  }
  for (var i in eventNames) {
    if (el.style[i] !== undefined) {
      return eventNames[i]
    }
  }
  return false
})()

// vex base CSS classes
var baseClassNames = {
  vex: 'vex',
  content: 'vex-content',
  overlay: 'vex-overlay',
  close: 'vex-close',
  closing: 'vex-closing',
  open: 'vex-open'
}

// Private lookup table of all open vex objects, keyed by id
var vexes = {}
var globalId = 1

// vex itself is an object that exposes a simple API to open and close vex objects in various ways
var vex = {
  open: function open (opts) {
    // Check for usage of deprecated options, and log a warning
    var warnDeprecated = function warnDeprecated (prop) {
      console.warn('The "' + prop + '" property is deprecated in vex 3. Use CSS classes and the appropriate "ClassName" options, instead.')
    }
    if (opts.css) {
      warnDeprecated('css')
    }
    if (opts.overlayCSS) {
      warnDeprecated('overlayCSS')
    }
    if (opts.contentCSS) {
      warnDeprecated('contentCSS')
    }
    if (opts.closeCSS) {
      warnDeprecated('closeCSS')
    }

    // The dialog instance
    var vexInstance = {}

    // Set id
    vexInstance.id = globalId++

    // Store internally
    vexes[vexInstance.id] = vexInstance

    // Set state
    vexInstance.isOpen = true

    // Close function on the vex instance
    // This is how all API functions should close individual vexes
    vexInstance.close = function instanceClose () {
      // Check state
      if (!this.isOpen) {
        return true
      }

      var options = this.options

      // Allow the user to validate any info or abort the close with the beforeClose callback
      var shouldClose = (function shouldClose () {
        // Call before close callback
        if (options.beforeClose) {
          return options.beforeClose.call(this)
        }
        // Otherwise indicate that it's ok to continue with close
        return true
      }.bind(this)())

      // If beforeClose() fails, abort the close
      if (shouldClose === false) {
        return false
      }

      // Update state
      this.isOpen = false

      // Detect if the content el has any CSS animations defined
      var style = window.getComputedStyle(this.contentEl)
      function hasAnimationPre (prefix) {
        return style.getPropertyValue(prefix + 'animation-name') !== 'none' && style.getPropertyValue(prefix + 'animation-duration') !== '0s'
      }
      var hasAnimation = hasAnimationPre('') || hasAnimationPre('-webkit-') || hasAnimationPre('-moz-') || hasAnimationPre('-o-')

      // Define the function that will actually close the instance
      var close = function close () {
        if (!this.rootEl.parentNode) {
          return
        }
        // Run once
        this.rootEl.removeEventListener(animationEndEvent, close)
        // Remove from lookup table (prevent memory leaks)
        delete vexes[this.id]
        // Remove the dialog from the DOM
        this.rootEl.parentNode.removeChild(this.rootEl)
        // Call after close callback
        if (options.afterClose) {
          options.afterClose.call(this)
        }
        // Remove styling from the body, if no more vexes are open
        if (Object.keys(vexes).length === 0) {
          document.body.classList.remove(baseClassNames.open)
        }
      }.bind(this)

      // Close the vex
      if (animationEndEvent && hasAnimation) {
        // Setup the end event listener, to remove the el from the DOM
        this.rootEl.addEventListener(animationEndEvent, close)
        // Add the closing class to the dialog, showing the close animation
        this.rootEl.classList.add(baseClassNames.closing)
      } else {
        close()
      }

      return true
    }

    // Allow strings as content
    if (typeof opts === 'string') {
      opts = {
        content: opts
      }
    }
    // Store options on instance for future reference
    var options = vexInstance.options = Object.assign({}, vex.defaultOptions, opts)

    // vex root
    var rootEl = vexInstance.rootEl = document.createElement('div')
    rootEl.classList.add(baseClassNames.vex)
    if (options.className) {
      rootEl.classList.add(options.className)
    }

    // Overlay
    var overlayEl = vexInstance.overlayEl = document.createElement('div')
    overlayEl.classList.add(baseClassNames.overlay)
    if (options.overlayClassName) {
      overlayEl.classList.add(options.overlayClassName)
    }
    if (options.overlayClosesOnClick) {
      overlayEl.addEventListener('click', function overlayClickListener (e) {
        if (e.target === overlayEl) {
          vexInstance.close()
        }
      })
    }
    rootEl.appendChild(overlayEl)

    // Content
    var contentEl = vexInstance.contentEl = document.createElement('div')
    contentEl.classList.add(baseClassNames.content)
    if (options.contentClassName) {
      contentEl.classList.add(options.contentClassName)
    }
    contentEl.appendChild(options.content instanceof window.Node ? options.content : domify(options.content))
    rootEl.appendChild(contentEl)

    // Close button
    if (options.showCloseButton) {
      var closeEl = vexInstance.closeEl = document.createElement('div')
      closeEl.classList.add(baseClassNames.close)
      if (options.closeClassName) {
        closeEl.classList.add(options.closeClassName)
      }
      closeEl.addEventListener('click', vexInstance.close.bind(vexInstance))
      contentEl.appendChild(closeEl)
    }

    // Add to DOM
    document.querySelector(options.appendLocation).appendChild(rootEl)

    // Call after open callback
    if (options.afterOpen) {
      options.afterOpen.call(vexInstance)
    }

    // Apply styling to the body
    document.body.classList.add(baseClassNames.open)

    // Return the created vex instance
    return vexInstance
  },

  // A top-level vex.close function to close dialogs by reference or id
  close: function close (vexOrId) {
    var id
    if (vexOrId.id) {
      id = vexOrId.id
    } else if (typeof vexOrId === 'string') {
      id = vexOrId
    } else {
      throw new TypeError('close requires a vex object or id string')
    }
    if (!vexes[id]) {
      return false
    }
    return vexes[id].close()
  },

  // Close the most recently created/opened vex
  closeTop: function closeTop () {
    var ids = Object.keys(vexes)
    if (!ids.length) {
      return false
    }
    return vexes[ids[ids.length - 1]].close()
  },

  // Close every vex!
  closeAll: function closeAll () {
    for (var id in vexes) {
      this.close(id)
    }
    return true
  },

  // A getter for the internal lookup table
  getAll: function getAll () {
    return vexes
  },

  // A getter for the internal lookup table
  getById: function getById (id) {
    return vexes[id]
  }
}

// Close top vex on escape
window.addEventListener('keyup', function vexKeyupListener (e) {
  if (e.keyCode === 27) {
    vex.closeTop()
  }
})
// Close all vexes on history pop state (useful in single page apps)
window.addEventListener('popstate', vex.closeAll)

vex.defaultOptions = {
  content: '',
  showCloseButton: true,
  escapeButtonCloses: true,
  overlayClosesOnClick: true,
  appendLocation: 'body',
  className: '',
  overlayClassName: '',
  contentClassName: '',
  closeClassName: ''
}

// TODO Loading symbols?

// Plugin system!
vex.registerPlugin = function registerPlugin (pluginFn, name) {
  var plugin = pluginFn(vex)
  var pluginName = name || plugin.name
  if (vex[pluginName]) {
    throw new Error('Plugin ' + name + ' is already registered.')
  }
  vex[pluginName] = plugin
}

module.exports = vex
<commit_msg>Add best guess for API location in console.warn<commit_after>// classList polyfill for old browsers
require('classlist-polyfill')
// Object.assign polyfill
require('es6-object-assign').polyfill()

// String to DOM function
var domify = require('domify')

// Detect CSS Animation End Support
// https://github.com/limonte/sweetalert2/blob/99bd539f85e15ac170f69d35001d12e092ef0054/src/utils/dom.js#L194
var animationEndEvent = (function detectAnimationEndEvent () {
  var el = document.createElement('div')
  var eventNames = {
    'WebkitAnimation': 'webkitAnimationEnd',
    'MozAnimation': 'animationend',
    'OAnimation': 'oanimationend',
    'msAnimation': 'MSAnimationEnd',
    'animation': 'animationend'
  }
  for (var i in eventNames) {
    if (el.style[i] !== undefined) {
      return eventNames[i]
    }
  }
  return false
})()

// vex base CSS classes
var baseClassNames = {
  vex: 'vex',
  content: 'vex-content',
  overlay: 'vex-overlay',
  close: 'vex-close',
  closing: 'vex-closing',
  open: 'vex-open'
}

// Private lookup table of all open vex objects, keyed by id
var vexes = {}
var globalId = 1

// vex itself is an object that exposes a simple API to open and close vex objects in various ways
var vex = {
  open: function open (opts) {
    // Check for usage of deprecated options, and log a warning
    var warnDeprecated = function warnDeprecated (prop) {
      console.warn('The "' + prop + '" property is deprecated in vex 3. Use CSS classes and the appropriate "ClassName" options, instead.')
      console.warn('See http://github.hubspot.com/vex/api/advanced/#options')
    }
    if (opts.css) {
      warnDeprecated('css')
    }
    if (opts.overlayCSS) {
      warnDeprecated('overlayCSS')
    }
    if (opts.contentCSS) {
      warnDeprecated('contentCSS')
    }
    if (opts.closeCSS) {
      warnDeprecated('closeCSS')
    }

    // The dialog instance
    var vexInstance = {}

    // Set id
    vexInstance.id = globalId++

    // Store internally
    vexes[vexInstance.id] = vexInstance

    // Set state
    vexInstance.isOpen = true

    // Close function on the vex instance
    // This is how all API functions should close individual vexes
    vexInstance.close = function instanceClose () {
      // Check state
      if (!this.isOpen) {
        return true
      }

      var options = this.options

      // Allow the user to validate any info or abort the close with the beforeClose callback
      var shouldClose = (function shouldClose () {
        // Call before close callback
        if (options.beforeClose) {
          return options.beforeClose.call(this)
        }
        // Otherwise indicate that it's ok to continue with close
        return true
      }.bind(this)())

      // If beforeClose() fails, abort the close
      if (shouldClose === false) {
        return false
      }

      // Update state
      this.isOpen = false

      // Detect if the content el has any CSS animations defined
      var style = window.getComputedStyle(this.contentEl)
      function hasAnimationPre (prefix) {
        return style.getPropertyValue(prefix + 'animation-name') !== 'none' && style.getPropertyValue(prefix + 'animation-duration') !== '0s'
      }
      var hasAnimation = hasAnimationPre('') || hasAnimationPre('-webkit-') || hasAnimationPre('-moz-') || hasAnimationPre('-o-')

      // Define the function that will actually close the instance
      var close = function close () {
        if (!this.rootEl.parentNode) {
          return
        }
        // Run once
        this.rootEl.removeEventListener(animationEndEvent, close)
        // Remove from lookup table (prevent memory leaks)
        delete vexes[this.id]
        // Remove the dialog from the DOM
        this.rootEl.parentNode.removeChild(this.rootEl)
        // Call after close callback
        if (options.afterClose) {
          options.afterClose.call(this)
        }
        // Remove styling from the body, if no more vexes are open
        if (Object.keys(vexes).length === 0) {
          document.body.classList.remove(baseClassNames.open)
        }
      }.bind(this)

      // Close the vex
      if (animationEndEvent && hasAnimation) {
        // Setup the end event listener, to remove the el from the DOM
        this.rootEl.addEventListener(animationEndEvent, close)
        // Add the closing class to the dialog, showing the close animation
        this.rootEl.classList.add(baseClassNames.closing)
      } else {
        close()
      }

      return true
    }

    // Allow strings as content
    if (typeof opts === 'string') {
      opts = {
        content: opts
      }
    }
    // Store options on instance for future reference
    var options = vexInstance.options = Object.assign({}, vex.defaultOptions, opts)

    // vex root
    var rootEl = vexInstance.rootEl = document.createElement('div')
    rootEl.classList.add(baseClassNames.vex)
    if (options.className) {
      rootEl.classList.add(options.className)
    }

    // Overlay
    var overlayEl = vexInstance.overlayEl = document.createElement('div')
    overlayEl.classList.add(baseClassNames.overlay)
    if (options.overlayClassName) {
      overlayEl.classList.add(options.overlayClassName)
    }
    if (options.overlayClosesOnClick) {
      overlayEl.addEventListener('click', function overlayClickListener (e) {
        if (e.target === overlayEl) {
          vexInstance.close()
        }
      })
    }
    rootEl.appendChild(overlayEl)

    // Content
    var contentEl = vexInstance.contentEl = document.createElement('div')
    contentEl.classList.add(baseClassNames.content)
    if (options.contentClassName) {
      contentEl.classList.add(options.contentClassName)
    }
    contentEl.appendChild(options.content instanceof window.Node ? options.content : domify(options.content))
    rootEl.appendChild(contentEl)

    // Close button
    if (options.showCloseButton) {
      var closeEl = vexInstance.closeEl = document.createElement('div')
      closeEl.classList.add(baseClassNames.close)
      if (options.closeClassName) {
        closeEl.classList.add(options.closeClassName)
      }
      closeEl.addEventListener('click', vexInstance.close.bind(vexInstance))
      contentEl.appendChild(closeEl)
    }

    // Add to DOM
    document.querySelector(options.appendLocation).appendChild(rootEl)

    // Call after open callback
    if (options.afterOpen) {
      options.afterOpen.call(vexInstance)
    }

    // Apply styling to the body
    document.body.classList.add(baseClassNames.open)

    // Return the created vex instance
    return vexInstance
  },

  // A top-level vex.close function to close dialogs by reference or id
  close: function close (vexOrId) {
    var id
    if (vexOrId.id) {
      id = vexOrId.id
    } else if (typeof vexOrId === 'string') {
      id = vexOrId
    } else {
      throw new TypeError('close requires a vex object or id string')
    }
    if (!vexes[id]) {
      return false
    }
    return vexes[id].close()
  },

  // Close the most recently created/opened vex
  closeTop: function closeTop () {
    var ids = Object.keys(vexes)
    if (!ids.length) {
      return false
    }
    return vexes[ids[ids.length - 1]].close()
  },

  // Close every vex!
  closeAll: function closeAll () {
    for (var id in vexes) {
      this.close(id)
    }
    return true
  },

  // A getter for the internal lookup table
  getAll: function getAll () {
    return vexes
  },

  // A getter for the internal lookup table
  getById: function getById (id) {
    return vexes[id]
  }
}

// Close top vex on escape
window.addEventListener('keyup', function vexKeyupListener (e) {
  if (e.keyCode === 27) {
    vex.closeTop()
  }
})
// Close all vexes on history pop state (useful in single page apps)
window.addEventListener('popstate', vex.closeAll)

vex.defaultOptions = {
  content: '',
  showCloseButton: true,
  escapeButtonCloses: true,
  overlayClosesOnClick: true,
  appendLocation: 'body',
  className: '',
  overlayClassName: '',
  contentClassName: '',
  closeClassName: ''
}

// TODO Loading symbols?

// Plugin system!
vex.registerPlugin = function registerPlugin (pluginFn, name) {
  var plugin = pluginFn(vex)
  var pluginName = name || plugin.name
  if (vex[pluginName]) {
    throw new Error('Plugin ' + name + ' is already registered.')
  }
  vex[pluginName] = plugin
}

module.exports = vex
<|endoftext|>


<commit_before>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    files: [
      { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false },
      { pattern: '../../node_modules/hammer-simulator/index.js', watched: false },
      { pattern: './test.css', watched: false },
      { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false }
    ],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('karma-spec-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false, // leave Jasmine Spec Runner output visible in browser
      jasmine: {
        random: false
      }
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../../coverage'),
      reports: ['html', 'lcovonly'],
      fixWebpackSourcePaths: true
    },
    reporters: ['spec'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<commit_msg>chore(test): suppress skipped tests in reporter output<commit_after>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    files: [
      { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false },
      { pattern: '../../node_modules/hammer-simulator/index.js', watched: false },
      { pattern: './test.css', watched: false },
      { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false }
    ],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('karma-spec-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false, // leave Jasmine Spec Runner output visible in browser
      jasmine: {
        random: false
      }
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../../coverage'),
      reports: ['html', 'lcovonly'],
      fixWebpackSourcePaths: true
    },
    reporters: ['spec'],
    specReporter: {
        suppressSkipped: true
    },
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<|endoftext|>


<commit_before>import { observable, computed, transaction } from "mobx";
import Immutable from "seamless-immutable";
import { generate } from "shortid";

import elementMap from "../elements";

// TODO: REMOVE. Useful for testing
const allColors = [
  "#EF767A", "#456990", "#49BEAA", "#49DCB1", "#EEB868", "#EF767A", "#456990",
  "#49BEAA", "#49DCB1", "#EEB868", "#EF767A"
];

export default class SlidesStore {
  // Default slides state
  // history will be an array of slides arrays
  @observable history = Immutable.from([{
    currentSlideIndex: 0,
    currentElementIndex: null,
    slides: [{
      // Default first slide
      id: generate(),
      props: {},
      children: [],
      color: allColors[0]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[1]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[2]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[3]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[4]
    }
  ] }]);

  @observable historyIndex = 0;

  // Returns a new mutable object. Functions as a cloneDeep.
  @computed get slides() {
    return this.history[this.historyIndex].slides.asMutable({ deep: true });
  }

  @computed get currentSlideIndex() {
    return this.history[this.historyIndex].currentSlideIndex;
  }

  @computed get currentElementIndex() {
    return this.history[this.historyIndex].currentElementIndex;
  }

  // Returns a new mutable object. Functions as a cloneDeep.
  @computed get currentSlide() {
    return this.slides[this.currentSlideIndex];
  }

  // Returns a new mutable object. Functions as a cloneDeep.
  @computed get currentElement() {
    return this.currentElementIndex && this.currentSlide[this.currentElementIndex];
  }

  @computed get undoDisabled() {
    return this.historyIndex === 0 || this.history.length <= 1;
  }

  @computed get redoDisabled() {
    return this.historyIndex >= this.history.length - 1;
  }

  @computed get snapshot() {
    return this.history[this.historyIndex].asMutable({ deep: true });
  }

  constructor(slides) {
    if (slides) {
      this.history = Immutable.from([{
        currentSlideIndex: 0,
        currentElementIndex: null,
        slides
      }]);
    }
  }

  dropElement(elementType) {
    const slideToAddTo = this.currentSlide;
    const newSlidesArray = this.slides;

    slideToAddTo.children.push({
      ...elementMap[elementType],
      id: generate()
    });

    newSlidesArray[this.currentSlideIndex] = slideToAddTo;
    const elementIndex = this.currentElementIndex ?
        this.currentElementIndex + 1 :
        slideToAddTo.children.length - 1;

    this._addToHistory({
      currentSlideIndex: this.currentSlideIndex,
      currentElementIndex: elementIndex,
      slides: newSlidesArray
    });
  }

  setCurrentElementIndex(newIndex) {
    const snapshot = this.snapshot;
    snapshot.currentElementIndex = newIndex;

    transaction(() => {
      const left = this.history.slice(0, this.historyIndex);
      const right = this.history.slice(this.historyIndex + 1, this.history.length);
      this.history = left.concat([snapshot], right);
    });
  }

  setSelectedSlideIndex(newSlideIndex) {
    const snapshot = this.snapshot;
    snapshot.currentElementIndex = null;
    snapshot.currentSlideIndex = newSlideIndex;

    transaction(() => {
      const left = this.history.slice(0, this.historyIndex);
      const right = this.history.slice(this.historyIndex + 1, this.history.length);
      this.history = left.concat([snapshot], right);
    });
  }

  moveSlide(currentIndex, newIndex) {
    const slidesArray = this.slides;

    slidesArray.splice(newIndex, 0, slidesArray.splice(currentIndex, 1)[0]);

    this._addToHistory({
      currentSlideIndex: newIndex,
      slides: slidesArray
    });
  }

  addSlide() {
    const slidesArray = this.slides;

    // TODO: Figure out new slide defaults/interface
    const newSlide = {
      id: generate(),
      props: {},
      children: [],
      color: allColors[6]
    };

    const index = this.currentSlideIndex + 1;
    slidesArray.splice(index, 0, newSlide);

    this._addToHistory({
      currentSlideIndex: index,
      currentElementIndex: null,
      slides: slidesArray
    });
  }

  deleteSlide() {
    const slidesArray = this.slides;
    const index = this.currentSlideIndex === 0 ? 0 : this.currentSlideIndex - 1;

    slidesArray.splice(this.currentSlideIndex, 1);

    this._addToHistory({
      currentSlideIndex: index,
      currentElementIndex: null,
      slides: slidesArray
    });
  }

  undo() {
    // double check we're not trying to undo without history
    if (this.historyIndex === 0) {
      return;
    }

    this.historyIndex -= 1;
  }

  redo() {
    // Double check we've got a future to redo to
    if (this.historyIndex > this.history.length - 1) {
      return;
    }

    this.historyIndex += 1;
  }

  // TODO: Cap history length to some number to prevent absurd memory leaks
  _addToHistory(snapshot) {
    // Only notify observers once all expressions have completed
    transaction(() => {
      // If we have a future and we do an action, remove the future.
      if (this.historyIndex < this.history.length - 1) {
        this.history = this.history.slice(0, this.historyIndex + 1);
      }

      // Wrapp the new slides array in an array so they aren't concatted as individual slide objects
      this.history = this.history.concat([Immutable.from(snapshot)]);
      this.historyIndex += 1;
    });
  }
}
<commit_msg>rename this.snapshot to this.currentState<commit_after>import { observable, computed, transaction } from "mobx";
import Immutable from "seamless-immutable";
import { generate } from "shortid";

import elementMap from "../elements";

// TODO: REMOVE. Useful for testing
const allColors = [
  "#EF767A", "#456990", "#49BEAA", "#49DCB1", "#EEB868", "#EF767A", "#456990",
  "#49BEAA", "#49DCB1", "#EEB868", "#EF767A"
];

export default class SlidesStore {
  // Default slides state
  // history will be an array of slides arrays
  @observable history = Immutable.from([{
    currentSlideIndex: 0,
    currentElementIndex: null,
    slides: [{
      // Default first slide
      id: generate(),
      props: {},
      children: [],
      color: allColors[0]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[1]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[2]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[3]
    }, {
      id: generate(),
      props: {},
      children: [],
      color: allColors[4]
    }
  ] }]);

  @observable historyIndex = 0;

  // Returns a new mutable object. Functions as a cloneDeep.
  @computed get slides() {
    return this.history[this.historyIndex].slides.asMutable({ deep: true });
  }

  @computed get currentSlideIndex() {
    return this.history[this.historyIndex].currentSlideIndex;
  }

  @computed get currentElementIndex() {
    return this.history[this.historyIndex].currentElementIndex;
  }

  // Returns a new mutable object. Functions as a cloneDeep.
  @computed get currentSlide() {
    return this.slides[this.currentSlideIndex];
  }

  // Returns a new mutable object. Functions as a cloneDeep.
  @computed get currentElement() {
    return this.currentElementIndex && this.currentSlide[this.currentElementIndex];
  }

  @computed get undoDisabled() {
    return this.historyIndex === 0 || this.history.length <= 1;
  }

  @computed get redoDisabled() {
    return this.historyIndex >= this.history.length - 1;
  }

  @computed get currentState() {
    return this.history[this.historyIndex].asMutable({ deep: true });
  }

  constructor(slides) {
    if (slides) {
      this.history = Immutable.from([{
        currentSlideIndex: 0,
        currentElementIndex: null,
        slides
      }]);
    }
  }

  dropElement(elementType) {
    const slideToAddTo = this.currentSlide;
    const newSlidesArray = this.slides;

    slideToAddTo.children.push({
      ...elementMap[elementType],
      id: generate()
    });

    newSlidesArray[this.currentSlideIndex] = slideToAddTo;
    const elementIndex = this.currentElementIndex ?
        this.currentElementIndex + 1 :
        slideToAddTo.children.length - 1;

    this._addToHistory({
      currentSlideIndex: this.currentSlideIndex,
      currentElementIndex: elementIndex,
      slides: newSlidesArray
    });
  }

  setCurrentElementIndex(newIndex) {
    const snapshot = this.currentState;
    snapshot.currentElementIndex = newIndex;

    transaction(() => {
      const left = this.history.slice(0, this.historyIndex);
      const right = this.history.slice(this.historyIndex + 1, this.history.length);
      this.history = left.concat([snapshot], right);
    });
  }

  setSelectedSlideIndex(newSlideIndex) {
    const snapshot = this.currentState;
    snapshot.currentElementIndex = null;
    snapshot.currentSlideIndex = newSlideIndex;

    transaction(() => {
      const left = this.history.slice(0, this.historyIndex);
      const right = this.history.slice(this.historyIndex + 1, this.history.length);
      this.history = left.concat([snapshot], right);
    });
  }

  moveSlide(currentIndex, newIndex) {
    const slidesArray = this.slides;

    slidesArray.splice(newIndex, 0, slidesArray.splice(currentIndex, 1)[0]);

    this._addToHistory({
      currentSlideIndex: newIndex,
      slides: slidesArray
    });
  }

  addSlide() {
    const slidesArray = this.slides;

    // TODO: Figure out new slide defaults/interface
    const newSlide = {
      id: generate(),
      props: {},
      children: [],
      color: allColors[6]
    };

    const index = this.currentSlideIndex + 1;
    slidesArray.splice(index, 0, newSlide);

    this._addToHistory({
      currentSlideIndex: index,
      currentElementIndex: null,
      slides: slidesArray
    });
  }

  deleteSlide() {
    const slidesArray = this.slides;
    const index = this.currentSlideIndex === 0 ? 0 : this.currentSlideIndex - 1;

    slidesArray.splice(this.currentSlideIndex, 1);

    this._addToHistory({
      currentSlideIndex: index,
      currentElementIndex: null,
      slides: slidesArray
    });
  }

  undo() {
    // double check we're not trying to undo without history
    if (this.historyIndex === 0) {
      return;
    }

    this.historyIndex -= 1;
  }

  redo() {
    // Double check we've got a future to redo to
    if (this.historyIndex > this.history.length - 1) {
      return;
    }

    this.historyIndex += 1;
  }

  // TODO: Cap history length to some number to prevent absurd memory leaks
  _addToHistory(snapshot) {
    // Only notify observers once all expressions have completed
    transaction(() => {
      // If we have a future and we do an action, remove the future.
      if (this.historyIndex < this.history.length - 1) {
        this.history = this.history.slice(0, this.historyIndex + 1);
      }

      // Wrapp the new slides array in an array so they aren't concatted as individual slide objects
      this.history = this.history.concat([Immutable.from(snapshot)]);
      this.historyIndex += 1;
    });
  }
}
<|endoftext|>


<commit_before>//List from node-htmlparser
var singleTags = {
  area: 1,
  base: 1,
  basefont: 1,
  br: 1,
  col: 1,
  frame: 1,
  hr: 1,
  img: 1,
  input: 1,
  isindex: 1,
  link: 1,
  meta: 1,
  param: 1,
  embed: 1
};

var expr = {
  upperCaseChars: /([A-Z])/g,
  breakBetweenTags: /(<(\/?\w+).*?>)(?=<(?!\/\2))/gi,
  singleTag: (function() {
    var tags = [];
    for (var i in singleTags) {
      tags.push(i);
    }
    return new RegExp('<' + tags.join('|<'), 'i');
  })()
};

var uncanon = function(str, letter) {
  return '-' + letter.toLowerCase();
};

var HTMLEncode = require('./htmlencoding').HTMLEncode;

exports.stringifyElement = function stringifyElement(element) {
  var tagName = element.tagName.toLowerCase(),
      ret = {
        start: "<" + tagName,
        end:''
      },
      attributes = [],
      i,
      attribute = null;

  if (element.attributes.length) {
    ret.start += " ";
    for (i = 0; i<element.attributes.length; i++) {
      attribute = element.attributes.item(i);
      attributes.push(attribute.name + '="' +
                      HTMLEncode(attribute.nodeValue, true) + '"');
    }
  }
  ret.start += attributes.join(" ");

  if (singleTags[tagName]) {
    ret.start += " />";
    ret.end = '';
  } else {
    ret.start += ">";
    ret.end = "</" + tagName + ">";
  }

  return ret;
};

var rawTextElements = /SCRIPT|STYLE/i;

function stringifyDoctype (doctype) {
  if (doctype.ownerDocument && doctype.ownerDocument._fullDT) {
    return doctype.ownerDocument._fullDT;
  }

  var dt = '<!DOCTYPE ' + doctype.name;
  if (doctype.publicId) {
    // Public ID may never contain double quotes, so this is always safe.
    dt += ' PUBLIC "' + doctype.publicId + '" ';
  }
  if (!doctype.publicId && doctype.systemId) {
    dt += ' SYSTEM ';
  }
  if (doctype.systemId) {
    // System ID may contain double quotes OR single quotes, not never both.
    if (doctype.systemId.indexOf('"') > -1) {
      dt += "'" + doctype.systemId + "'";
    } else {
      dt += '"' + doctype.systemId + '"';
    }
  }
  dt += '>';
  return dt;
}

exports.makeHtmlGenerator = function makeHtmlGenerator(indentUnit, eol) {
  indentUnit = indentUnit || "";
  eol = eol || "";

  return function generateHtmlRecursive(node, rawText, curIndent) {
    var ret = "", parent, current, i;
    curIndent = curIndent || "";
    if (node) {
      if (node.nodeType &&
          node.nodeType === node.ENTITY_REFERENCE_NODE) {
        node = node._entity;
      }

      var childNodesRawText = rawText || rawTextElements.test(node.nodeName);

      switch (node.nodeType) {
        case node.ELEMENT_NODE:
          current = exports.stringifyElement(node);
          if (childNodesRawText) {
            ret += curIndent + current.start;
          } else {
            ret += curIndent + current.start;
          }
          var len = node._childNodes.length;
          if (len > 0) {
            if (node._childNodes[0].nodeType !== node.TEXT_NODE) {
              ret += eol;
            }
            for (i=0; i<len; i++) {
              ret += generateHtmlRecursive(node._childNodes[i], childNodesRawText, curIndent + indentUnit);
            }
            if (node._childNodes[len - 1].nodeType !== node.TEXT_NODE) {
              ret += curIndent;
            }
            ret += current.end + eol;
          } else {
            ret += ((rawText ? node.nodeValue : HTMLEncode(node.nodeValue, false)) || '') + current.end + eol;
          }
          break;
        case node.TEXT_NODE:
          // Skip pure whitespace nodes if we're indenting
          if (!indentUnit || !/^[\s\n]*$/.test(node.nodeValue)) {
            ret += (rawText ? node.nodeValue : HTMLEncode(node.nodeValue, false)) || '';
          }
          break;
        case node.COMMENT_NODE:
          ret += curIndent + '<!--' + node.nodeValue + '-->' + eol;
          break;
        case node.DOCUMENT_NODE:
          for (i=0; i<node._childNodes.length; i++) {
            ret += generateHtmlRecursive(node._childNodes[i], childNodesRawText, curIndent);
          }
          break;
        case node.DOCUMENT_TYPE_NODE:
          ret += stringifyDoctype(node);
        break;
      }
    }
    return ret;
  };
};

exports.domToHtml = function(dom, noformat, raw) {
  var htmlGenerator = exports.makeHtmlGenerator(noformat ? "" : "  ",
                                                noformat ? "" : "\n");
  if (dom._toArray) {
    // node list
    dom = dom._toArray();
  }
  if (typeof dom.length !== 'undefined') {
    var ret = "";
    for (var i=0,len=dom.length; i<len; i++) {
      ret += htmlGenerator(dom[i], raw);
    }
    return ret;
  } else {
    // single node
    return htmlGenerator(dom, raw);
  }
};
<commit_msg>domtohtml: Update the list of void elements.<commit_after>//List from htmlparser2
var singleTags = {
  area: true,
  base: true,
  basefont: true,
  br: true,
  col: true,
  command: true,
  embed: true,
  frame: true,
  hr: true,
  img: true,
  input: true,
  isindex: true,
  keygen: true,
  link: true,
  meta: true,
  param: true,
  source: true,
  track: true,
  wbr: true
};

var expr = {
  upperCaseChars: /([A-Z])/g,
  breakBetweenTags: /(<(\/?\w+).*?>)(?=<(?!\/\2))/gi,
  singleTag: (function() {
    var tags = [];
    for (var i in singleTags) {
      tags.push(i);
    }
    return new RegExp('<' + tags.join('|<'), 'i');
  })()
};

var uncanon = function(str, letter) {
  return '-' + letter.toLowerCase();
};

var HTMLEncode = require('./htmlencoding').HTMLEncode;

exports.stringifyElement = function stringifyElement(element) {
  var tagName = element.tagName.toLowerCase(),
      ret = {
        start: "<" + tagName,
        end:''
      },
      attributes = [],
      i,
      attribute = null;

  if (element.attributes.length) {
    ret.start += " ";
    for (i = 0; i<element.attributes.length; i++) {
      attribute = element.attributes.item(i);
      attributes.push(attribute.name + '="' +
                      HTMLEncode(attribute.nodeValue, true) + '"');
    }
  }
  ret.start += attributes.join(" ");

  if (singleTags[tagName]) {
    ret.start += " />";
    ret.end = '';
  } else {
    ret.start += ">";
    ret.end = "</" + tagName + ">";
  }

  return ret;
};

var rawTextElements = /SCRIPT|STYLE/i;

function stringifyDoctype (doctype) {
  if (doctype.ownerDocument && doctype.ownerDocument._fullDT) {
    return doctype.ownerDocument._fullDT;
  }

  var dt = '<!DOCTYPE ' + doctype.name;
  if (doctype.publicId) {
    // Public ID may never contain double quotes, so this is always safe.
    dt += ' PUBLIC "' + doctype.publicId + '" ';
  }
  if (!doctype.publicId && doctype.systemId) {
    dt += ' SYSTEM ';
  }
  if (doctype.systemId) {
    // System ID may contain double quotes OR single quotes, not never both.
    if (doctype.systemId.indexOf('"') > -1) {
      dt += "'" + doctype.systemId + "'";
    } else {
      dt += '"' + doctype.systemId + '"';
    }
  }
  dt += '>';
  return dt;
}

exports.makeHtmlGenerator = function makeHtmlGenerator(indentUnit, eol) {
  indentUnit = indentUnit || "";
  eol = eol || "";

  return function generateHtmlRecursive(node, rawText, curIndent) {
    var ret = "", parent, current, i;
    curIndent = curIndent || "";
    if (node) {
      if (node.nodeType &&
          node.nodeType === node.ENTITY_REFERENCE_NODE) {
        node = node._entity;
      }

      var childNodesRawText = rawText || rawTextElements.test(node.nodeName);

      switch (node.nodeType) {
        case node.ELEMENT_NODE:
          current = exports.stringifyElement(node);
          if (childNodesRawText) {
            ret += curIndent + current.start;
          } else {
            ret += curIndent + current.start;
          }
          var len = node._childNodes.length;
          if (len > 0) {
            if (node._childNodes[0].nodeType !== node.TEXT_NODE) {
              ret += eol;
            }
            for (i=0; i<len; i++) {
              ret += generateHtmlRecursive(node._childNodes[i], childNodesRawText, curIndent + indentUnit);
            }
            if (node._childNodes[len - 1].nodeType !== node.TEXT_NODE) {
              ret += curIndent;
            }
            ret += current.end + eol;
          } else {
            ret += ((rawText ? node.nodeValue : HTMLEncode(node.nodeValue, false)) || '') + current.end + eol;
          }
          break;
        case node.TEXT_NODE:
          // Skip pure whitespace nodes if we're indenting
          if (!indentUnit || !/^[\s\n]*$/.test(node.nodeValue)) {
            ret += (rawText ? node.nodeValue : HTMLEncode(node.nodeValue, false)) || '';
          }
          break;
        case node.COMMENT_NODE:
          ret += curIndent + '<!--' + node.nodeValue + '-->' + eol;
          break;
        case node.DOCUMENT_NODE:
          for (i=0; i<node._childNodes.length; i++) {
            ret += generateHtmlRecursive(node._childNodes[i], childNodesRawText, curIndent);
          }
          break;
        case node.DOCUMENT_TYPE_NODE:
          ret += stringifyDoctype(node);
        break;
      }
    }
    return ret;
  };
};

exports.domToHtml = function(dom, noformat, raw) {
  var htmlGenerator = exports.makeHtmlGenerator(noformat ? "" : "  ",
                                                noformat ? "" : "\n");
  if (dom._toArray) {
    // node list
    dom = dom._toArray();
  }
  if (typeof dom.length !== 'undefined') {
    var ret = "";
    for (var i=0,len=dom.length; i<len; i++) {
      ret += htmlGenerator(dom[i], raw);
    }
    return ret;
  } else {
    // single node
    return htmlGenerator(dom, raw);
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import {
	TouchableOpacity,
	Text,
	StyleSheet,
	ListView,
	View
} from 'react-native';

import Icon from 'react-native-vector-icons/FontAwesome';
import css from '../../styles/css';

const resultsDataSource = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });

const ShuttleStopsListView = ({ shuttle_stops, addStop }) => (
	<ListView
		style={[css.main_container, css.scroll_main, css.whitebg]}
		dataSource={resultsDataSource.cloneWithRows(shuttle_stops)}
		renderRow={
			(row) =>
				<StopItem
					data={row}
					addStop={addStop}
				/>
		}
	/>
);

const StopItem = ({ data, addStop }) => (
	<View
		style={styles.list_row}
	>
		<TouchableOpacity
			onPress={() => addStop(data.id, data.name.trim())}
			style={styles.touchable}
			disabled={(data.saved === true)}
		>
			<Text style={(data.saved) ? (styles.row_name_disabled) : (styles.row_name)}>
				{data.name.trim()}
			</Text>
			<Icon
				style={styles.icon}
				color="rgba(116,118,120,.6)"
				name="chevron-right"
				size={20}
			/>
		</TouchableOpacity>
	</View>
);

const styles = StyleSheet.create({
	icon: { alignSelf: 'flex-end' },
	touchable: { flex: 1, flexDirection: 'row', alignItems: 'center' },
	row_name: { flex: 1, paddingRight: 10 },
	row_name_disabled: { color: '#DDD', flex: 1, paddingRight: 10 },
	list_row: { flex: 1, height: 60, padding: 7, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: '#EEE', overflow: 'hidden' },
});

export default ShuttleStopsListView;
<commit_msg>Hide added stop<commit_after>import React from 'react';
import {
	TouchableOpacity,
	Text,
	StyleSheet,
	ListView,
	View
} from 'react-native';

import Icon from 'react-native-vector-icons/FontAwesome';
import css from '../../styles/css';

const resultsDataSource = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });

const ShuttleStopsListView = ({ shuttle_stops, addStop }) => (
	<ListView
		style={[css.main_container, css.scroll_main, css.whitebg]}
		dataSource={resultsDataSource.cloneWithRows(shuttle_stops)}
		renderRow={
			(row) => {
				if (row.saved === true) {
					return null;
				} else {
					return (
						<StopItem
							data={row}
							addStop={addStop}
						/>
					);
				}
			}
		}
	/>
);

const StopItem = ({ data, addStop }) => (
	<View
		style={styles.list_row}
	>
		<TouchableOpacity
			onPress={() => addStop(data.id, data.name.trim())}
			style={styles.touchable}
			disabled={(data.saved === true)}
		>
			<Text style={(data.saved === true) ? (styles.row_name_disabled) : (styles.row_name)}>
				{data.name.trim()}
			</Text>
			<Icon
				style={styles.icon}
				color="rgba(116,118,120,.6)"
				name="chevron-right"
				size={20}
			/>
		</TouchableOpacity>
	</View>
);

const styles = StyleSheet.create({
	icon: { alignSelf: 'flex-end' },
	touchable: { flex: 1, flexDirection: 'row', alignItems: 'center' },
	row_name: { flex: 1, paddingRight: 10 },
	row_name_disabled: { color: '#DDD', flex: 1, paddingRight: 10 },
	list_row: { flex: 1, height: 60, padding: 7, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: '#EEE', overflow: 'hidden' },
});

export default ShuttleStopsListView;
<|endoftext|>


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

        sass  : {
            dist : {
                options : {
                },
                files : {
                    'css/site.css' : 'sass/site.sass'
                }
            }
        },

        php :{
                dist : {
                    options : {
                        keepalive : true,
                        port: 9000
                    }
            }
        }, // ends php task

        watch : {
            styles  : {
                files : [ 'sass/*'],
                tasks : ['sass'],
                options : {
                    livereload: true
                }
            } // ends watch/styles
        },

	concurrent : {
	    target1 : ['php', 'watch']
	}

    });  // end task defintions

    grunt.loadNpmTasks('grunt-php');
    grunt.loadNpmTasks('grunt-concurrent');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.registerTask( 'default' , ['concurrent'] ) ;

} ;
<commit_msg>line up concurrent tasks<commit_after>module.exports = function (grunt){
    grunt.initConfig({

        sass  : {
            dist : {
                options : {
                },
                files : {
                    'css/site.css' : 'sass/site.sass'
                }
            }
        },

        php :{
            dist : {
                options : {
                    keepalive : true,
                    port: 9000
                }
            }
        }, // ends php task

        watch : {
            styles  : {
                files : [ 'sass/*'],
                tasks : ['sass']
            }, // ends watch/styles
            templates : {
                files : ['*.php', '*.html'],
                tasks : []
            },

            reload : {
                files : ['*/*'],
                tasks : [],
                options : {
                    livereload : true
                }
            },
        },

        concurrent : {
            target1 : ['php', 'watch:styles', 'watch:templates', 'watch:reload']
        }

    });  // end task defintions

    grunt.loadNpmTasks('grunt-php');
    grunt.loadNpmTasks('grunt-concurrent');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.registerTask( 'default' , ['concurrent'] ) ;

} ;
<|endoftext|>


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

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

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    watch: {
      options: {
        atBegin: true
      },

      css: {
        files: ['sass/**/*.scss'],
        tasks: ['compass', 'cssmin']
      },
    },

    compass: {
      compile: {
        options: {
          httpPath '/',
          sassDir: 'src/sass',
          cssDir: 'web/css',
          javascriptsDir: 'web/js'
          imagesDir: 'web/images',
          fontsDir: 'web/fonts',
          outputStyle: 'expanded',
          require: [
            'sass-globbing'
          ]
        }
      }
    },

    cssmin: {
      options: {
        report: 'min'
      },

      minify: {
        expand: true,
        cwd: 'css/',
        src: ['*.css', '!*.min.css'],
        dest: 'css/',
        ext: '.min.css'
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'images/',
          src: '{,*/}*.{gif,jpeg,jpg,png}',
          dest: 'images-imagemin/'
        }]
      }
    }

  });

  grunt.registerTask('default', ['watch']);
};<commit_msg>Fix Gruntfile<commit_after>module.exports = function(grunt) {

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

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    watch: {
      options: {
        atBegin: true
      },

      css: {
        files: ['sass/**/*.scss'],
        tasks: ['compass', 'cssmin']
      },
    },

    compass: {
      compile: {
        options: {
          httpPath: '/',
          sassDir: 'sass',
          cssDir: 'css',
          javascriptsDir: 'js',
          imagesDir: 'images',
          fontsDir: 'fonts',
          outputStyle: 'expanded',
          require: [
            'sass-globbing'
          ]
        }
      }
    },

    cssmin: {
      options: {
        report: 'min'
      },

      minify: {
        expand: true,
        cwd: 'css/',
        src: ['*.css', '!*.min.css'],
        dest: 'css/',
        ext: '.min.css'
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'images/',
          src: '{,*/}*.{gif,jpeg,jpg,png}',
          dest: 'images-imagemin/'
        }]
      }
    }

  });

  grunt.registerTask('default', ['watch']);
};<|endoftext|>


<commit_before>module.exports = function (grunt) {
	'use strict';

	// load all grunt tasks
	require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

		//Process CSS
		compass: {
			dev: {
				options: {
					config: 'config.rb',
					force: true
				}
			},
		},

		autoprefixer: {
			options: {
				browsers: ['last 2 versions']
			},
			dist: {
				files: [
					{ src: ['styles/main.css'], dest: 'styles/main.css' }
				]
			},
		},

		//Process Javascript
		uglify: {
			initiate: {
				files:
				[
					{
						src: ['components/modernizr/modernizr.js'],
						dest: 'js/vendor/modernizr.min.js'
					}
				]
			},
			dist: {
				files:
				[
					{
						src: ['js/main.js'],
						dest: 'js/main.min.js'
					}
				]
			},
		},

		concat : {
			dist : {
				src : ['js/plugins/*.js', 'js/main.js'],
				dest : 'js/main.min.js'
			},
		},

		//copy files from components to js
		copy: {
			initiate: {
				files:
				[
					{
						expand: true,
						cwd: 'components/jquery/',
						src: ['jquery.min.js'],
						dest: 'js/vendor/'
					},
					{
						expand: true,
						cwd: 'components/normalize.scss/',
						src: ['_normalize.scss'],
						dest: 'sass/base/'
					},
					//Foundation
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/',
						src: ['_variables.scss'],
						dest: 'sass/vendor/foundation/'
					},
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/components/',
						src: ['_global.scss'],
						dest: 'sass/vendor/foundation/components/'
					},
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/components/',
						src: ['_grid.scss'],
						dest: 'sass/vendor/foundation/components/'
					},
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/components/',
						src: ['_visibility.scss'],
						dest: 'sass/vendor/foundation/components/'
					}
				]
			},
		},

		watch: {
				/* watch to see if the sass files are changed, compile and add prefixes */
				styles: {
					files: ['sass/**/*.{scss,sass}'],
					tasks: ['compass:dev', 'autoprefixer']
				},

				// autoprefix: {
				//   files: ['styles/main.css'],
				//   tasks: ['autoprefixer']
				// },

				/* watch and see if our javascript files change, or new packages are installed */

				concatenate: {
					files: ['js/plugins/*.js', 'js/main.js'],
					tasks: ['concat:dist'],
					options: {
						livereload: true,
					},
				},

				uglifyit: {
					files: ['js/main.js'],
					tasks: ['uglify:dist'],
					options: {
						livereload: true,
					},
				},

				/* watch our files for change, reload */
				livereload: {
					files: ['*.html', '*.php', 'styles/*.css', 'images/**/*.{png,jpg,jpeg,gif,webp,svg}', '*.js'],
					options: {
						livereload: true
					},
				},
			},

		});

	//Task list
	grunt.registerTask('initiate', ['copy', 'uglify:initiate']);
	grunt.registerTask('lint', ['jshint']);
	grunt.registerTask('default', ['watch']);
};<commit_msg>Added build task, removed jshint task, removed uglify task from watch task<commit_after>module.exports = function (grunt) {
	'use strict';

	// load all grunt tasks
	require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

		//Process CSS
		compass: {
			dev: {
				options: {
					config: 'config.rb',
					force: true
				}
			},
		},

		autoprefixer: {
			options: {
				browsers: ['last 2 versions']
			},
			dist: {
				files: [
					{ src: ['styles/main.css'], dest: 'styles/main.css' }
				]
			},
		},

		//Process Javascript
		uglify: {
			initiate: {
				files:
				[
					{
						src: ['components/modernizr/modernizr.js'],
						dest: 'js/vendor/modernizr.min.js'
					}
				]
			},
			dist: {
				files:
				[
					{
						src: ['js/main.min.js'],
						dest: 'js/main.min.js'
					}
				]
			},
		},

		concat : {
			dist : {
				src : ['js/plugins/*.js', 'js/main.js'],
				dest : 'js/main.min.js'
			},
		},

		//copy files from components to js
		copy: {
			initiate: {
				files:
				[
					{
						expand: true,
						cwd: 'components/jquery/',
						src: ['jquery.min.js'],
						dest: 'js/vendor/'
					},
					{
						expand: true,
						cwd: 'components/normalize.scss/',
						src: ['_normalize.scss'],
						dest: 'sass/base/'
					},
					//Foundation
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/',
						src: ['_variables.scss'],
						dest: 'sass/vendor/foundation/'
					},
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/components/',
						src: ['_global.scss'],
						dest: 'sass/vendor/foundation/components/'
					},
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/components/',
						src: ['_grid.scss'],
						dest: 'sass/vendor/foundation/components/'
					},
					{
						expand: true,
						cwd: 'components/foundation/scss/foundation/components/',
						src: ['_visibility.scss'],
						dest: 'sass/vendor/foundation/components/'
					}
				]
			},
		},

		watch: {
				/* watch to see if the sass files are changed, compile and add prefixes */
				styles: {
					files: ['sass/**/*.{scss,sass}'],
					tasks: ['compass:dev', 'autoprefixer']
				},

				// autoprefix: {
				//   files: ['styles/main.css'],
				//   tasks: ['autoprefixer']
				// },

				/* watch and see if our javascript files change, or new packages are installed */

				concatenate: {
					files: ['js/plugins/*.js', 'js/main.js'],
					tasks: ['concat:dist'],
					options: {
						livereload: true,
					},
				},

				/* watch our files for change, reload */
				livereload: {
					files: ['*.html', '*.php', 'styles/*.css', 'images/**/*.{png,jpg,jpeg,gif,webp,svg}', '*.js'],
					options: {
						livereload: true
					},
				},
			},

		});

	//Task list
	grunt.registerTask('initiate', ['copy', 'uglify:initiate']);
	grunt.registerTask('build', ['uglify:dist']);
	grunt.registerTask('default', ['watch']);
};<|endoftext|>


<commit_before>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %>
'use strict';

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dev: 'dev',
        dist: 'dist'
    };

    grunt.initConfig({
        yeoman: yeomanConfig,

        watch: {
            options: {
                livereload: true,
            },
            css: {
                files: ['<%%= yeoman.app %>/assets/scss/*.scss'],
                tasks: ['compass']
            },
            html: {
                files: ['<%%= yeoman.app %>/*.html'],
                tasks: ['copy']
            }
        },

        connect: {
            options: {
                port: 9000,
                livereload: 35729,
                hostname: '0.0.0.0',
                base: '<%%= yeoman.dev %>'
            },
            livereload: {
                options: {
                    open: 'http://localhost:<%%= connect.options.port %>',
                    base: [
                        '<%%= yeoman.dev %>'
                    ]
                }
            }
        },

        open: {
            server: {
                path: 'http://localhost:<%%= connect.options.port %>'
            }
        },

        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%%= yeoman.dist %>/*',
                        '!<%%= yeoman.dist %>/.git*'
                    ]
                }]
            }
        },

        copy: {
            dev: {
                files: [
                    {expand: true, cwd: '<%%= yeoman.app %>', src: ['**', '!**/scss/**'], dest: '<%%= yeoman.dev %>'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/scss/fonts', src: ['**'], dest: '<%%= yeoman.dev %>/assets/css/fonts'}
                ]
            },

            dist: {
                files: [
                    {expand: true, cwd: '<%%= yeoman.app %>', src: ['**', '!**/scss/**', '!**/js/*.js', '!**/bower_components/**'], dest: '<%%= yeoman.dist %>'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/scss/fonts', src: ['**'], dest: '<%%= yeoman.dist %>/assets/css/fonts'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/bower_components/jquery', src: ['jquery.min.js'], dest: '<%%= yeoman.dist %>/assets/js/lib'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/bower_components/jquery-legacy', src: ['jquery.min.js'], dest: '<%%= yeoman.dist %>/assets/js/lib', rename: function (dest) {
                        return dest + '/jquery-legacy.min.js';
                    }},
                    // Only copy over the minified migrate plugin
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/bower_components/jquery-migrate', src: ['jquery-migrate.min.js'], dest: '<%%= yeoman.dist %>/assets/js/lib'}
                ]
            }
        },

        compass: {
            dev: {
                options: {
                    sassDir: '<%%= yeoman.app %>/assets/scss',
                    cssDir: '<%%= yeoman.dev %>/assets/css',
                    environment: 'development'
                }
            },

            dist: {
                options: {
                    sassDir: '<%%= yeoman.app %>/assets/scss',
                    cssDir: '<%%= yeoman.dist %>/assets/css',
                    environment: 'production'
                }
            }
        },

/*        uglify: {
            dist: {
                files: {
                    '<%%= yeoman.dist %>/assets/js/main.js': [
                        '<%%= yeoman.app %>/assets/js/variables.js',
                        '<%%= yeoman.app %>/assets/js/functions.js',
                        '<%%= yeoman.app %>/assets/js/script.js',
                        '<%%= yeoman.app %>/assets/js/event.js'
                    ],
                    '<%%= yeoman.dist %>/assets/js/lteie8.main.js': [
                        '<%%= yeoman.app %>/assets/bower_components/selectivizr/selectivizr.js',
                        '<%%= yeoman.app %>/assets/bower_components/respond/respond.src.js'
                    ]
                }
            }
        },*/

        replace: {
            dist: {
                options: {
                    patterns: [{
                        match: '/@jquery-cdn/g',
                        replacement: function () {
                            var jQConf = grunt.file.readJSON('app/assets/bower_components/jquery/bower.json');
                            return '//ajax.googleapis.com/ajax/libs/jquery/' + jQConf.version + '/jquery.min.js';
                        },
                        expression: true
                    }, {
                        match: '/@jquery-legacy-cdn/g',
                        replacement: function () {
                            var jQLegConf = grunt.file.readJSON('app/assets/bower_components/jquery-legacy/bower.json');
                            return '//ajax.googleapis.com/ajax/libs/jquery/' + jQLegConf.version + '/jquery.min.js';
                        },
                        expression: true
                    }]
                },
                files: [
                    {src:  ['app/index.html'], dest: 'app/index.html'}
                ]
            }
        },

        processhtml: {
            options: {
                process: true,
                templateSettings: {
                    opener: '{!',
                    closer: '!}'
                }
            },
            dev: {
                options: {
                    data: {
                        jqMinLocal: 'assets/bower_components/jquery/jquery.min.js',
                        jqLegMinLocal: 'assets/bower_components/jquery-legacy/jquery.min.js',
                        jqMigrate: 'assets/bower_components/jquery-migrate/jquery-migrate.js'
                    }
                },
                files: {
                    '<%%= yeoman.dev %>/index.html': ['<%%= yeoman.app %>/index.html']
                }
            },
            dist: {
                options: {
                    data: {
                        jqMinLocal: 'assets/js/lib/jquery.min.js',
                        jqLegMinLocal: 'assets/js/lib/jquery-legacy.min.js',
                        jqMigrate: 'assets/js/lib/jquery-migrate.min.js'
                    }
                },
                files: {
                    '<%%= yeoman.dist %>/index.html': ['<%%= yeoman.app %>/index.html']
                }
            }
        },

        modernizr: {
            'devFile' : '<%%= yeoman.app %>/assets/bower_components/modernizr/modernizr.js',
            'outputFile' : '<%%= yeoman.dist %>/assets/js/lib/modernizr-custom.min.js',
            'files' : ['<%%= yeoman.dist %>/**/*.js', '<%%= yeoman.dist %>/**/*.css', '<%%= yeoman.dist %>/**/*.scss']
        },

        rev: {
            dist: {
                files: {
                    src: [
                        '<%%= yeoman.dist %>/assets/js/{,*/}*.js',
                        '<%%= yeoman.dist %>/assets/css/{,*/}*.css',
                        '<%%= yeoman.dist %>/assets/img/{,*/}*.{png,jpg,jpeg,gif,webp}',
                        '<%%= yeoman.dist %>/assets/css/fonts/*'
                    ]
                }
            }
        },

        useminPrepare: {
            options: {
                dest: '<%%= yeoman.dist %>'
            },
            html: '<%%= yeoman.app %>/index.html'
        },

        usemin: {
            options: {
                dirs: ['<%%= yeoman.dist %>']
            },
            html: ['<%%= yeoman.dist %>/*.html']
            /*html: ['** /*.html'],
            css: ['** /*.css']*/
        }

    });

    grunt.registerTask('server', function (target) {
        if (target === 'dev') {
            return grunt.task.run(['dev', 'watchit:dev']);
        }

        if (target === 'build') {
            return grunt.task.run(['build', 'watchit:dist']);
        }

        grunt.task.run([
            'connect:livereload',
            'watch'
        ]);
    });

    grunt.registerTask('watchit', function (type) {
        grunt.config('connect.livereload.options.base', '<%%= yeoman.' + type + ' %>');

        if (type === 'dev') {
            grunt.config('watch.html.tasks', ['copy:' + type, 'replace', 'processhtml:' + type]);
        }
        if (type === 'dist') {
            grunt.config('watch.html.tasks', ['copy:' + type, 'replace', 'modernizr', 'processhtml:' + type, 'useminPrepare', 'concat', 'uglify', 'rev', 'usemin']);
        }

        grunt.config('watch.css.tasks', 'compass:' + type);
        grunt.task.run('connect:livereload');
        grunt.task.run('watch');
    });

    grunt.registerTask('dev', [
        'clean', 'copy:dev', 'compass:dev', 'replace', 'processhtml:dev'
    ]);

    grunt.registerTask('build', [
        'clean', 'copy:dist', 'compass:dist', 'replace:dist', 'modernizr', 'processhtml:dist', 'useminPrepare', 'concat', 'uglify', 'rev', 'usemin'
    ]);
};<commit_msg>Remove server:build as was unnecessary<commit_after>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %>
'use strict';

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dev: 'dev',
        dist: 'dist'
    };

    grunt.initConfig({
        yeoman: yeomanConfig,

        watch: {
            options: {
                livereload: true,
            },
            css: {
                files: ['<%%= yeoman.app %>/assets/scss/*.scss'],
                tasks: ['compass:dev']
            },
            html: {
                //files: ['<%%= yeoman.app %>/{,*/}*.html'],
                //files: ['<%%= yeoman.app %>/*.html', '<%%= yeoman.app %>/*/*.html'],
                files: ['<%%= yeoman.app %>/**/*.html'],
                tasks: ['copy:html', 'replace', 'processhtml:dev']
            }
        },

        connect: {
            options: {
                port: 9000,
                livereload: 35729,
                hostname: '0.0.0.0',
                base: '<%%= yeoman.dev %>'
            },
            livereload: {
                options: {
                    open: 'http://localhost:<%%= connect.options.port %>',
                    base: [
                        '<%%= yeoman.dev %>'
                    ]
                }
            }
        },

        open: {
            server: {
                path: 'http://localhost:<%%= connect.options.port %>'
            }
        },

        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%%= yeoman.dist %>/*',
                        '!<%%= yeoman.dist %>/.git*'
                    ]
                }]
            }
        },

        copy: {
            dev: {
                files: [
                    {expand: true, cwd: '<%%= yeoman.app %>', src: ['**', '!**/scss/**'], dest: '<%%= yeoman.dev %>'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/scss/fonts', src: ['**'], dest: '<%%= yeoman.dev %>/assets/css/fonts'}
                ]
            },

            dist: {
                files: [
                    {expand: true, cwd: '<%%= yeoman.app %>', src: ['**', '!**/scss/**', '!**/js/*.js', '!**/bower_components/**'], dest: '<%%= yeoman.dist %>'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/scss/fonts', src: ['**'], dest: '<%%= yeoman.dist %>/assets/css/fonts'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/bower_components/jquery', src: ['jquery.min.js'], dest: '<%%= yeoman.dist %>/assets/js/lib'},
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/bower_components/jquery-legacy', src: ['jquery.min.js'], dest: '<%%= yeoman.dist %>/assets/js/lib', rename: function (dest) {
                        return dest + '/jquery-legacy.min.js';
                    }},
                    // Only copy over the minified migrate plugin
                    {expand: true, cwd: '<%%= yeoman.app %>/assets/bower_components/jquery-migrate', src: ['jquery-migrate.min.js'], dest: '<%%= yeoman.dist %>/assets/js/lib'}
                ]
            },

            html: {
                files: [
                    {expand: true, cwd: '<%%= yeoman.app %>', src: ['{,*/}*.html'], dest: '<%%= yeoman.dev %>'}
                ]
            }
        },

        compass: {
            dev: {
                options: {
                    sassDir: '<%%= yeoman.app %>/assets/scss',
                    cssDir: '<%%= yeoman.dev %>/assets/css',
                    environment: 'development'
                }
            },

            dist: {
                options: {
                    sassDir: '<%%= yeoman.app %>/assets/scss',
                    cssDir: '<%%= yeoman.dist %>/assets/css',
                    environment: 'production'
                }
            }
        },

/*        uglify: {
            dist: {
                files: {
                    '<%%= yeoman.dist %>/assets/js/main.js': [
                        '<%%= yeoman.app %>/assets/js/variables.js',
                        '<%%= yeoman.app %>/assets/js/functions.js',
                        '<%%= yeoman.app %>/assets/js/script.js',
                        '<%%= yeoman.app %>/assets/js/event.js'
                    ],
                    '<%%= yeoman.dist %>/assets/js/lteie8.main.js': [
                        '<%%= yeoman.app %>/assets/bower_components/selectivizr/selectivizr.js',
                        '<%%= yeoman.app %>/assets/bower_components/respond/respond.src.js'
                    ]
                }
            }
        },*/

        replace: {
            dist: {
                options: {
                    patterns: [{
                        match: '/@jquery-cdn/g',
                        replacement: function () {
                            var jQConf = grunt.file.readJSON('app/assets/bower_components/jquery/bower.json');
                            return '//ajax.googleapis.com/ajax/libs/jquery/' + jQConf.version + '/jquery.min.js';
                        },
                        expression: true
                    }, {
                        match: '/@jquery-legacy-cdn/g',
                        replacement: function () {
                            var jQLegConf = grunt.file.readJSON('app/assets/bower_components/jquery-legacy/bower.json');
                            return '//ajax.googleapis.com/ajax/libs/jquery/' + jQLegConf.version + '/jquery.min.js';
                        },
                        expression: true
                    }]
                },
                files: [
                    {src:  ['app/index.html'], dest: 'app/index.html'}
                ]
            }
        },

        processhtml: {
            options: {
                process: true,
                templateSettings: {
                    opener: '{!',
                    closer: '!}'
                }
            },
            dev: {
                options: {
                    data: {
                        jqMinLocal: 'assets/bower_components/jquery/jquery.min.js',
                        jqLegMinLocal: 'assets/bower_components/jquery-legacy/jquery.min.js',
                        jqMigrate: 'assets/bower_components/jquery-migrate/jquery-migrate.js'
                    }
                },
                files: {
                    '<%%= yeoman.dev %>/index.html': ['<%%= yeoman.app %>/index.html']
                }
            },
            dist: {
                options: {
                    data: {
                        jqMinLocal: 'assets/js/lib/jquery.min.js',
                        jqLegMinLocal: 'assets/js/lib/jquery-legacy.min.js',
                        jqMigrate: 'assets/js/lib/jquery-migrate.min.js'
                    }
                },
                files: {
                    '<%%= yeoman.dist %>/index.html': ['<%%= yeoman.app %>/index.html']
                }
            }
        },

        modernizr: {
            'devFile' : '<%%= yeoman.app %>/assets/bower_components/modernizr/modernizr.js',
            'outputFile' : '<%%= yeoman.dist %>/assets/js/lib/modernizr-custom.min.js',
            'files' : ['<%%= yeoman.dist %>/**/*.js', '<%%= yeoman.dist %>/**/*.css', '<%%= yeoman.dist %>/**/*.scss']
        },

        rev: {
            dist: {
                files: {
                    src: [
                        '<%%= yeoman.dist %>/assets/js/{,*/}*.js',
                        '<%%= yeoman.dist %>/assets/css/{,*/}*.css',
                        '<%%= yeoman.dist %>/assets/img/{,*/}*.{png,jpg,jpeg,gif,webp}',
                        '<%%= yeoman.dist %>/assets/css/fonts/*'
                    ]
                }
            }
        },

        useminPrepare: {
            options: {
                dest: '<%%= yeoman.dist %>'
            },
            html: '<%%= yeoman.app %>/index.html'
        },

        usemin: {
            options: {
                dirs: ['<%%= yeoman.dist %>']
            },
            html: ['<%%= yeoman.dist %>/*.html']
        }
    });

    grunt.registerTask('server', [
        'dev', 'connect:livereload', 'watch'
    ]);

    grunt.registerTask('dev', [
        'clean', 'copy:dev', 'compass:dev', 'replace', 'processhtml:dev'
    ]);

    grunt.registerTask('build', [
        'clean', 'copy:dist', 'compass:dist', 'replace:dist', 'modernizr', 'processhtml:dist', 'useminPrepare', 'concat', 'uglify', 'rev', 'usemin'
    ]);
};<|endoftext|>