<commit_before>/**
 * @file Tool definition for the PC dual purpose selection tool. Provides event
 * handlers and special logic for the selection tool ONLY. Allows selection of
 * entire objects, rotation, scaling and node/segment adjustment.
 **/
"use strict";

module.exports = function(paper) {
  var tool = new paper.Tool();

  // Paper global extenders
  var Path = paper.Path;
  var Point = paper.Point;
  var Rectangle = paper.Rectangle;
  var project = paper.project;

  // Handy internal vars
  paper.selectRect = null;
  var selectionRectangleScale = null;
  var selectionRectangleRotation = null;
  var segment, path;
  paper.imageTraceMode = false;
  var hitOptions = {
    segments: true,
    stroke: true,
    fill: true,
    tolerance: 5
  };

  // Externalize deseletion
  paper.deselect = function() {
    if (paper.selectRect) {
      paper.selectRect.remove();
      paper.selectRect = null;

      // Complete imageTraceMode if we're deselecting.
      if (paper.imageTraceMode) {
        paper.finishImageImport();
      }
    }
  };

  // Tool identification (for building out tool palette)
  tool.name = 'tools.select';
  tool.key = 'select';
  tool.cursorOffset = '1 1'; // Position for cursor point

  tool.onMouseDown = function(event) {
    segment = path = null;

    var hitResult = project.hitTest(event.point, hitOptions);

    // Don't select image if not in trace mode
    if (hitResult && !paper.imageTraceMode) {
      if (paper.traceImage) {
        if (hitResult.item == paper.traceImage
                || hitResult.item == paper.traceImage.img) {
          hitResult = null; // Act like we didn't hit anything
        }
      }
    }

    // If we didn't hit anything with hitTest...
    if (!hitResult) {
      // Finish imageTraceMode
      if (paper.imageTraceMode) {
        paper.deselect();
        return;
      }

      // Find any items that are Paths (not layers) that contain the point
      var item = getBoundSelection(event.point);

      // If we actually found something, fake a fill hitResult
      if (item) {
        hitResult = {
          type: 'fill', // SURE it is ;)
          item: item
        };
      } else {
        // Deselect if nothing clicked (feels natural for deselection)
        if (paper.selectRect !== null) {
          paper.deselect();
        }

        return;
      }
    }

    if (event.modifiers.shift) {
      if (hitResult.type === 'segment') {
        hitResult.segment.remove();
      }
      return;
    }

    if (hitResult) {
      if (paper.imageTraceMode) {

        // Select the group, not the image
        if (hitResult.item == paper.traceImage.img) {
          hitResult.item = paper.traceImage;
        }

        //console.log('HITRESULT', hitResult.item);

        // Don't select any other items if in image trace mode
        if (hitResult.item != paper.selectRect && hitResult.item != paper.traceImage) {
          return;
        }
      }

      path = hitResult.item;

      if (hitResult.type === 'segment') {
        if (paper.selectRect !== null && path.name === "selection rectangle") {
          if (hitResult.segment.index >= 2 && hitResult.segment.index <= 4) {
            // Rotation hitbox
            selectionRectangleRotation = 0;
          } else {
            // Scale hitbox
            selectionRectangleScale = event.point.subtract(paper.selectRect.bounds.center).length / path.scaling.x;
          }
        } else {
          segment = hitResult.segment;
        }
      } else if (hitResult.type === 'stroke' && path !== paper.selectRect) {
        if (paper.selectRect && paper.selectRect.ppath === path) {
          // Add new segment node to the path (if it's already selected)
          var location = hitResult.location;
          segment = path.insert(location.index + 1, event.point);
        }
      }

      if ((paper.selectRect === null || paper.selectRect.ppath !== path) && paper.selectRect !== path) {
        initSelectionRectangle(path);
      }
    }

    // If a fill hit, move the path
    if (hitResult.type === 'fill') {
      project.activeLayer.addChild(hitResult.item);
    }
  };

  tool.onMouseDrag = function(event) {
    if (selectionRectangleScale !== null) {
      // Path scale adjustment
      var ratio = event.point.subtract(paper.selectRect.bounds.center).length / selectionRectangleScale;
      var scaling = new Point(ratio, ratio);
      paper.selectRect.scaling = scaling;
      paper.selectRect.ppath.scaling = scaling;
      return;
    } else if (selectionRectangleRotation !== null) {
      // Path rotation adjustment
      var rotation = event.point.subtract(paper.selectRect.pivot).angle + 90;
      paper.selectRect.ppath.rotation = rotation;
      paper.selectRect.rotation = rotation;
      return;
    }

    if (segment && !paper.imageTraceMode) {
      // Individual path segment position adjustment
      segment.point.x += event.delta.x;
      segment.point.y += event.delta.y;

      // Smooth -only- non-polygonal paths
      //if (!path.data.isPolygonal) path.smooth();

      initSelectionRectangle(path);
    } else if (path) {
      // Path translate position adjustment
      if (path !== paper.selectRect) {
        path.position.x += event.delta.x;
        path.position.y += event.delta.y;
        paper.selectRect.position.x += event.delta.x;
        paper.selectRect.position.y += event.delta.y;
      } else {
        paper.selectRect.position = paper.selectRect.position.add(event.delta);
        paper.selectRect.ppath.position = paper.selectRect.ppath.position.add(event.delta);
      }
    }
  };

  tool.onMouseMove = function(event) {
    project.activeLayer.selected = false;

    if (paper.selectRect) {
      paper.selectRect.selected = true;
    }

    if (paper.imageTraceMode) {
      return; // No hover events for imageTraceMode
    } else {
      // No hover events for the trace image
      if (paper.traceImage) {
        if (event.item == paper.traceImage) return;
        if (event.item == paper.traceImage.img) return;
      }
    }

    var boundItem = getBoundSelection(event.point);

    if (event.item) {
      event.item.selected = true;
      paper.setCursor('copy');
    } else if (boundItem) {
      boundItem.selected = true;
      paper.setCursor('move');
    } else {
      paper.setCursor();
    }
  };

  tool.onMouseUp = function(event) {
    selectionRectangleScale = null;
    selectionRectangleRotation = null;

    // If we have a mouse up with either of these, the file has changed!
    if (path || segment) {
      paper.cleanPath(path);
      paper.fileChanged();
    }
  };

  tool.onKeyDown = function (event) {
    if (paper.selectRect) {
      // Delete a selected path
      if (event.key === 'delete' || event.key === 'backspace') {
        paper.selectRect.ppath.remove();
        if (paper.imageTraceMode) paper.traceImage = null;
        paper.deselect();
      }

      // Deselect
      if (event.key === 'escape') {
        paper.selectRect.ppath.fullySelected = false;
        paper.deselect();
      }

    }
  };

  paper.selectPath = initSelectionRectangle;
  function initSelectionRectangle(path) {
    if (paper.selectRect !== null) paper.selectRect.remove();
    var reset = path.rotation === 0 && path.scaling.x === 1 && path.scaling.y === 1;
    var bounds;

    if (reset) {
      // Actually reset bounding box
      bounds = path.bounds;
      path.pInitialBounds = path.bounds;
    } else {
      // No bounding box reset
      bounds = path.pInitialBounds;
    }

    var b = bounds.clone().expand(25, 25);

    paper.selectRect = new Path.Rectangle(b);
    paper.selectRect.pivot = paper.selectRect.position;
    paper.selectRect.insert(2, new Point(b.center.x, b.top));
    paper.selectRect.insert(2, new Point(b.center.x, b.top - 25));
    paper.selectRect.insert(2, new Point(b.center.x, b.top));

    if (!reset) {
      paper.selectRect.position = path.bounds.center;
      paper.selectRect.rotation = path.rotation;
      paper.selectRect.scaling = path.scaling;
    }

    paper.selectRect.strokeWidth = 2;
    paper.selectRect.strokeColor = 'blue';
    paper.selectRect.name = "selection rectangle";
    paper.selectRect.selected = true;
    paper.selectRect.ppath = path;
    paper.selectRect.ppath.pivot = paper.selectRect.pivot;
  }

  function getBoundSelection(point) {
    // Check for items that are overlapping a rect around the event point
    var items = project.getItems({
      overlapping: new Rectangle(point.x - 2, point.y - 2,point.x + 2, point.y + 2)
    });

    var item = null;
    _.each(items, function (i) {

      if (paper.traceImage) {
        if (i == paper.traceImage) return; // Don't select the trace image group
        if (i == paper.traceImage.img) return; // Don't select the trace image
      }

      // TODO: Prioritize selection of paths completely inside of other paths
      if (i instanceof Path) {
        if (i.contains(point)) {
          item = i;
        }
      }
    });

    return item;
  }

  // Change the select tool mode to/from image trace mode
  tool.imageTraceMode = function(toggle) {
    paper.imageTraceMode = toggle;

    if (toggle) {
      initSelectionRectangle(paper.traceImage);
      tool.activate();
    } else {
      path = null;
      paper.deselect();
    }
  };

  return tool;
};
<commit_msg>Select tool linting<commit_after>/**
 * @file Tool definition for the PC dual purpose selection tool. Provides event
 * handlers and special logic for the selection tool ONLY. Allows selection of
 * entire objects, rotation, scaling and node/segment adjustment.
 **/
"use strict";
/*globals _ */

module.exports = function(paper) {
  var tool = new paper.Tool();

  // Paper global extenders
  var Path = paper.Path;
  var Point = paper.Point;
  var Rectangle = paper.Rectangle;
  var project = paper.project;

  // Handy internal vars
  paper.selectRect = null;
  var selectionRectangleScale = null;
  var selectionRectangleRotation = null;
  var segment, path;
  paper.imageTraceMode = false;
  var hitOptions = {
    segments: true,
    stroke: true,
    fill: true,
    tolerance: 5
  };

  // Externalize deseletion
  paper.deselect = function() {
    if (paper.selectRect) {
      paper.selectRect.remove();
      paper.selectRect = null;

      // Complete imageTraceMode if we're deselecting.
      if (paper.imageTraceMode) {
        paper.finishImageImport();
      }
    }
  };

  // Tool identification (for building out tool palette)
  tool.name = 'tools.select';
  tool.key = 'select';
  tool.cursorOffset = '1 1'; // Position for cursor point

  tool.onMouseDown = function(event) {
    segment = path = null;

    var hitResult = project.hitTest(event.point, hitOptions);

    // Don't select image if not in trace mode
    if (hitResult && !paper.imageTraceMode) {
      if (paper.traceImage) {
        if (hitResult.item === paper.traceImage ||
            hitResult.item === paper.traceImage.img) {
          hitResult = null; // Act like we didn't hit anything
        }
      }
    }

    // If we didn't hit anything with hitTest...
    if (!hitResult) {
      // Finish imageTraceMode
      if (paper.imageTraceMode) {
        paper.deselect();
        return;
      }

      // Find any items that are Paths (not layers) that contain the point
      var item = getBoundSelection(event.point);

      // If we actually found something, fake a fill hitResult
      if (item) {
        hitResult = {
          type: 'fill', // SURE it is ;)
          item: item
        };
      } else {
        // Deselect if nothing clicked (feels natural for deselection)
        if (paper.selectRect !== null) {
          paper.deselect();
        }

        return;
      }
    }

    if (event.modifiers.shift) {
      if (hitResult.type === 'segment') {
        hitResult.segment.remove();
      }
      return;
    }

    if (hitResult) {
      if (paper.imageTraceMode) {

        // Select the group, not the image
        if (hitResult.item === paper.traceImage.img) {
          hitResult.item = paper.traceImage;
        }

        //console.log('HITRESULT', hitResult.item);

        // Don't select any other items if in image trace mode
        if (hitResult.item !== paper.selectRect &&
            hitResult.item !== paper.traceImage) {
          return;
        }
      }

      path = hitResult.item;

      if (hitResult.type === 'segment') {
        if (paper.selectRect !== null && path.name === "selection rectangle") {
          if (hitResult.segment.index >= 2 && hitResult.segment.index <= 4) {
            // Rotation hitbox
            selectionRectangleRotation = 0;
          } else {
            // Scale hitbox
            var center = event.point.subtract(paper.selectRect.bounds.center);
            selectionRectangleScale = center.length / path.scaling.x;
          }
        } else {
          segment = hitResult.segment;
        }
      } else if (hitResult.type === 'stroke' && path !== paper.selectRect) {
        if (paper.selectRect && paper.selectRect.ppath === path) {
          // Add new segment node to the path (if it's already selected)
          var location = hitResult.location;
          segment = path.insert(location.index + 1, event.point);
        }
      }

      if ((paper.selectRect === null || paper.selectRect.ppath !== path) &&
          paper.selectRect !== path) {
        initSelectionRectangle(path);
      }
    }

    // If a fill hit, move the path
    if (hitResult.type === 'fill') {
      project.activeLayer.addChild(hitResult.item);
    }
  };

  tool.onMouseDrag = function(event) {
    if (selectionRectangleScale !== null) {
      // Path scale adjustment
      var centerDiff = event.point.subtract(paper.selectRect.bounds.center);
      var ratio = centerDiff.length / selectionRectangleScale;
      var scaling = new Point(ratio, ratio);
      paper.selectRect.scaling = scaling;
      paper.selectRect.ppath.scaling = scaling;
      return;
    } else if (selectionRectangleRotation !== null) {
      // Path rotation adjustment
      var rotation = event.point.subtract(paper.selectRect.pivot).angle + 90;
      paper.selectRect.ppath.rotation = rotation;
      paper.selectRect.rotation = rotation;
      return;
    }

    if (segment && !paper.imageTraceMode) {
      // Individual path segment position adjustment
      segment.point.x += event.delta.x;
      segment.point.y += event.delta.y;

      // Smooth -only- non-polygonal paths
      //if (!path.data.isPolygonal) path.smooth();

      initSelectionRectangle(path);
    } else if (path) {
      var psr = paper.selectRect;

      // Path translate position adjustment
      if (path !== paper.selectRect) {
        path.position.x += event.delta.x;
        path.position.y += event.delta.y;
        psr.position.x += event.delta.x;
        psr.position.y += event.delta.y;
      } else {
        psr.position = psr.position.add(event.delta);
        psr.ppath.position = psr.ppath.position.add(event.delta);
      }
    }
  };

  tool.onMouseMove = function(event) {
    project.activeLayer.selected = false;

    if (paper.selectRect) {
      paper.selectRect.selected = true;
    }

    if (paper.imageTraceMode) {
      return; // No hover events for imageTraceMode
    } else {
      // No hover events for the trace image
      if (paper.traceImage) {
        if (event.item === paper.traceImage) return;
        if (event.item === paper.traceImage.img) return;
      }
    }

    var boundItem = getBoundSelection(event.point);

    if (event.item) {
      event.item.selected = true;
      paper.setCursor('copy');
    } else if (boundItem) {
      boundItem.selected = true;
      paper.setCursor('move');
    } else {
      paper.setCursor();
    }
  };

  tool.onMouseUp = function() {
    selectionRectangleScale = null;
    selectionRectangleRotation = null;

    // If we have a mouse up with either of these, the file has changed!
    if (path || segment) {
      paper.cleanPath(path);
      paper.fileChanged();
    }
  };

  tool.onKeyDown = function (event) {
    if (paper.selectRect) {
      // Delete a selected path
      if (event.key === 'delete' || event.key === 'backspace') {
        paper.selectRect.ppath.remove();
        if (paper.imageTraceMode) paper.traceImage = null;
        paper.deselect();
      }

      // Deselect
      if (event.key === 'escape') {
        paper.selectRect.ppath.fullySelected = false;
        paper.deselect();
      }

    }
  };

  paper.selectPath = initSelectionRectangle;
  function initSelectionRectangle(path) {
    if (paper.selectRect !== null) paper.selectRect.remove();
    var reset = path.rotation === 0 && path.scaling.x === 1 && path.scaling.y === 1;
    var bounds;

    if (reset) {
      // Actually reset bounding box
      bounds = path.bounds;
      path.pInitialBounds = path.bounds;
    } else {
      // No bounding box reset
      bounds = path.pInitialBounds;
    }

    var b = bounds.clone().expand(25, 25);

    paper.selectRect = new Path.Rectangle(b);
    paper.selectRect.pivot = paper.selectRect.position;
    paper.selectRect.insert(2, new Point(b.center.x, b.top));
    paper.selectRect.insert(2, new Point(b.center.x, b.top - 25));
    paper.selectRect.insert(2, new Point(b.center.x, b.top));

    if (!reset) {
      paper.selectRect.position = path.bounds.center;
      paper.selectRect.rotation = path.rotation;
      paper.selectRect.scaling = path.scaling;
    }

    paper.selectRect.strokeWidth = 2;
    paper.selectRect.strokeColor = 'blue';
    paper.selectRect.name = "selection rectangle";
    paper.selectRect.selected = true;
    paper.selectRect.ppath = path;
    paper.selectRect.ppath.pivot = paper.selectRect.pivot;
  }

  function getBoundSelection(point) {
    // Check for items that are overlapping a rect around the event point
    var items = project.getItems({
      overlapping: new Rectangle(
        point.x - 2,
        point.y - 2,
        point.x + 2,
        point.y + 2
      )
    });

    var item = null;
    _.each(items, function (i) {

      if (paper.traceImage) {
        if (i === paper.traceImage) return; // Don't select the trace img group
        if (i === paper.traceImage.img) return; // Don't select the trace image
      }

      // TODO: Prioritize selection of paths completely inside of other paths
      if (i instanceof Path) {
        if (i.contains(point)) {
          item = i;
        }
      }
    });

    return item;
  }

  // Change the select tool mode to/from image trace mode
  tool.imageTraceMode = function(toggle) {
    paper.imageTraceMode = toggle;

    if (toggle) {
      initSelectionRectangle(paper.traceImage);
      tool.activate();
    } else {
      path = null;
      paper.deselect();
    }
  };

  return tool;
};
<|endoftext|>


<commit_before>/*
 * EJS Embedded JavaScript templates
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var fs = require('fs')
  , utils = require('./utils')
  , templateCache = {}
  , jsCache = {}
  , optInDataWarned = false
  , scopeOptionWarned = false
  , _DEFAULT_DELIMITER = '%'
  , _REGEX_STRING = '(<%%)|(<%=)|(<%-)|(<%#)|(<%)|(%>)|(-%>)'
  , _OPTS = [ 'cache', 'filename', 'delimiter', 'scope', 'context'
            , 'debug', 'compileDebug', 'client'
            ]

function resolveInclude(name, filename) {
  var path = require('path')
    , dirname = path.dirname
    , extname = path.extname
    , resolve = path.resolve
    , includePath = resolve(dirname(filename), name)
    , ext = extname(name);
  if (!ext) {
    includePath += '.ejs';
  }
  return includePath;
}

function includeFile(path, options) {
  var fn
    , opts = utils.shallowCopy({}, options || /* istanbul ignore next */ {})
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  fn = exports.compile(template, opts);
  return fn;
}

function includeSource(path, options) {
  var opts = utils.shallowCopy({}, options || {})
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  var templ = new Template(template, opts);
  templ.generateSource();
  return templ.source;
}

function rethrow(err, str, filename, lineno){
  var lines = str.split('\n')
    , start = Math.max(lineno - 3, 0)
    , end = Math.min(lines.length, lineno + 3);

  // Error context
  var context = lines.slice(start, end).map(function (line, i){
    var curr = i + start + 1;
    return (curr == lineno ? ' >> ' : '    ')
      + curr
      + '| '
      + line;
  }).join('\n');

  // Alter exception message
  err.path = filename;
  err.message = (filename || 'ejs') + ':'
    + lineno + '\n'
    + context + '\n\n'
    + err.message;

  throw err;
}

function cpOptsInData(data, opts) {
  _OPTS.forEach(function (p) {
    if (typeof data[p] != 'undefined') {
      if (!optInDataWarned) {
        console.warn('options found in locals object. The option(s) is '
                   + 'copied to the option object. This behavior is '
                   + 'deprecated and will be removed in EJS 3');
        optInDataWarned = true;
      }
      opts[p] = data[p];
    }
  });
}

function compile(template, opts) {
  var templ;

  // v1 compat
  // 'scope' is 'context'
  // FIXME: Remove this in a future version
  if (opts && opts.scope) {
    if (!scopeOptionWarned){
      console.warn('`scope` option is deprecated and will be removed in EJS 3');
      scopeOptionWarned = true;
    }
    if (!opts.context) {
      opts.context = opts.scope;
    }
    delete opts.scope;
  }
  templ = new Template(template, opts);
  return templ.compile();
}
exports.compile = compile;

// template, [data], [opts]
// Have to include an empty data object if you want opts and no data
exports.render = function (template, data, opts) {
  data = data || {};
  opts = opts || {};
  var fn
    , filename;

  // No options object -- if there are optiony names
  // in the data, copy them to options
  if (arguments.length == 2) {
    cpOptsInData(data, opts);
  }

  if (opts.cache) {
    filename = opts.filename;
    if (!filename) {
      throw new Error('cache option requires a filename');
    }
    fn = jsCache[filename];
    if (!fn) {
      fn = exports.compile(template, opts);
      jsCache[filename] = fn;
    }
  }
  else {
    fn = exports.compile(template, opts);
  }
  return fn.call(opts.context, data);
};

// path, [data] [opts], cb
// Have to include an empty data object if you want opts and no data
exports.renderFile = function () {
  var args = Array.prototype.slice.call(arguments)
    , path = args.shift()
    , cb = args.pop()
    , data = args.shift() || {}
    , opts = args.pop() || {}
    , template;

  // No options object -- if there are optiony names
  // in the data, copy them to options
  if (arguments.length == 3) {
    cpOptsInData(data, opts);
  }

  // Set the filename for includes
  opts.filename = path;

  function handleTemplate(template) {
    var result
      , failed = false;
    try {
      result = exports.render(template, data, opts);
    }
    catch(err) {
      cb(err);
      failed = true;
    }
    if (!failed) {
      cb(null, result);
    }
  }

  template = templateCache[path];
  if (opts.cache && template) {
    handleTemplate(template);
  }
  else {
    fs.readFile(path, function (err, data) {
      var tmpl;
      if (err) {
        return cb(err);
      }
      tmpl = data.toString().trim();
      if (opts.cache) {
        templateCache[path] = tmpl;
      }
      handleTemplate(tmpl);
    });
  }
};

exports.clearCache = function () {
  templateCache = {};
  jsCache = {};
};

function Template(text, opts) {
  opts = opts || {};
  var options = {};
  this.templateText = text;
  this.mode = null;
  this.truncate = false;
  this.currentLine = 1;
  this.source = '';
  options.client = opts.client || false;
  options.escapeFunction = opts.escape || utils.escapeXML;
  options.compileDebug = opts.compileDebug !== false;
  options.debug = !!opts.debug;
  options.filename = opts.filename;
  options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;
  options._with = typeof opts._with != 'undefined' ? opts._with : true;
  this.opts = options;

  this.regex = this.createRegex();
}

Template.prototype = new function () {
  this.modes = {
      EVAL: 'eval'
    , ESCAPED: 'escaped'
    , RAW: 'raw'
    , APPEND: 'append'
    , COMMENT: 'comment'
    , LITERAL: 'literal'
  };

  this.createRegex = function () {
    var str = _REGEX_STRING
      , delim = utils.escapeRegExpChars(this.opts.delimiter);
    str = str.replace(/%/g, delim);
    return new RegExp(str);
  };

  this.compile = function () {
    var src
      , fn
      , opts = this.opts
      , escape = opts.escapeFunction;

    if (!this.source) {
      this.generateSource();
      var appended = 'var __output = "";';
      if (opts._with !== false) {
        appended +=  ' with (locals || {}) { ';
      }
      this.source  = appended + this.source;
      if (opts._with !== false) {
        this.source += '}';
      }
      this.source += ';return __output.trim();';
    }

    if (opts.compileDebug) {
      src = 'var __line = 1' +
          ', __lines = ' + JSON.stringify(this.templateText) +
          ', __filename = ' + (opts.filename ?
                JSON.stringify(opts.filename) : 'undefined') +
          '; try {' +
          this.source + '} catch (e) { rethrow(e, __lines, __filename, __line); }';
    }
    else {
      src = this.source;
    }

    if (opts.debug) {
      console.log(src);
    }

    if (opts.client) {
      src = 'escape = escape || ' + escape.toString() + ';\n' + src;
      src = 'rethrow = rethrow || ' + rethrow.toString() + ';\n' + src;
    }

    try {
      fn = new Function('locals, escape, include, rethrow', src);
    }
    catch(e) {
      if (e instanceof SyntaxError) {
        if (opts.filename) {
          e.message += ' in ' + opts.filename;
        }
        e.message += ' while compiling ejs';
        throw e;
      }
    }

    if (opts.client) {
      return fn;
    }

    // Return a callable function which will execute the function
    // created by the source-code, with the passed data as locals
    return function (data) {
      var include = function (path, includeData) {
        var d = utils.shallowCopy({}, data);
        if (includeData) {
          d = utils.shallowCopy(d, includeData);
        }
        return includeFile(path, opts)(d);
      };
      return fn(data || {}, escape, include, rethrow);
    };

  };

  this.generateSource = function () {
    var self = this
      , matches = this.parseTemplateText()
      , d = this.opts.delimiter;

    if (matches && matches.length) {
      matches.forEach(function (line, index) {
        var closing
          , include
          , includeOpts
          , includeSrc;
        // If this is an opening tag, check for closing tags
        // FIXME: May end up with some false positives here
        // Better to store modes as k/v with '<' + delimiter as key
        // Then this can simply check against the map
        if ( line.indexOf('<' + d) === 0        // If it is a tag
          && line.indexOf('<' + d + d) !== 0) { // and is not escaped
          closing = matches[index + 2];
          if (!(closing == d + '>' || closing == '-' + d + '>')) {
            throw new Error('Could not find matching close tag for "' + line + '".');
          }
        }
        // HACK: backward-compat `include` preprocessor directives
        if ((include = line.match(/^\s*include\s+(\S+)/))) {
          includeOpts = utils.shallowCopy({}, self.opts);
          includeSrc = includeSource(include[1], includeOpts);
          includeSrc = ';(function(){' + includeSrc + '})();';
          self.source += includeSrc;
        }
        else {
          self.scanLine(line);
        }
      });
    }

  };

  this.parseTemplateText = function () {
    var str = this.templateText
      , pat = this.regex
      , result = pat.exec(str)
      , arr = []
      , firstPos
      , lastPos;

    while (result) {
      firstPos = result.index;
      lastPos = pat.lastIndex;

      if (firstPos !== 0) {
        arr.push(str.substring(0, firstPos));
        str = str.slice(firstPos);
      }

      arr.push(result[0]);
      str = str.slice(result[0].length);
      result = pat.exec(str);
    }

    if (str) {
      arr.push(str);
    }

    return arr;
  };

  this.scanLine = function (line) {
    var self = this
      , d = this.opts.delimiter
      , newLineCount = 0;

    function _addOutput() {
      if (self.truncate) {
        line = line.replace('\n', '');
      }

      // Preserve literal slashes
      line = line.replace(/\\/g, '\\\\');

      // Convert linebreaks
      line = line.replace(/\n/g, '\\n');
      line = line.replace(/\r/g, '\\r');

      // Escape double-quotes
      // - this will be the delimiter during execution
      line = line.replace(/"/g, '\\"');
      self.source += ';__output += "' + line + '";';
    }

    newLineCount = (line.split('\n').length - 1);

    switch (line) {
      case '<' + d:
        this.mode = this.modes.EVAL;
        break;
      case '<' + d + '=':
        this.mode = this.modes.ESCAPED;
        break;
      case '<' + d + '-':
        this.mode = this.modes.RAW;
        break;
      case '<' + d + '#':
        this.mode = this.modes.COMMENT;
        break;
      case '<' + d + d:
        this.mode = this.modes.LITERAL;
        this.source += ';__output += "' + line.replace('<' + d + d, '<' + d) + '";';
        break;
      case d + '>':
      case '-' + d + '>':
        if (this.mode == this.modes.LITERAL) {
          _addOutput();
        }

        this.mode = null;
        this.truncate = line.indexOf('-') === 0;
        break;
      default:
        // In script mode, depends on type of tag
        if (this.mode) {
          // If '//' is found without a line break, add a line break.
          switch (this.mode) {
            case this.modes.EVAL:
            case this.modes.ESCAPED:
            case this.modes.RAW:
              if (line.lastIndexOf('//') > line.lastIndexOf('\n')) {
                line += '\n';
              }
          }
          switch (this.mode) {
            // Just executing code
            case this.modes.EVAL:
              this.source += ';' + line;
              break;
            // Exec, esc, and output
            case this.modes.ESCAPED:
              // Add the exec'd, escaped result to the output
              this.source += ';__output += escape(' +
                  line.replace(/;\S*/, '').trim() + ')';
              break;
            // Exec and output
            case this.modes.RAW:
              // Add the exec'd result to the output
              this.source += ';__output += ' + line.trim();
              break;
            case this.modes.COMMENT:
              // Do nothing
              break;
            // Literal <%% mode, append as raw output
            case this.modes.LITERAL:
              _addOutput();
              break;
          }
        }
        // In string mode, just add the output
        else {
          _addOutput();
        }
    }

    if (self.opts.compileDebug && newLineCount) {
      this.currentLine += newLineCount;
      this.source += ';__line = ' + this.currentLine + ';';
    }
  };
};

// Express support
exports.__express = exports.renderFile;

// Add require support
/* istanbul ignore else */
if (require.extensions) {
  require.extensions['.ejs'] = function (module, filename) {
    filename = filename || /* istanbul ignore next */ module.filename;
    var options = {
          filename: filename
        , client: true
        }
      , template = fs.readFileSync(filename).toString().trim()
      , fn = compile(template, options);
    module._compile('module.exports = ' + fn.toString() + ';', filename);
  };
}

exports.VERSION = '2.1.4';

/* istanbul ignore if */
if (typeof window != 'undefined') {
  window.ejs = exports;
}
<commit_msg>Pass cache option to templates<commit_after>/*
 * EJS Embedded JavaScript templates
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var fs = require('fs')
  , utils = require('./utils')
  , templateCache = {}
  , jsCache = {}
  , optInDataWarned = false
  , scopeOptionWarned = false
  , _DEFAULT_DELIMITER = '%'
  , _REGEX_STRING = '(<%%)|(<%=)|(<%-)|(<%#)|(<%)|(%>)|(-%>)'
  , _OPTS = [ 'cache', 'filename', 'delimiter', 'scope', 'context'
            , 'debug', 'compileDebug', 'client'
            ]

function resolveInclude(name, filename) {
  var path = require('path')
    , dirname = path.dirname
    , extname = path.extname
    , resolve = path.resolve
    , includePath = resolve(dirname(filename), name)
    , ext = extname(name);
  if (!ext) {
    includePath += '.ejs';
  }
  return includePath;
}

function includeFile(path, options) {
  var fn
    , opts = utils.shallowCopy({}, options || /* istanbul ignore next */ {})
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  fn = exports.compile(template, opts);
  return fn;
}

function includeSource(path, options) {
  var opts = utils.shallowCopy({}, options || {})
    , includePath
    , template;
  if (!opts.filename) {
    throw new Error('`include` requires the \'filename\' option.');
  }
  includePath = resolveInclude(path, opts.filename);
  if (opts.cache) {
    template = templateCache[includePath];
    if (!template) {
      template = fs.readFileSync(includePath).toString().trim();
      templateCache[includePath] = template;
    }
  }
  else {
    template = fs.readFileSync(includePath).toString().trim();
  }

  opts.filename = includePath;
  var templ = new Template(template, opts);
  templ.generateSource();
  return templ.source;
}

function rethrow(err, str, filename, lineno){
  var lines = str.split('\n')
    , start = Math.max(lineno - 3, 0)
    , end = Math.min(lines.length, lineno + 3);

  // Error context
  var context = lines.slice(start, end).map(function (line, i){
    var curr = i + start + 1;
    return (curr == lineno ? ' >> ' : '    ')
      + curr
      + '| '
      + line;
  }).join('\n');

  // Alter exception message
  err.path = filename;
  err.message = (filename || 'ejs') + ':'
    + lineno + '\n'
    + context + '\n\n'
    + err.message;

  throw err;
}

function cpOptsInData(data, opts) {
  _OPTS.forEach(function (p) {
    if (typeof data[p] != 'undefined') {
      if (!optInDataWarned) {
        console.warn('options found in locals object. The option(s) is '
                   + 'copied to the option object. This behavior is '
                   + 'deprecated and will be removed in EJS 3');
        optInDataWarned = true;
      }
      opts[p] = data[p];
    }
  });
}

function compile(template, opts) {
  var templ;

  // v1 compat
  // 'scope' is 'context'
  // FIXME: Remove this in a future version
  if (opts && opts.scope) {
    if (!scopeOptionWarned){
      console.warn('`scope` option is deprecated and will be removed in EJS 3');
      scopeOptionWarned = true;
    }
    if (!opts.context) {
      opts.context = opts.scope;
    }
    delete opts.scope;
  }
  templ = new Template(template, opts);
  return templ.compile();
}
exports.compile = compile;

// template, [data], [opts]
// Have to include an empty data object if you want opts and no data
exports.render = function (template, data, opts) {
  data = data || {};
  opts = opts || {};
  var fn
    , filename;

  // No options object -- if there are optiony names
  // in the data, copy them to options
  if (arguments.length == 2) {
    cpOptsInData(data, opts);
  }

  if (opts.cache) {
    filename = opts.filename;
    if (!filename) {
      throw new Error('cache option requires a filename');
    }
    fn = jsCache[filename];
    if (!fn) {
      fn = exports.compile(template, opts);
      jsCache[filename] = fn;
    }
  }
  else {
    fn = exports.compile(template, opts);
  }
  return fn.call(opts.context, data);
};

// path, [data] [opts], cb
// Have to include an empty data object if you want opts and no data
exports.renderFile = function () {
  var args = Array.prototype.slice.call(arguments)
    , path = args.shift()
    , cb = args.pop()
    , data = args.shift() || {}
    , opts = args.pop() || {}
    , template;

  // No options object -- if there are optiony names
  // in the data, copy them to options
  if (arguments.length == 3) {
    cpOptsInData(data, opts);
  }

  // Set the filename for includes
  opts.filename = path;

  function handleTemplate(template) {
    var result
      , failed = false;
    try {
      result = exports.render(template, data, opts);
    }
    catch(err) {
      cb(err);
      failed = true;
    }
    if (!failed) {
      cb(null, result);
    }
  }

  template = templateCache[path];
  if (opts.cache && template) {
    handleTemplate(template);
  }
  else {
    fs.readFile(path, function (err, data) {
      var tmpl;
      if (err) {
        return cb(err);
      }
      tmpl = data.toString().trim();
      if (opts.cache) {
        templateCache[path] = tmpl;
      }
      handleTemplate(tmpl);
    });
  }
};

exports.clearCache = function () {
  templateCache = {};
  jsCache = {};
};

function Template(text, opts) {
  opts = opts || {};
  var options = {};
  this.templateText = text;
  this.mode = null;
  this.truncate = false;
  this.currentLine = 1;
  this.source = '';
  options.client = opts.client || false;
  options.escapeFunction = opts.escape || utils.escapeXML;
  options.compileDebug = opts.compileDebug !== false;
  options.debug = !!opts.debug;
  options.filename = opts.filename;
  options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;
  options._with = typeof opts._with != 'undefined' ? opts._with : true;
  options.cache = opts.cache || false;
  this.opts = options;

  this.regex = this.createRegex();
}

Template.prototype = new function () {
  this.modes = {
      EVAL: 'eval'
    , ESCAPED: 'escaped'
    , RAW: 'raw'
    , APPEND: 'append'
    , COMMENT: 'comment'
    , LITERAL: 'literal'
  };

  this.createRegex = function () {
    var str = _REGEX_STRING
      , delim = utils.escapeRegExpChars(this.opts.delimiter);
    str = str.replace(/%/g, delim);
    return new RegExp(str);
  };

  this.compile = function () {
    var src
      , fn
      , opts = this.opts
      , escape = opts.escapeFunction;

    if (!this.source) {
      this.generateSource();
      var appended = 'var __output = "";';
      if (opts._with !== false) {
        appended +=  ' with (locals || {}) { ';
      }
      this.source  = appended + this.source;
      if (opts._with !== false) {
        this.source += '}';
      }
      this.source += ';return __output.trim();';
    }

    if (opts.compileDebug) {
      src = 'var __line = 1' +
          ', __lines = ' + JSON.stringify(this.templateText) +
          ', __filename = ' + (opts.filename ?
                JSON.stringify(opts.filename) : 'undefined') +
          '; try {' +
          this.source + '} catch (e) { rethrow(e, __lines, __filename, __line); }';
    }
    else {
      src = this.source;
    }

    if (opts.debug) {
      console.log(src);
    }

    if (opts.client) {
      src = 'escape = escape || ' + escape.toString() + ';\n' + src;
      src = 'rethrow = rethrow || ' + rethrow.toString() + ';\n' + src;
    }

    try {
      fn = new Function('locals, escape, include, rethrow', src);
    }
    catch(e) {
      if (e instanceof SyntaxError) {
        if (opts.filename) {
          e.message += ' in ' + opts.filename;
        }
        e.message += ' while compiling ejs';
        throw e;
      }
    }

    if (opts.client) {
      return fn;
    }

    // Return a callable function which will execute the function
    // created by the source-code, with the passed data as locals
    return function (data) {
      var include = function (path, includeData) {
        var d = utils.shallowCopy({}, data);
        if (includeData) {
          d = utils.shallowCopy(d, includeData);
        }
        return includeFile(path, opts)(d);
      };
      return fn(data || {}, escape, include, rethrow);
    };

  };

  this.generateSource = function () {
    var self = this
      , matches = this.parseTemplateText()
      , d = this.opts.delimiter;

    if (matches && matches.length) {
      matches.forEach(function (line, index) {
        var closing
          , include
          , includeOpts
          , includeSrc;
        // If this is an opening tag, check for closing tags
        // FIXME: May end up with some false positives here
        // Better to store modes as k/v with '<' + delimiter as key
        // Then this can simply check against the map
        if ( line.indexOf('<' + d) === 0        // If it is a tag
          && line.indexOf('<' + d + d) !== 0) { // and is not escaped
          closing = matches[index + 2];
          if (!(closing == d + '>' || closing == '-' + d + '>')) {
            throw new Error('Could not find matching close tag for "' + line + '".');
          }
        }
        // HACK: backward-compat `include` preprocessor directives
        if ((include = line.match(/^\s*include\s+(\S+)/))) {
          includeOpts = utils.shallowCopy({}, self.opts);
          includeSrc = includeSource(include[1], includeOpts);
          includeSrc = ';(function(){' + includeSrc + '})();';
          self.source += includeSrc;
        }
        else {
          self.scanLine(line);
        }
      });
    }

  };

  this.parseTemplateText = function () {
    var str = this.templateText
      , pat = this.regex
      , result = pat.exec(str)
      , arr = []
      , firstPos
      , lastPos;

    while (result) {
      firstPos = result.index;
      lastPos = pat.lastIndex;

      if (firstPos !== 0) {
        arr.push(str.substring(0, firstPos));
        str = str.slice(firstPos);
      }

      arr.push(result[0]);
      str = str.slice(result[0].length);
      result = pat.exec(str);
    }

    if (str) {
      arr.push(str);
    }

    return arr;
  };

  this.scanLine = function (line) {
    var self = this
      , d = this.opts.delimiter
      , newLineCount = 0;

    function _addOutput() {
      if (self.truncate) {
        line = line.replace('\n', '');
      }

      // Preserve literal slashes
      line = line.replace(/\\/g, '\\\\');

      // Convert linebreaks
      line = line.replace(/\n/g, '\\n');
      line = line.replace(/\r/g, '\\r');

      // Escape double-quotes
      // - this will be the delimiter during execution
      line = line.replace(/"/g, '\\"');
      self.source += ';__output += "' + line + '";';
    }

    newLineCount = (line.split('\n').length - 1);

    switch (line) {
      case '<' + d:
        this.mode = this.modes.EVAL;
        break;
      case '<' + d + '=':
        this.mode = this.modes.ESCAPED;
        break;
      case '<' + d + '-':
        this.mode = this.modes.RAW;
        break;
      case '<' + d + '#':
        this.mode = this.modes.COMMENT;
        break;
      case '<' + d + d:
        this.mode = this.modes.LITERAL;
        this.source += ';__output += "' + line.replace('<' + d + d, '<' + d) + '";';
        break;
      case d + '>':
      case '-' + d + '>':
        if (this.mode == this.modes.LITERAL) {
          _addOutput();
        }

        this.mode = null;
        this.truncate = line.indexOf('-') === 0;
        break;
      default:
        // In script mode, depends on type of tag
        if (this.mode) {
          // If '//' is found without a line break, add a line break.
          switch (this.mode) {
            case this.modes.EVAL:
            case this.modes.ESCAPED:
            case this.modes.RAW:
              if (line.lastIndexOf('//') > line.lastIndexOf('\n')) {
                line += '\n';
              }
          }
          switch (this.mode) {
            // Just executing code
            case this.modes.EVAL:
              this.source += ';' + line;
              break;
            // Exec, esc, and output
            case this.modes.ESCAPED:
              // Add the exec'd, escaped result to the output
              this.source += ';__output += escape(' +
                  line.replace(/;\S*/, '').trim() + ')';
              break;
            // Exec and output
            case this.modes.RAW:
              // Add the exec'd result to the output
              this.source += ';__output += ' + line.trim();
              break;
            case this.modes.COMMENT:
              // Do nothing
              break;
            // Literal <%% mode, append as raw output
            case this.modes.LITERAL:
              _addOutput();
              break;
          }
        }
        // In string mode, just add the output
        else {
          _addOutput();
        }
    }

    if (self.opts.compileDebug && newLineCount) {
      this.currentLine += newLineCount;
      this.source += ';__line = ' + this.currentLine + ';';
    }
  };
};

// Express support
exports.__express = exports.renderFile;

// Add require support
/* istanbul ignore else */
if (require.extensions) {
  require.extensions['.ejs'] = function (module, filename) {
    filename = filename || /* istanbul ignore next */ module.filename;
    var options = {
          filename: filename
        , client: true
        }
      , template = fs.readFileSync(filename).toString().trim()
      , fn = compile(template, options);
    module._compile('module.exports = ' + fn.toString() + ';', filename);
  };
}

exports.VERSION = '2.1.4';

/* istanbul ignore if */
if (typeof window != 'undefined') {
  window.ejs = exports;
}
<|endoftext|>


<commit_before>var Sequelize = require('sequelize'),
    Model = require('../model/models.js');

var attributes = {
  username: {
    type: Sequelize.STRING,
    allowNull: false,
    unique: true,
    validate: {
      is: /^[a-z0-9\_\-]+$/i,
    }
  },
  email: {
    type: Sequelize.STRING,
    validate: {
      isEmail: true
    }
  },
  firstName: {
    type: Sequelize.STRING,
  },
  lastName: {
    type: Sequelize.STRING,
  },
  password: {
    type: Sequelize.STRING,
  },
  salt: {
    type: Sequelize.STRING,
  },
  resetPasswordToken: {
    type: Sequelize.STRING,
  },
  resetPasswordExpires: {
    type: Sequelize.DATE,
  },
  bio: {
    type: Sequelize.TEXT,
  },
  phone: {
    type: Sequelize.INTEGER,
  },
  propertyRenting: {
    type: Sequelize.STRING,
  },
  propertyManager: {
    type: Sequelize.STRING,
  },
  billingInfo: {
    type: Sequelize.TEXT,
  },
  property: {
    type: Sequelize.INTEGER,
    primaryKey: true,
  },
  userType: {
    type: Sequelize.STRING
  }
};

var options = {
  freezeTableName: true
};

module.exports.attributes = attributes;
module.exports.options = options;<commit_msg>fixing tenant table<commit_after>var Sequelize = require('sequelize'),
    Model = require('../model/models.js');

var attributes = {
  username: {
    type: Sequelize.STRING,
    allowNull: false,
    unique: true,
    validate: {
      is: /^[a-z0-9\_\-]+$/i,
    }
  },
  email: {
    type: Sequelize.STRING,
    validate: {
      isEmail: true
    }
  },
  firstName: {
    type: Sequelize.STRING,
  },
  lastName: {
    type: Sequelize.STRING,
  },
  password: {
    type: Sequelize.STRING,
  },
  salt: {
    type: Sequelize.STRING,
  },
  resetPasswordToken: {
    type: Sequelize.STRING,
  },
  resetPasswordExpires: {
    type: Sequelize.DATE,
  },
  bio: {
    type: Sequelize.TEXT,
  },
  phone: {
    type: Sequelize.INTEGER,
  },
  propertyRenting: {
    type: Sequelize.STRING,
  },
  propertyManager: {
    type: Sequelize.STRING,
  },
  billingInfo: {
    type: Sequelize.TEXT,
  },
  property: {
    type: Sequelize.INTEGER,
  },
  userType: {
    type: Sequelize.STRING
  }
};

var options = {
  freezeTableName: true
};

module.exports.attributes = attributes;
module.exports.options = options;<|endoftext|>


<commit_before>var os = require('os'),
  path = require('path'),
  unzip = require('unzip'),
  colors = require('colors'),
  fs = require('fs'),
  request = require('request'),
  prompt = require('prompt'),
  Q = require('q');

colors.setTheme({
  silly: 'rainbow',
  input: 'grey',
  small: 'grey',
  verbose: 'cyan',
  prompt: 'grey',
  info: 'white',
  data: 'grey',
  help: 'cyan',
  warn: 'yellow',
  debug: 'blue',
  error: 'red'
});

var Fay = {
  run: function () {
    var that = this;
    prompt.message = "Question!";
    prompt.delimiter = "".green;

    prompt.start();

    prompt.get({
      properties: {
        mobile: {
          description: "Do you need mobile app? y/N: "
        },
        editor: {
          description: "Do you need desktop editor source code? y/N: "
        }
      }
    }, function (err, result) {
      var withMobileApp = result.mobile === "y" || result.mobile === "yes";
      var withEditor = result.editor === "y" || result.editor === "yes";

      that.fetchRepo('fay', 'deploy', 'https://github.com/phodal-archive/echeveria-deploy/archive/master.zip');
      that.fetchRepo('fay', 'content', 'https://github.com/phodal-archive/echeveria-content/archive/master.zip');

      if (withMobileApp) {
        console.log("fetch mobile .. ");
        that.fetchRepo('fay', 'mobile', 'https://github.com/phodal-archive/echeveria-mobile/archive/master.zip');
      }
      if (withEditor) {
        console.log("fetch editor .. ");
        that.fetchRepo('fay', 'editor', 'https://github.com/phodal/echeveria-editor/archive/master.zip');
      }
    });
  },

  /**
   * Fetch a repo from GitHub, unzip it to a specific folder.
   *
   * The MIT License (MIT)
   *
   * Copyright (c) 2013 Drifty
   * https://github.com/driftyco/ionic-cli/blob/ce33bcc26336538d86f16b2fcd400dfbce5c73a7/lib/ionic/templates.js
   */
  fetchRepo: function (targetPath, repoName, repoUrl) {
    var q = Q.defer();

    var proxy = process.env.PROXY || null;

    // The folder name the project will be downloaded and extracted to
    console.log('\nDOWNLOADING:'.info.bold, repoUrl);

    var tmpFolder = os.tmpdir();
    var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip');
    var tempZipFileStream = fs.createWriteStream(tempZipFilePath);

    var unzipRepo = function (fileName) {
      var readStream = fs.createReadStream(fileName);

      var writeStream = unzip.Extract({path: targetPath});
      writeStream.on('close', function () {
        q.resolve(repoName);
      });
      readStream.pipe(writeStream);
    };

    request({url: repoUrl, encoding: null, proxy: proxy}, function (err, res, body) {
      if (res.statusCode !== 200) {
        q.reject(res);
        return;
      }
      tempZipFileStream.write(body);
      tempZipFileStream.close();
      unzipRepo(tempZipFilePath);
    });

    return q.promise;
  }
};

exports.Fay = Fay;
<commit_msg>update unzip<commit_after>var os = require('os'),
  path = require('path'),
  unzip = require('unzip'),
  colors = require('colors'),
  fs = require('fs'),
  request = require('request'),
  prompt = require('prompt'),
  Q = require('q');

colors.setTheme({
  silly: 'rainbow',
  input: 'grey',
  small: 'grey',
  verbose: 'cyan',
  prompt: 'grey',
  info: 'white',
  data: 'grey',
  help: 'cyan',
  warn: 'yellow',
  debug: 'blue',
  error: 'red'
});

var Fay = {
  run: function () {
    var that = this;
    prompt.message = "Question!";
    prompt.delimiter = "".green;

    prompt.start();

    prompt.get({
      properties: {
        mobile: {
          description: "Do you need mobile app? y/N: "
        },
        editor: {
          description: "Do you need desktop editor source code? y/N: "
        }
      }
    }, function (err, result) {
      var withMobileApp = result.mobile === "y" || result.mobile === "yes";
      var withEditor = result.editor === "y" || result.editor === "yes";

      that.fetchRepo('fay', 'deploy', 'https://github.com/phodal-archive/echeveria-deploy/archive/master.zip');
      that.fetchRepo('fay', 'content', 'https://github.com/phodal-archive/echeveria-content/archive/master.zip');

      if (withMobileApp) {
        console.log("fetch mobile .. ");
        that.fetchRepo('fay', 'mobile', 'https://github.com/phodal-archive/echeveria-mobile/archive/master.zip');
      }
      if (withEditor) {
        console.log("fetch editor .. ");
        that.fetchRepo('fay', 'editor', 'https://github.com/phodal/echeveria-editor/archive/master.zip');
      }
    });
  },

  /**
   * Fetch a repo from GitHub, unzip it to a specific folder.
   *
   * The MIT License (MIT)
   *
   * Copyright (c) 2013 Drifty
   * https://github.com/driftyco/ionic-cli/blob/8103bc2e751ef7ce02c1aaa0fa9e624df8f1909d/lib/ionic.js
   */
  fetchRepo: function (targetPath, repoName, repoUrl) {
    var q = Q.defer();

    var proxy = process.env.PROXY || null;

    // The folder name the project will be downloaded and extracted to
    console.log('\nDOWNLOADING:'.info.bold, repoUrl);

    var tmpFolder = os.tmpdir();
    var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip');
    var tempZipFileStream = fs.createWriteStream(tempZipFilePath);

    var unzipRepo = function (fileName) {
      var readStream = fs.createReadStream(fileName);
      readStream.on('error', function (err) {
        console.log(('unzipRepo readStream: ' + err).error);
        q.reject(err);
      });

      var writeStream = unzip.Extract({path: targetPath});
      writeStream.on('close', function () {
        q.resolve();
      });
      writeStream.on('error', function (err) {
        console.log(('unzipRepo writeStream: ' + err).error);
        q.reject(err);
      });
      readStream.pipe(writeStream);
    };

    request({url: repoUrl, encoding: null, proxy: proxy}, function (err, res, body) {
      if (res.statusCode !== 200) {
        q.reject(res);
        return;
      }
      tempZipFileStream.write(body);
      tempZipFileStream.close();
      unzipRepo(tempZipFilePath);
    });

    return q.promise;
  }
};

exports.Fay = Fay;
<|endoftext|>


<commit_before>/**
 * @fileoverview
 * This file contains most of the code implementing the console view in
 * Dragonfly
 */

window.cls || (window.cls = {});
cls.ConsoleLogger || (cls.ConsoleLogger = {});
cls.ConsoleLogger["2.0"] || (cls.ConsoleLogger["2.0"] = {});

/**
 * Data class for console logger
 * @constructor
 */
cls.ConsoleLogger["2.0"].ErrorConsoleData = function()
{
  this._msgs = [];
  this._toggled = [];
  this._dragonfly_msgs = [];
  this._views = [];
  this._selected_rt_url = '';
  this._url_self = location.host + location.pathname;
  this._lastid = 0;

  this._updateviews = function()
  {
    var view = '', i = 0;
    for( ; view = this._views[i]; i++)
    {
      window.views[view].update();
    }
  };

  this.addview = function(view_id)
  {
    this._views.push(view_id);
  };

  /**
   * Adds a log entry to the data model.
   */
  this.addentry = function(entry)
  {
    if( !entry.uri || entry.uri.indexOf(this._url_self) == -1 )
    {
      this._msgs.push(entry);
    }
    else
    {
      this._dragonfly_msgs.push(entry);
    }

    window.messages.post('console-message', entry);
    this._updateviews();
  };

  /**
   * Clear the log. If source is set, clear only the entries with that source
   */
  this.clear = function(source)
  {
    if( source ) {
      var fun = function(e) {return e.source!=source;};
      this._msgs = this._msgs.filter(fun);
    }
    else {
      this._msgs = [];
      this._toggled = [];
    }
    this._updateviews();
  };

  /**
   * Toggle an entry. This is context sensitive.
   * Whatever is in the list behaves opposite of the default. In other words,
   * when items are expanded by default, items in the toggled list are not
   * expanded and vice-versa.
   */
  this.toggle_entry = function(logid)
  {
    if (this._toggled.indexOf(logid) == -1) {
      this._toggled.push(logid);
    }
    else {
      this._toggled.splice(this._toggled.indexOf(logid), 1);
    }
  };

  /**
   * Return all the messages. If souce is set, return only messages for
   * that source.
   */
  this._get_msgs_without_filter = function(source)
  {
    if( source ) {
        var fun = function(e) {return e.source==source;};
        return this._msgs.filter(fun);
    }
    return this._msgs;
  };

  /**
   * Return all the messages whose uri is the same as __selected_rt_url.
   * If souce is set, return only messages for that source.
   */
  this._get_msgs_with_filter = function(source)
  {
    var fun = function(e) { return e.uri == this._selected_rt_url &&
                            (!source || e.source==source);
    };
  return this._msgs.filter(fun);
  };

  this.get_messages = function(source, filter)
  {
    return filter || settings.console.get('use-selected-runtime-as-filter')
      ? this._get_msgs_with_filter(source, filter)
      : this._get_msgs_without_filter(source);
  };

  this.get_message = function(id)
  {
    if (! this._msgs)
    {
      return null;
    }
    else
    {
      var fun = function(e) {
        return e.id == id;
      };
      return this._msgs.filter(fun)[0] || null;
    }
  };

  this.clear_dragonfly_messages = function()
  {
    this._dragonfly_msgs = [];
    this._updateviews();
  };

  this.get_dragonfly_messages = function()
  {
    return this._dragonfly_msgs;
  };

  this.get_toggled = function()
  {
    return this._toggled;
  };

  this._on_setting_change = function(msg)
  {
    if( msg.id == 'console' )
    {
      switch(msg.key)
      {
        case 'expand-all-entries': {
          toggled = [];
          this._updateviews();
          break;
        }
        case 'use-selected-runtime-as-filter': {
          this._updateviews();
          break;
        }
        default: { // these settings are names of tabs to show.
          var is_disabled = !settings[msg.id].get(msg.key);
          views[msg.key].ishidden_in_menu = is_disabled;
          topCell.disableTab(msg.key, is_disabled);
        }
      }
    }
  };

  this._extract_title = function(description)
  {
    var parts = description.split("\n");
    if (parts.length)
    {
      return parts[0] == "Error:" ? parts[1].substr(6) : parts[0];
    }
    return "";
  };

  this._extract_line = function(description)
  {
    var matcher = /[lL]ine (\d*)/;
    var linematch = matcher.exec(description);
    return linematch ? linematch[1] : null;
  };

  this._on_console_message = function(message)
  {
    /*
     const
     WINDOW_ID = 0,
     TIME = 1,
     DESCRIPTION = 2,
     URI = 3,
     CONTEXT = 4,
     SOURCE = 5,
     SEVERITY = 6;
     */
    this.addentry({
      id: "" + (++this._lastid),
      window_id: message[0],
      time: new Date(parseInt(message[1])),
      description: message[2],
      title: this._extract_title(message[2]),
      line: this._extract_line(message[2]),
      uri: message[3],
      context: message[4],
      source: message[5],
      severity: message[6]
    });

  };

  this._on_runtime_selecetd = function(msg)
  {
    var rt = window.runtimes.getRuntime(msg.id);
    this._selected_rt_url = rt && rt.uri || '';
  };

  this.init = function()
  {
    window.messages.addListener('setting-changed', this._on_setting_change.bind(this));
    window.messages.addListener('runtime-selected', this._on_runtime_selecetd.bind(this));
    var service = window.services['console-logger'];
    service.add_listener("consolemessage", this._on_console_message.bind(this));
  };

  this.init();
};

/**
 * Error Console view
 * @constructor
 * @extends ViewBase
 */

var ErrorConsoleView = function(id, name, container_class, source)
{
  container_class = container_class ? container_class : 'scroll error-console';
  name = name ? name : 'missing name ' + id;

  var _expand_all_state = null;
  var _table_ele = null;

  this.createView = function(container)
  {
    // Switch on whether we have a table element allready. If we do, just
    // render the latest log entry
    var entries = window.error_console_data.get_messages(source);
    topCell.statusbar.updateInfo(ui_strings.S_CONSOLE_TOOLBAR_MESSAGES_COUNT.replace("%s", entries.length));
    var expand_all = settings.console.get('expand-all-entries');

    // If there is no table, it's empty or expand state changed, render all
    if (! _table_ele || ! entries.length || expand_all != _expand_all_state)
    {
      // The expand all state thingy is to make sure we handle switching
      // between expand all/collapse all properly.
      _expand_all_state = expand_all;
      this.renderFull(container, entries, expand_all);
    }
    // but if not, check if there are new entries to show and just
    // update the list with them
    else if (_table_ele.childNodes.length-1 < entries.length)
    {
      this.renderUpdate(entries.slice(-1), expand_all);
    }
  };

  this.renderFull = function(container, messages, expand_all)
  {
    container.clearAndRender(templates.error_log_table(messages,
                                                       expand_all,
                                                       window.error_console_data.get_toggled(),
                                                       this.id)
                             );
    _table_ele = container.getElementsByTagName("table")[0];
    //container.scrollTop = container.scrollHeight;
  };

  this.renderUpdate = function(entries, expandAll)
  {
    for (var n=0, cur; cur=entries[n]; n++)
    {
      _table_ele.render(templates.error_log_row(cur, expandAll, window.error_console_data.get_toggled(), this.id));
    }
  };

  this.ondestroy = function() {
    delete _table_ele;
    _table_ele = null;
  };

  this.init(id, name, container_class );
};
ErrorConsoleView.prototype = ViewBase;

ErrorConsoleView.roughViews =
[
  {
    id: 'console-all',
    name: ui_strings.M_VIEW_LABEL_ERROR_ALL
  },
  {
    id: 'console-script',
    name: ui_strings.M_VIEW_LABEL_ERROR_SCRIPT,
    source: 'ecmascript'
  },
  {
    id: 'console-css',
    name: ui_strings.M_VIEW_LABEL_ERROR_CSS,
    source: 'css'
  },
  {
    id: 'console-java',
    name: ui_strings.M_VIEW_LABEL_ERROR_JAVA,
    source: 'java'
  },
  {
    id: 'console-m2',
    name: ui_strings.M_VIEW_LABEL_ERROR_M2,
    source: 'm2'
  },
  {
    id: 'console-network',
    name: ui_strings.M_VIEW_LABEL_ERROR_NETWORK,
    source: 'network'
  },
  {
    id: 'console-xml',
    name: ui_strings.M_VIEW_LABEL_ERROR_XML,
    source: 'xml'
  },
  {
    id: 'console-html',
    name: ui_strings.M_VIEW_LABEL_ERROR_HTML,
    source: 'html'
  },
  {
    id: 'console-xslt',
    name: ui_strings.M_VIEW_LABEL_ERROR_XSLT,
    source: 'xslt'
  },
  {
    id: 'console-svg',
    name: ui_strings.M_VIEW_LABEL_ERROR_SVG,
    source: 'svg'
  },
  {
    id: 'console-bittorrent',
    name: ui_strings.M_VIEW_LABEL_ERROR_BITTORRENT,
    source: 'bittorrent'
  },
  {
    id: 'console-voice',
    name: ui_strings.M_VIEW_LABEL_ERROR_VOICE,
    source: 'ecmascript'
  },
  {
    id: 'console-widget',
    name: ui_strings.M_VIEW_LABEL_ERROR_WIDGET,
    source: 'widget'
  }
];

ErrorConsoleView.roughViews.bindClearSource = function(source)
{
  return function(event, target)
  {
    window.error_console_data.clear(source);
  };
};

ErrorConsoleView.roughViews.createViews = function()
{
  var r_v = null, i = 0, handler_id = '';
  for( ; r_v = this[i]; i++)
  {
    new ErrorConsoleView(r_v.id, r_v.name, r_v.container_class, r_v.source);
    window.error_console_data.addview(r_v.id);
    handler_id = 'clear-error-console' + ( r_v.source ? '-' + r_v.source : '' );
    new ToolbarConfig
    (
      r_v.id,
      [
        {
          handler: handler_id,
          title: ui_strings.S_BUTTON_LABEL_CLEAR_LOG,
          class_name: 'clear-log'
        }
      ],
      [
        {
          handler: 'console-text-search-' + r_v.id,
          title: ui_strings.S_INPUT_DEFAULT_TEXT_SEARCH
        }
    ]

    );
    new Switches
    (
      r_v.id,
      [
        'console.expand-all-entries'
        //'console.use-selected-runtime-as-filter' // Not in use
      ]
    );
    eventHandlers.click[handler_id] = this.bindClearSource( r_v.source ? r_v.source : '' );

    /* create the handler code for the text search box
       We make a function here so we close around the view id */
    (function() {
      var textSearch = new TextSearch();

      var view_id = r_v.id;
      var onViewCreated = function(msg)
      {
        if( msg.id == view_id )
        {
          textSearch.setContainer(msg.container);
          textSearch.setFormInput(views.console.getToolbarControl( msg.container, 'console-text-search-' + view_id));
        }
      };

      var onViewDestroyed = function(msg)
      {
        if( msg.id == view_id )
        {
          textSearch.cleanup();
        }
      };

      messages.addListener('view-created', onViewCreated);
      messages.addListener('view-destroyed', onViewDestroyed);

      eventHandlers.input['console-text-search-'+ view_id] = function(event, target)
      {
        textSearch.searchDelayed(target.value);
      };

      eventHandlers.keypress['console-text-search-'+ view_id] = function(event, target)
      {
        if( event.keyCode == 13 )
        {
          textSearch.highlight();
        }
      };
    })();

  }
};

eventHandlers.click['error-log-list-expand-collapse'] = function(event, target)
{
  var logid = target.getAttribute("data-logid");
  window.error_console_data.toggle_entry(logid);
  if (target.hasClass("expanded"))
  {
    target.parentNode.removeChild(target.nextSibling);
    target.swapClass("expanded", "collapsed");
  }
  else
  {
    var entry = window.error_console_data.get_message(logid);
    var row = document.render(templates.error_log_detail_row(entry));
    target.parentNode.insertAfter(row, target);
    target.swapClass("collapsed", "expanded");
    row.scrollSoftIntoContainerView();
  }
};

/**
  * @constructor
  * @extends ViewBase
  * General view to get general console setting.
  */
cls.ConsoleLogger["2.0"].ConsoleView = function(id, name, container_class)
{
  this.ishidden_in_menu = true;
  this.createView = function(container){};
  this.init(id, name, container_class);
};

cls.ConsoleLogger["2.0"].ConsoleView.create_ui_widgets = function()
{

  new Settings
  (
    // id
    'console',
    // key-value map
    {
      'console-all': true,
      'console-script': true,
      'console-css': true,
      'console-xml': false,
      'console-java': false,
      'console-m2': false,
      'console-network': false,
      'console-html': false,
      'console-xslt': false,
      'console-svg': false,
      'console-bittorrent': false,
      'console-voice': false,
      'console-widget': false,
      'use-selected-runtime-as-filter': false,
      'expand-all-entries': false
    },
    // key-label map
    {
      'console-all': ui_strings.S_SWITCH_SHOW_TAB_ALL,
      'console-script': ui_strings.S_SWITCH_SHOW_TAB_SCRIPT,
      'console-css': ui_strings.S_SWITCH_SHOW_TAB_CSS,
      'console-xml': ui_strings.S_SWITCH_SHOW_TAB_XML,
      'console-java': ui_strings.S_SWITCH_SHOW_TAB_JAVA,
      'console-m2': ui_strings.S_SWITCH_SHOW_TAB_M2,
      'console-network': ui_strings.S_SWITCH_SHOW_TAB_NETWORK,
      'console-html': ui_strings.S_SWITCH_SHOW_TAB_HTML,
      'console-xslt': ui_strings.S_SWITCH_SHOW_TAB_XSLT,
      'console-svg': ui_strings.S_SWITCH_SHOW_TAB_SVG,
      'console-bittorrent': ui_strings.S_SWITCH_SHOW_TAB_BITTORRENT,
      'console-voice': ui_strings.S_SWITCH_SHOW_TAB_VOICE,
      'console-widget': ui_strings.S_SWITCH_SHOW_TAB_WIDGET,
      'use-selected-runtime-as-filter': ' use selected runtime as filter', // Not in use!
      'expand-all-entries': ui_strings.S_SWITCH_EXPAND_ALL
  },
    // settings map
    {
      checkboxes:
      [
        'console-all',
        'console-script',
        'console-css',
        'console-xml',
        'console-java',
        'console-m2',
        'console-network',
        'console-html',
        'console-xslt',
        'console-svg',
        'console-bittorrent',
        'console-voice',
        'console-widget'
      ]
    }
  );
};
<commit_msg>Removed deprecated dragonfly messages stuff<commit_after>/**
 * @fileoverview
 * This file contains most of the code implementing the console view in
 * Dragonfly
 */

window.cls || (window.cls = {});
cls.ConsoleLogger || (cls.ConsoleLogger = {});
cls.ConsoleLogger["2.0"] || (cls.ConsoleLogger["2.0"] = {});

/**
 * Data class for console logger
 * @constructor
 */
cls.ConsoleLogger["2.0"].ErrorConsoleData = function()
{
  this._msgs = [];
  this._toggled = [];
  this._views = [];
  this._selected_rt_url = '';
  this._url_self = location.host + location.pathname;
  this._lastid = 0;

  this._updateviews = function()
  {
    var view = '', i = 0;
    for( ; view = this._views[i]; i++)
    {
      window.views[view].update();
    }
  };

  this.addview = function(view_id)
  {
    this._views.push(view_id);
  };

  /**
   * Adds a log entry to the data model.
   */
  this.addentry = function(entry)
  {
    if( !entry.uri || entry.uri.indexOf(this._url_self) == -1 )
    {
      this._msgs.push(entry);
    }

    window.messages.post('console-message', entry);
    this._updateviews();
  };

  /**
   * Clear the log. If source is set, clear only the entries with that source
   */
  this.clear = function(source)
  {
    if( source ) {
      var fun = function(e) {return e.source!=source;};
      this._msgs = this._msgs.filter(fun);
    }
    else {
      this._msgs = [];
      this._toggled = [];
    }
    this._updateviews();
  };

  /**
   * Toggle an entry. This is context sensitive.
   * Whatever is in the list behaves opposite of the default. In other words,
   * when items are expanded by default, items in the toggled list are not
   * expanded and vice-versa.
   */
  this.toggle_entry = function(logid)
  {
    if (this._toggled.indexOf(logid) == -1) {
      this._toggled.push(logid);
    }
    else {
      this._toggled.splice(this._toggled.indexOf(logid), 1);
    }
  };

  /**
   * Return all the messages. If souce is set, return only messages for
   * that source.
   */
  this._get_msgs_without_filter = function(source)
  {
    if( source ) {
        var fun = function(e) {return e.source==source;};
        return this._msgs.filter(fun);
    }
    return this._msgs;
  };

  /**
   * Return all the messages whose uri is the same as __selected_rt_url.
   * If souce is set, return only messages for that source.
   */
  this._get_msgs_with_filter = function(source)
  {
    var fun = function(e) { return e.uri == this._selected_rt_url &&
                            (!source || e.source==source);
    };
  return this._msgs.filter(fun);
  };

  this.get_messages = function(source, filter)
  {
    return filter || settings.console.get('use-selected-runtime-as-filter')
      ? this._get_msgs_with_filter(source, filter)
      : this._get_msgs_without_filter(source);
  };

  this.get_message = function(id)
  {
    if (! this._msgs)
    {
      return null;
    }
    else
    {
      var fun = function(e) {
        return e.id == id;
      };
      return this._msgs.filter(fun)[0] || null;
    }
  };

  this.get_toggled = function()
  {
    return this._toggled;
  };

  this._on_setting_change = function(msg)
  {
    if( msg.id == 'console' )
    {
      switch(msg.key)
      {
        case 'expand-all-entries': {
          toggled = [];
          this._updateviews();
          break;
        }
        case 'use-selected-runtime-as-filter': {
          this._updateviews();
          break;
        }
        default: { // these settings are names of tabs to show.
          var is_disabled = !settings[msg.id].get(msg.key);
          views[msg.key].ishidden_in_menu = is_disabled;
          topCell.disableTab(msg.key, is_disabled);
        }
      }
    }
  };

  this._extract_title = function(description)
  {
    var parts = description.split("\n");
    if (parts.length)
    {
      return parts[0] == "Error:" ? parts[1].substr(6) : parts[0];
    }
    return "";
  };

  this._extract_line = function(description)
  {
    var matcher = /[lL]ine (\d*)/;
    var linematch = matcher.exec(description);
    return linematch ? linematch[1] : null;
  };

  this._on_console_message = function(message)
  {
    /*
     const
     WINDOW_ID = 0,
     TIME = 1,
     DESCRIPTION = 2,
     URI = 3,
     CONTEXT = 4,
     SOURCE = 5,
     SEVERITY = 6;
     */
    this.addentry({
      id: "" + (++this._lastid),
      window_id: message[0],
      time: new Date(parseInt(message[1])),
      description: message[2],
      title: this._extract_title(message[2]),
      line: this._extract_line(message[2]),
      uri: message[3],
      context: message[4],
      source: message[5],
      severity: message[6]
    });

  };

  this._on_runtime_selecetd = function(msg)
  {
    var rt = window.runtimes.getRuntime(msg.id);
    this._selected_rt_url = rt && rt.uri || '';
  };

  this.init = function()
  {
    window.messages.addListener('setting-changed', this._on_setting_change.bind(this));
    window.messages.addListener('runtime-selected', this._on_runtime_selecetd.bind(this));
    var service = window.services['console-logger'];
    service.add_listener("consolemessage", this._on_console_message.bind(this));
  };

  this.init();
};

/**
 * Error Console view
 * @constructor
 * @extends ViewBase
 */

var ErrorConsoleView = function(id, name, container_class, source)
{
  container_class = container_class ? container_class : 'scroll error-console';
  name = name ? name : 'missing name ' + id;

  var _expand_all_state = null;
  var _table_ele = null;

  this.createView = function(container)
  {
    // Switch on whether we have a table element allready. If we do, just
    // render the latest log entry
    var entries = window.error_console_data.get_messages(source);
    topCell.statusbar.updateInfo(ui_strings.S_CONSOLE_TOOLBAR_MESSAGES_COUNT.replace("%s", entries.length));
    var expand_all = settings.console.get('expand-all-entries');

    // If there is no table, it's empty or expand state changed, render all
    if (! _table_ele || ! entries.length || expand_all != _expand_all_state)
    {
      // The expand all state thingy is to make sure we handle switching
      // between expand all/collapse all properly.
      _expand_all_state = expand_all;
      this.renderFull(container, entries, expand_all);
    }
    // but if not, check if there are new entries to show and just
    // update the list with them
    else if (_table_ele.childNodes.length-1 < entries.length)
    {
      this.renderUpdate(entries.slice(-1), expand_all);
    }
  };

  this.renderFull = function(container, messages, expand_all)
  {
    container.clearAndRender(templates.error_log_table(messages,
                                                       expand_all,
                                                       window.error_console_data.get_toggled(),
                                                       this.id)
                             );
    _table_ele = container.getElementsByTagName("table")[0];
    //container.scrollTop = container.scrollHeight;
  };

  this.renderUpdate = function(entries, expandAll)
  {
    for (var n=0, cur; cur=entries[n]; n++)
    {
      _table_ele.render(templates.error_log_row(cur, expandAll, window.error_console_data.get_toggled(), this.id));
    }
  };

  this.ondestroy = function() {
    delete _table_ele;
    _table_ele = null;
  };

  this.init(id, name, container_class );
};
ErrorConsoleView.prototype = ViewBase;

ErrorConsoleView.roughViews =
[
  {
    id: 'console-all',
    name: ui_strings.M_VIEW_LABEL_ERROR_ALL
  },
  {
    id: 'console-script',
    name: ui_strings.M_VIEW_LABEL_ERROR_SCRIPT,
    source: 'ecmascript'
  },
  {
    id: 'console-css',
    name: ui_strings.M_VIEW_LABEL_ERROR_CSS,
    source: 'css'
  },
  {
    id: 'console-java',
    name: ui_strings.M_VIEW_LABEL_ERROR_JAVA,
    source: 'java'
  },
  {
    id: 'console-m2',
    name: ui_strings.M_VIEW_LABEL_ERROR_M2,
    source: 'm2'
  },
  {
    id: 'console-network',
    name: ui_strings.M_VIEW_LABEL_ERROR_NETWORK,
    source: 'network'
  },
  {
    id: 'console-xml',
    name: ui_strings.M_VIEW_LABEL_ERROR_XML,
    source: 'xml'
  },
  {
    id: 'console-html',
    name: ui_strings.M_VIEW_LABEL_ERROR_HTML,
    source: 'html'
  },
  {
    id: 'console-xslt',
    name: ui_strings.M_VIEW_LABEL_ERROR_XSLT,
    source: 'xslt'
  },
  {
    id: 'console-svg',
    name: ui_strings.M_VIEW_LABEL_ERROR_SVG,
    source: 'svg'
  },
  {
    id: 'console-bittorrent',
    name: ui_strings.M_VIEW_LABEL_ERROR_BITTORRENT,
    source: 'bittorrent'
  },
  {
    id: 'console-voice',
    name: ui_strings.M_VIEW_LABEL_ERROR_VOICE,
    source: 'ecmascript'
  },
  {
    id: 'console-widget',
    name: ui_strings.M_VIEW_LABEL_ERROR_WIDGET,
    source: 'widget'
  }
];

ErrorConsoleView.roughViews.bindClearSource = function(source)
{
  return function(event, target)
  {
    window.error_console_data.clear(source);
  };
};

ErrorConsoleView.roughViews.createViews = function()
{
  var r_v = null, i = 0, handler_id = '';
  for( ; r_v = this[i]; i++)
  {
    new ErrorConsoleView(r_v.id, r_v.name, r_v.container_class, r_v.source);
    window.error_console_data.addview(r_v.id);
    handler_id = 'clear-error-console' + ( r_v.source ? '-' + r_v.source : '' );
    new ToolbarConfig
    (
      r_v.id,
      [
        {
          handler: handler_id,
          title: ui_strings.S_BUTTON_LABEL_CLEAR_LOG,
          class_name: 'clear-log'
        }
      ],
      [
        {
          handler: 'console-text-search-' + r_v.id,
          title: ui_strings.S_INPUT_DEFAULT_TEXT_SEARCH
        }
    ]

    );
    new Switches
    (
      r_v.id,
      [
        'console.expand-all-entries'
        //'console.use-selected-runtime-as-filter' // Not in use
      ]
    );
    eventHandlers.click[handler_id] = this.bindClearSource( r_v.source ? r_v.source : '' );

    /* create the handler code for the text search box
       We make a function here so we close around the view id */
    (function() {
      var textSearch = new TextSearch();

      var view_id = r_v.id;
      var onViewCreated = function(msg)
      {
        if( msg.id == view_id )
        {
          textSearch.setContainer(msg.container);
          textSearch.setFormInput(views.console.getToolbarControl( msg.container, 'console-text-search-' + view_id));
        }
      };

      var onViewDestroyed = function(msg)
      {
        if( msg.id == view_id )
        {
          textSearch.cleanup();
        }
      };

      messages.addListener('view-created', onViewCreated);
      messages.addListener('view-destroyed', onViewDestroyed);

      eventHandlers.input['console-text-search-'+ view_id] = function(event, target)
      {
        textSearch.searchDelayed(target.value);
      };

      eventHandlers.keypress['console-text-search-'+ view_id] = function(event, target)
      {
        if( event.keyCode == 13 )
        {
          textSearch.highlight();
        }
      };
    })();

  }
};

eventHandlers.click['error-log-list-expand-collapse'] = function(event, target)
{
  var logid = target.getAttribute("data-logid");
  window.error_console_data.toggle_entry(logid);
  if (target.hasClass("expanded"))
  {
    target.parentNode.removeChild(target.nextSibling);
    target.swapClass("expanded", "collapsed");
  }
  else
  {
    var entry = window.error_console_data.get_message(logid);
    var row = document.render(templates.error_log_detail_row(entry));
    target.parentNode.insertAfter(row, target);
    target.swapClass("collapsed", "expanded");
    row.scrollSoftIntoContainerView();
  }
};

/**
  * @constructor
  * @extends ViewBase
  * General view to get general console setting.
  */
cls.ConsoleLogger["2.0"].ConsoleView = function(id, name, container_class)
{
  this.ishidden_in_menu = true;
  this.createView = function(container){};
  this.init(id, name, container_class);
};

cls.ConsoleLogger["2.0"].ConsoleView.create_ui_widgets = function()
{

  new Settings
  (
    // id
    'console',
    // key-value map
    {
      'console-all': true,
      'console-script': true,
      'console-css': true,
      'console-xml': false,
      'console-java': false,
      'console-m2': false,
      'console-network': false,
      'console-html': false,
      'console-xslt': false,
      'console-svg': false,
      'console-bittorrent': false,
      'console-voice': false,
      'console-widget': false,
      'use-selected-runtime-as-filter': false,
      'expand-all-entries': false
    },
    // key-label map
    {
      'console-all': ui_strings.S_SWITCH_SHOW_TAB_ALL,
      'console-script': ui_strings.S_SWITCH_SHOW_TAB_SCRIPT,
      'console-css': ui_strings.S_SWITCH_SHOW_TAB_CSS,
      'console-xml': ui_strings.S_SWITCH_SHOW_TAB_XML,
      'console-java': ui_strings.S_SWITCH_SHOW_TAB_JAVA,
      'console-m2': ui_strings.S_SWITCH_SHOW_TAB_M2,
      'console-network': ui_strings.S_SWITCH_SHOW_TAB_NETWORK,
      'console-html': ui_strings.S_SWITCH_SHOW_TAB_HTML,
      'console-xslt': ui_strings.S_SWITCH_SHOW_TAB_XSLT,
      'console-svg': ui_strings.S_SWITCH_SHOW_TAB_SVG,
      'console-bittorrent': ui_strings.S_SWITCH_SHOW_TAB_BITTORRENT,
      'console-voice': ui_strings.S_SWITCH_SHOW_TAB_VOICE,
      'console-widget': ui_strings.S_SWITCH_SHOW_TAB_WIDGET,
      'use-selected-runtime-as-filter': ' use selected runtime as filter', // Not in use!
      'expand-all-entries': ui_strings.S_SWITCH_EXPAND_ALL
  },
    // settings map
    {
      checkboxes:
      [
        'console-all',
        'console-script',
        'console-css',
        'console-xml',
        'console-java',
        'console-m2',
        'console-network',
        'console-html',
        'console-xslt',
        'console-svg',
        'console-bittorrent',
        'console-voice',
        'console-widget'
      ]
    }
  );
};
<|endoftext|>


<commit_before>(function(define){

define(function() {
"use strict";

/* Forward declarations
 ******************************************************************************/
var gen;

/* Helper functions
 ******************************************************************************/
var identity = function(v) { return v; };

var constant = function(v) { return identity.bind(undefined, v); };

var noop = constant(function(){});

/* Built-In Simple Generators
 ******************************************************************************/
/**
 * Factory for generator that yields a single value.
 */
var single = function(func) {
    var hasRun;
    return gen(function(y, b) {
        if (hasRun) return b();
        hasRun = true;
        return y(func());
    });
};

/* Built-In Higher Order Generators
 ******************************************************************************/
/**
 * Factory for generator that greedily iterates over a source generator.
 *
 * Returned generator does not return a value.
 *
 * @param {gen} source Source generator being iterated over.
 * @param {function(value, index)} callback Function called for each element of
 *     source.
 *
 * @return {function(yield, break)} Generator function that performs
 *    the forEach operation when invoked.
 */
var forEach = function(source, callback, t) {
    return single(function() {
        var i = 0;
        source(function(v) {
            callback.call(t, v, i++);
        }, noop);
    });
};

/**
 * Factory for a generator that reduces a source generator left to right.
 *
 * Returned generator yields a single value.
 *
 * @param {gen} source Source generator to reduce.
 * @param {function(previous, current, index)} callback Function that reduces
 *     the source.
 * @param initial The initial value used for reduce.
 *
 * @return {function(yield, break)} Generator function that reduces the
 *     source generator when invoked.
 */
var reduce = function(source, callback, initial) {
    return single(function() {
        var p = initial;
        forEach(source, function(v, i) {
            p = callback(p, v, i);
        })(noop, noop);
        return p;
    });
};

/**
 * Factory for generator that transforms values from a source generator.
 *
 * @param {gen} source Source generator being transformed.
 * @param {function(value)} callback Function that transforms source values and
 *     returns the transformed value.
 * @param [thisObj] 'this' object used for callback.
 *
 * @return {function(yield, break)} Transformed generator that yields transformed
 *     values when invoked.
 */
var map = function(source, callback, thisObj) {
    var innerY = function(v) {
        return constant(callback.call(thisObj, v));
    };
    return gen(function(y, b) {
        return y(source(innerY, b));
    });
};

/**
 * Factory for generators that filter a source generator.
 *
 * Returned generator only yields values from the source generator that meet the
 * given condition.
 *
 * @param {gen} source Source generator being filtered.
 * @param {function(value): boolean} predicate Predicate function used to filter
 *     source generator results.
 * @param [thisObj] 'this' object used for predicate.
 *
 * @return {function(yield, break)} Generator that yields filtered source
 *     generator values.
 */
var filter = function(source, predicate, thisObj) {
    var innerY = function(v) {
        if (predicate.call(thisObj, v))
            return constant(v);
    };
    return gen(function(y, b) {
        return y(source(innerY, b));
    });
};

/**
 * Factory for generators that greedily transform a source generator into an array.
 *
 * Returned generator yields a single value, an array of all source generator
 * values.
 *
 * @param {gen} source Source generator
 *
 * @return {function(yield, break)} Generator that yields all source generator
 *     values as an array when invoked.
 */
var toArray = (function(){
    function arrayReduce(p, c) {
        p.push(c);
        return p;
    }
    return function(source) {
        return reduce(source, arrayReduce, []);
    };
}());

/* Exported Objects
 ******************************************************************************/
/**
 * Exception thrown by default when a generator function breaks.
 */
var GenBreak = function(){};
GenBreak.prototype = new Error();
GenBreak.prototype.name = "GenBreak";

/**
 * Properties exported on gen instances.
 *
 * Because we cannot cleanly define a prototype of a function object using
 * standard code, any properties for gen instances must be set using properties.
 * Unlike prototype, adding or changing properties only effects instances created
 * after the property is set.
 */
var properties = {
    'map': {
        'value': function(c, t) { return map(this, c, t ); },
        'writable': true
    },
    'filter': {
        'value': function(p, t) { return filter(this, p, t); },
        'writable': true
    },
    'reduce': {
        'value': function(c, i) { return reduce(this, c, i); },
        'writable': true
    },
    'toArray': {
        'value': function() { return toArray(this); },
        'writable': true
    },
    'forEach': {
        'value': function(c, t) { return forEach(this, c, t); },
        'writable': true
    }
};

/**
 * Factory for gen style generators.
 *
 * Adds flow control logic to generator and default values for yield and break
 * continuations.
 *
 * @param {function(yield, break)} source A generator function that produces
 *     values for this generator.
 *
 * @return {function(yield, break)} A gen style generator function that yields
 *    values from the source generator.
 */
gen = (function(){
    var defaultY = constant;
    var defaultB = constant(function() { throw new GenBreak(); });

    var syncNext = function(source, y, b) {
        var continuation;
        do
        {
            continuation = source(y, b);
        } while (continuation === undefined);
        return continuation();
    };

    var asyncNext = function(source, y, b) {
        var continuation;
        setTimeout(function getNext(){
            continuation = source(y, b);
            if (continuation === undefined) {
                setTimeout(getNext, 0);
            } else {
                continuation();
            }
        }, 0);
    };

    return function(source) {
        var syncGenerator = function(y, b) {
            return syncNext(source, y || defaultY, b || defaultB);
        };
        Object.defineProperties(syncGenerator, properties);
        syncGenerator.async = constant(function(y, b) {
            return asyncNext(source, y || defaultY, b || defaultB);
        });
        return syncGenerator;
    };
}());

/* Export
 ******************************************************************************/
return Object.defineProperties(gen, {
    'properties': {
        'value': properties
    },
    'GenBreak': GenBreak,
    'single': {
        'value': single,
        'writable': true
    },
    'map': {
        'value': function(s, c, t) { return map(gen(s), c, t); },
        'writable': true
    },
    'filter': {
        'value': function(s, p, t) { return filter(gen(s), p, t); },
        'writable': true
    },
    'reduce': {
        'value': function(s, c, i) { return reduce(gen(s), c, i); },
        'writable': true
     },
    'toArray': {
        'value': function(s) { return toArray(gen(s)); },
        'writable': true
    },
    'forEach': {
        'value': function(s, c, t) { return forEach(gen(s), c, t); },
        'writable': true
    }
});

});

}(
    typeof define !== 'undefined' ? define : function(factory) { gen = factory(); }
));<commit_msg>Updated documentation<commit_after>(function(define){

define(function() {
"use strict";

/* Forward declarations
 ******************************************************************************/
var gen;

/* Helper functions
 ******************************************************************************/
var identity = function(v) { return v; };

var constant = function(v) { return identity.bind(undefined, v); };

var noop = constant(function(){});

/* Built-In Simple Generators
 ******************************************************************************/
/**
 * Factory for generator that yields a single value.
 *
 * Returned generator yields a single value.
 *
 * @param {function} func Function that returns single value to yield.
 *
 * @return {function(yield, break)} Generator function that performs
 *    the forEach operation when invoked.
 */
var single = function(func) {
    var hasRun;
    return gen(function(y, b) {
        if (hasRun) return b();
        hasRun = true;
        return y(func());
    });
};

/* Built-In Higher Order Generators
 ******************************************************************************/
/**
 * Factory for generator that greedily iterates over a source generator.
 *
 * Returned generator does not return a value.
 *
 * @param {gen} source Source generator being iterated over.
 * @param {function(value, index)} callback Function called for each element of
 *     source.
 *
 * @return {function(yield, break)} Generator function that performs
 *    the forEach operation when invoked.
 */
var forEach = function(source, callback, t) {
    return single(function() {
        var i = 0;
        source(function(v) {
            callback.call(t, v, i++);
        }, noop);
    });
};

/**
 * Factory for a generator that reduces a source generator left to right.
 *
 * Returned generator yields a single value.
 *
 * @param {gen} source Source generator to reduce.
 * @param {function(previous, current, index)} callback Function that reduces
 *     the source.
 * @param initial The initial value used for reduce.
 *
 * @return {function(yield, break)} Generator function that reduces the
 *     source generator when invoked.
 */
var reduce = function(source, callback, initial) {
    return single(function() {
        var p = initial;
        forEach(source, function(v, i) {
            p = callback(p, v, i);
        })(noop, noop);
        return p;
    });
};

/**
 * Factory for generator that transforms values from a source generator.
 *
 * @param {gen} source Source generator being transformed.
 * @param {function(value)} callback Function that transforms source values and
 *     returns the transformed value.
 * @param [thisObj] 'this' object used for callback.
 *
 * @return {function(yield, break)} Transformed generator that yields transformed
 *     values when invoked.
 */
var map = function(source, callback, thisObj) {
    var innerY = function(v) {
        return constant(callback.call(thisObj, v));
    };
    return gen(function(y, b) {
        return y(source(innerY, b));
    });
};

/**
 * Factory for generators that filter a source generator.
 *
 * Returned generator only yields values from the source generator that meet the
 * given condition.
 *
 * @param {gen} source Source generator being filtered.
 * @param {function(value): boolean} predicate Predicate function used to filter
 *     source generator results.
 * @param [thisObj] 'this' object used for predicate.
 *
 * @return {function(yield, break)} Generator that yields filtered source
 *     generator values.
 */
var filter = function(source, predicate, thisObj) {
    var innerY = function(v) {
        if (predicate.call(thisObj, v))
            return constant(v);
    };
    return gen(function(y, b) {
        return y(source(innerY, b));
    });
};

/**
 * Factory for generators that greedily transform a source generator into an array.
 *
 * Returned generator yields a single value, an array of all source generator
 * values.
 *
 * @param {gen} source Source generator
 *
 * @return {function(yield, break)} Generator that yields all source generator
 *     values as an array when invoked.
 */
var toArray = (function(){
    function arrayReduce(p, c) {
        p.push(c);
        return p;
    }
    return function(source) {
        return reduce(source, arrayReduce, []);
    };
}());

/* Exported Objects
 ******************************************************************************/
/**
 * Exception thrown by default when a generator function breaks.
 */
var GenBreak = function(){};
GenBreak.prototype = new Error();
GenBreak.prototype.name = "GenBreak";

/**
 * Properties exported on gen instances.
 *
 * Because we cannot cleanly define a prototype of a function object using
 * standard code, any properties for gen instances must be set using properties.
 * Unlike prototype, adding or changing properties only effects instances created
 * after the property is set.
 */
var properties = {
    'map': {
        'value': function(c, t) { return map(this, c, t ); },
        'writable': true
    },
    'filter': {
        'value': function(p, t) { return filter(this, p, t); },
        'writable': true
    },
    'reduce': {
        'value': function(c, i) { return reduce(this, c, i); },
        'writable': true
    },
    'toArray': {
        'value': function() { return toArray(this); },
        'writable': true
    },
    'forEach': {
        'value': function(c, t) { return forEach(this, c, t); },
        'writable': true
    }
};

/**
 * Factory for gen style generators.
 *
 * Adds flow control logic to generator and default values for yield and break
 * continuations.
 *
 * @param {function(yield, break)} source A generator function that produces
 *     values for this generator.
 *
 * @return {function(yield, break)} A gen style generator function that yields
 *    values from the source generator.
 */
gen = (function(){
    var defaultY = constant;
    var defaultB = constant(function() { throw new GenBreak(); });

    var syncNext = function(source, y, b) {
        var continuation;
        do
        {
            continuation = source(y, b);
        } while (continuation === undefined);
        return continuation();
    };

    var asyncNext = function(source, y, b) {
        var continuation;
        setTimeout(function getNext(){
            continuation = source(y, b);
            if (continuation === undefined) {
                setTimeout(getNext, 0);
            } else {
                continuation();
            }
        }, 0);
    };

    return function(source) {
        var syncGenerator = function(y, b) {
            return syncNext(source, y || defaultY, b || defaultB);
        };
        Object.defineProperties(syncGenerator, properties);
        syncGenerator.async = constant(function(y, b) {
            return asyncNext(source, y || defaultY, b || defaultB);
        });

        return syncGenerator;
    };
}());

/* Export
 ******************************************************************************/
return Object.defineProperties(gen, {
    'properties': {
        'value': properties
    },
    'GenBreak': GenBreak,
    'single': {
        'value': single,
        'writable': true
    },
    'map': {
        'value': function(s, c, t) { return map(gen(s), c, t); },
        'writable': true
    },
    'filter': {
        'value': function(s, p, t) { return filter(gen(s), p, t); },
        'writable': true
    },
    'reduce': {
        'value': function(s, c, i) { return reduce(gen(s), c, i); },
        'writable': true
     },
    'toArray': {
        'value': function(s) { return toArray(gen(s)); },
        'writable': true
    },
    'forEach': {
        'value': function(s, c, t) { return forEach(gen(s), c, t); },
        'writable': true
    }
});

});

}(
    typeof define !== 'undefined' ? define : function(factory) { gen = factory(); }
));<|endoftext|>