<commit_before>
// TODO: export to external module
//       when i do, add option to not fully traverse into a directory,
//       and option to not traverse into symlinks
//
// TODO: limit max parallellism
// TODO: UNIT TESTS!!! ROBUST CONTRACTS W.R.T. INPUT AND OUTPUT

// tries to match globs with a target destination, so things like
// {src: ['packages/*/src'], dest: ['dist']} are possible.
//
// eventually, something like
//
// {src: ['packages/*/src/*'], dest: ['packages/*/lib']}
//
// should be possible.
//
// For now, something like `scripts/_get-test-directories.sh` can be used for this multi src-dest purpose.

import path from "path";
import glob from "glob";
import globCommon from "glob/common";
const {Glob} = glob;
import isGlob from "is-glob";
import forEach from "lodash/forEach";
import map from "lodash/map";
import isArray from "lodash/isArray";

import asyncBlock from "./_async-block";

function ownProp (obj, field) {
  return Object.prototype.hasOwnProperty.call(obj, field)
}

export default function walk(args: Object, eachCb, cb) {
  return new Walker(args, eachCb, cb).walk(args);
}

// it's a zombie! run!
export class Walker {
  constructor(...args) {
    this.cb = args.pop();
    this.eachCb = args.pop();
    const opts = args[0] || {};

    this._asyncBlock = asyncBlock((err) => {
      if (err) {
        if (!this.aborted) this.abort();
        return (0, this.cb)(err);
      }
      return (0, this.cb)();
    });
    this.retain = this._asyncBlock.retain;
    this.release = this._asyncBlock.release;

    // cwd & root logic borrowed from glob, used in makeAbs
    this.changedCwd = false;
    const cwd = process.cwd();
    if (!ownProp(opts, "cwd"))
      this.cwd = cwd;
    else {
      this.cwd = path.resolve(opts.cwd);
      this.changedCwd = this.cwd !== cwd;
    }

    this.root = opts.root ? path.resolve(opts.root) : path.resolve(this.cwd, "/");
    if (process.platform === "win32") this.root = this.root.replace(/\\/g, "/")

    this._pending = 0;

    this.nextGlobId = 0;
    this.pendingGlobs = Object.create(null);

    this.aborted = false;
    this.seen = Object.create(null);

    // Shared cache between different glob invokations
    this.realpathCache = Object.create(null);
    this.globCache = Object.create(null);
    this.statCache = Object.create(null);
    this.symlinks = Object.create(null);
  }

  walk({src: globs, dest: dests}) {
    if (this._pending > 0) throw new Error("Not reentrant");

    const hasDest = !!dests;
    const oneDest = hasDest && dests.length === 1;
    // assert oneDest || dests.length === globs.length
    for (let i = 0, len = globs.length; i < len; i++) {
      const globPat = globs[i];
      const dest = hasDest && (oneDest ? dests[0] : dests[i]);
      if (isGlob(globPat)) {
        this.walkGlob(globPat, dest);
      } else {
        this.walkPathDirect(globPat, dest);
      }
    }
    return this;
  }

  _globOpts(opts = {}) {
    opts.realpathCache = this.realpathCache;
    opts.cache = this.globCache;
    opts.statCache = this.statCache;
    opts.symlinks = this.symlinks;
    return opts;
  }

  walkGlob(globPat, dest) {
    // TODO: match dest according to globbing
    const dests = dest ? [dest] : false;

    const globberId = this.nextGlobId++;
    // stat all paths, since we'll be walking into found directories
    this.retain();
    this.pendingGlobs[globberId] = new Glob(globPat, this._globOpts({stat: true}), (err, matches) => {
      if (this.aborted) return;
      if (err) return this.abort(err);

      this.pendingGlobs[globberId] = undefined;
      this.walkPaths(matches, dests, globPat.slice(-1) !== "*");
      this.release();
    });
  }

  walkPaths(paths, dests, direct) {
    const hasDest = !!dests;
    const oneDest = hasDest && dests.length === 1;
    // assert oneDest || dests.length === paths.length
    for (let i = 0, len = paths.length; i < len; i++) {
      const src = paths[i]
      const dest = hasDest && (oneDest ? path.join(dests[0], path.basename(src)) : dests[i]);
      this.walkPath(src, dest, direct);
    }
  }

  _makeAbs(f) {
    return globCommon.makeAbs(this, f);
  }

  walkPathDirect(src, dest) {
    // perform a glob just to populate the stat cache
    const globberId = this.nextGlobId++;
    this.retain();
    this.pendingGlobs[globberId] = new Glob(src, this._globOpts({stat: true}), (err) => {
      if (this.aborted) return;
      if (err) return this.abort(err);

      this.pendingGlobs[globberId] = undefined;
      this.walkPath(src, dest, true);
      this.release();
    });
  }

  walkPath(src, dest, direct = false) {
    const cacheKey = this._makeAbs(src);
    const seen = this.seen[cacheKey];
    if (seen) return;
    this.seen[cacheKey] = true;

    const cacheItem = this.globCache[cacheKey];

    if (cacheItem === "DIR" || isArray(cacheItem)) {
      const globberId = this.nextGlobId++;
      this.retain();
      this.pendingGlobs[globberId] = new Glob(src + "/**", this._globOpts(), (err, matches) => {
        if (this.aborted) return;
        if (err) return this.abort(err);

        this.pendingGlobs[globberId] = undefined;

        if (direct) {
          const dests = map(matches, (match) => path.join(dest, match));

          this.walkPaths(matches, dests);
        } else {
          const srcPathLen = src.length;
          const dests = map(matches, (match) => dest + match.slice(srcPathLen));

          this.walkPaths(matches, dests);
        }
        this.release();
      });
    } else {
      (0, this.eachCb)(src, dest);
    }
  }

  abort(err) {
    this.aborted = true;
    forEach(this.pendingGlobs, (globber) => { globber && globber.abort(); });
    this.pendingGlobs = Object.create(null);
    this._asyncBlock.error(err);
  }
}
<commit_msg>fix(tacoscript/cli): replace file extension when compiling<commit_after>
// TODO: export to external module
//       when i do, add option to not fully traverse into a directory,
//       and option to not traverse into symlinks
//
// TODO: limit max parallellism
// TODO: UNIT TESTS!!! ROBUST CONTRACTS W.R.T. INPUT AND OUTPUT

// tries to match globs with a target destination, so things like
// {src: ['packages/*/src'], dest: ['dist']} are possible.
//
// eventually, something like
//
// {src: ['packages/*/src/*'], dest: ['packages/*/lib']}
//
// should be possible.
//
// For now, something like `scripts/_get-test-directories.sh` can be used for this multi src-dest purpose.

import path from "path";

import glob from "glob";
import globCommon from "glob/common";
const {Glob} = glob;
import isGlob from "is-glob";
import forEach from "lodash/forEach";
import map from "lodash/map";
import isArray from "lodash/isArray";

import asyncBlock from "./_async-block";

function ownProp (obj, field) {
  return Object.prototype.hasOwnProperty.call(obj, field)
}

export default function walk(args: Object, eachCb, cb) {
  return new Walker(args, eachCb, cb).walk(args);
}

// it's a zombie! run!
export class Walker {
  constructor(...args) {
    this.cb = args.pop();
    this.eachCb = args.pop();
    const opts = args[0] || {};

    this.destExt = opts.destExt;

    this._asyncBlock = asyncBlock((err) => {
      if (err) {
        if (!this.aborted) this.abort();
        return (0, this.cb)(err);
      }
      return (0, this.cb)();
    });
    this.retain = this._asyncBlock.retain;
    this.release = this._asyncBlock.release;

    // cwd & root logic borrowed from glob, used in makeAbs
    this.changedCwd = false;
    const cwd = process.cwd();
    if (!ownProp(opts, "cwd"))
      this.cwd = cwd;
    else {
      this.cwd = path.resolve(opts.cwd);
      this.changedCwd = this.cwd !== cwd;
    }

    this.root = opts.root ? path.resolve(opts.root) : path.resolve(this.cwd, "/");
    if (process.platform === "win32") this.root = this.root.replace(/\\/g, "/")

    this._pending = 0;

    this.nextGlobId = 0;
    this.pendingGlobs = Object.create(null);

    this.aborted = false;
    this.seen = Object.create(null);

    // Shared cache between different glob invokations
    this.realpathCache = Object.create(null);
    this.globCache = Object.create(null);
    this.statCache = Object.create(null);
    this.symlinks = Object.create(null);
  }

  walk({src: globs, dest: dests}) {
    if (this._pending > 0) throw new Error("Not reentrant");

    const hasDest = !!dests;
    const oneDest = hasDest && dests.length === 1;
    // assert oneDest || dests.length === globs.length
    for (let i = 0, len = globs.length; i < len; i++) {
      const globPat = globs[i];
      const dest = hasDest && (oneDest ? dests[0] : dests[i]);
      if (isGlob(globPat)) {
        this.walkGlob(globPat, dest);
      } else {
        this.walkPathDirect(globPat, dest);
      }
    }
    return this;
  }

  _globOpts(opts = {}) {
    opts.realpathCache = this.realpathCache;
    opts.cache = this.globCache;
    opts.statCache = this.statCache;
    opts.symlinks = this.symlinks;
    return opts;
  }

  walkGlob(globPat, dest) {
    // TODO: match dest according to globbing
    const dests = dest ? [dest] : false;

    const globberId = this.nextGlobId++;
    // stat all paths, since we'll be walking into found directories
    this.retain();
    this.pendingGlobs[globberId] = new Glob(globPat, this._globOpts({stat: true}), (err, matches) => {
      if (this.aborted) return;
      if (err) return this.abort(err);

      this.pendingGlobs[globberId] = undefined;
      this.walkPaths(matches, dests, globPat.slice(-1) !== "*");
      this.release();
    });
  }

  walkPaths(paths, dests, direct) {
    const hasDest = !!dests;
    const oneDest = hasDest && dests.length === 1;
    // assert oneDest || dests.length === paths.length
    for (let i = 0, len = paths.length; i < len; i++) {
      const src = paths[i]
      const dest = hasDest && (oneDest ? path.join(dests[0], path.basename(src)) : dests[i]);
      this.walkPath(src, dest, direct);
    }
  }

  _makeAbs(f) {
    return globCommon.makeAbs(this, f);
  }

  walkPathDirect(src, dest) {
    // perform a glob just to populate the stat cache
    const globberId = this.nextGlobId++;
    this.retain();
    this.pendingGlobs[globberId] = new Glob(src, this._globOpts({stat: true}), (err) => {
      if (this.aborted) return;
      if (err) return this.abort(err);

      this.pendingGlobs[globberId] = undefined;
      this.walkPath(src, dest, true);
      this.release();
    });
  }

  walkPath(src, dest, direct = false) {
    const cacheKey = this._makeAbs(src);
    const seen = this.seen[cacheKey];
    if (seen) return;
    this.seen[cacheKey] = true;

    const cacheItem = this.globCache[cacheKey];

    if (cacheItem === "DIR" || isArray(cacheItem)) {
      const globberId = this.nextGlobId++;
      this.retain();
      this.pendingGlobs[globberId] = new Glob(src + "/**", this._globOpts(), (err, matches) => {
        if (this.aborted) return;
        if (err) return this.abort(err);

        this.pendingGlobs[globberId] = undefined;

        if (direct) {
          const dests = map(matches, (match) => path.join(dest, match));

          this.walkPaths(matches, dests);
        } else {
          const srcPathLen = src.length;
          const dests = map(matches, (match) => dest + match.slice(srcPathLen));

          this.walkPaths(matches, dests);
        }
        this.release();
      });
    } else {
      (0, this.eachCb)(src, this.replaceExt(dest));
    }
  }

  abort(err) {
    this.aborted = true;
    forEach(this.pendingGlobs, (globber) => { globber && globber.abort(); });
    this.pendingGlobs = Object.create(null);
    this._asyncBlock.error(err);
  }

  replaceExt(dest) {
    if (!this.destExt) return dest;
    const p = path.parse(dest);
    p.base = path.basename(p.base, p.ext) + this.destExt;
    return path.format(p);
  }
}
<|endoftext|>


<commit_before>module.exports = [
  {
    value: 'logo',
    name: 'Studio logo',
    url: 'https://github.com/sanity-io/plugin-template-logo/archive/master.zip'
  },
  {
    value: 'tool',
    name: 'Basic, empty tool',
    url: 'https://github.com/sanity-io/plugin-template-tool/archive/master.zip'
  },
  {
    value: 'toolWithRouting',
    name: 'Tool with basic routing',
    url: 'https://github.com/sanity-io/plugin-template-tool-with-routing/archive/master.zip'
  }
]
<commit_msg>[cli] Add chess board input as plugin template<commit_after>module.exports = [
  {
    value: 'logo',
    name: 'Studio logo',
    url: 'https://github.com/sanity-io/plugin-template-logo/archive/master.zip'
  },
  {
    value: 'tool',
    name: 'Basic, empty tool',
    url: 'https://github.com/sanity-io/plugin-template-tool/archive/master.zip'
  },
  {
    value: 'toolWithRouting',
    name: 'Tool with basic routing',
    url: 'https://github.com/sanity-io/plugin-template-tool-with-routing/archive/master.zip'
  },
  {
    value: 'chessInput',
    name: 'Chess board input component w/ block preview',
    url: 'https://github.com/sanity-io/plugin-template-chess-input/archive/master.zip'
  }
]
<|endoftext|>


<commit_before>;(function () {
  'use strict'

  /* imports */
  var typeCheck = require('type-check').typeCheck
  var stringifySafe = require('json-stringify-safe')
  var deepEqual = require('deep-equal')

  /* exports */
  module.exports = {
    truthy: truthy(),
    falsey: falsey(),
    type: type,
    equal: equal,
    match: match,
    or: or,
    and: and,
    not: not
  }

  function truthy () {
    function asserter (subject) {
      if (!subject) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'be'

      return makeError(subject, verb, 'truthy')
    }

    asserter.error = error

    return asserter
  }

  function falsey () {
    function asserter (subject) {
      if (subject) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'be'

      return makeError(subject, verb, 'falsey')
    }

    asserter.error = error

    return asserter
  }

  function equal (reference) {
    function asserter (subject) {
      var ok = reference === subject

      if (typeCheck('Object|Array', reference)) {
        ok = deepEqual(subject, reference, {strict: true})
      }

      if (!ok) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'equal'

      return makeError(subject, verb, reference)
    }

    asserter.error = error

    return asserter
  }

  function match (reference) {
    function asserter (subject) {
      var ok = reference.test(subject)

      if (!ok) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'match'

      return makeError(subject, verb, reference.source)
    }

    asserter.error = error

    return asserter
  }

  function type (reference) {
    function asserter (subject) {
      var ok = typeCheck(reference, subject)

      if (!ok) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'have type'

      return makeError(subject, verb, reference)
    }

    asserter.error = error

    return asserter
  }

  function and (asserters) {
    function asserter (subject) {
      asserters.forEach(function (asserter) {
        try {
          asserter(subject)
        } catch (e) {
          throw error(subject)
        }
      })

      return subject
    }

    function error (subject) {
      var errors = asserters.map(function (asserter) {
        var error = asserter.error(subject)

        error.message = '(' + error.message + ')'

        return error
      })

      var combinedError = errors.reduce(function (combined, error) {
        combined.message += ' AND ' + error.message

        return combined
      })

      return combinedError
    }

    asserter.error = error

    return asserter
  }

  function or (asserters) {
    function asserter (subject) {
      var errors = asserters.reduce(function (results, asserter) {
        try {
          asserter(subject)
        } catch (error) {
          results.push(error)
        }

        return results
      }, [])

      if (errors.length === asserters.length) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var errors = asserters.map(function (asserter) {
        var error = asserter.error(subject)

        error.message = '(' + error.message + ')'

        return error
      })

      var combinedError = errors.reduce(function (combined, error) {
        combined.message += ' OR ' + error.message

        return combined
      })

      return combinedError
    }

    asserter.error = error

    return asserter
  }

  function not (originalAsserter) {
    function asserter (subject) {
      try {
        originalAsserter(subject)
      } catch (error) {
        return subject
      }

      throw error(subject)
    }

    function error (subject) {
      var original = originalAsserter.error(subject)

      original.message = 'NOT(' + original.message + ')'
      return original
    }

    asserter.error = error

    return asserter
  }

  function makeError (subject, verb, reference) {
    var s = stringifySafe(subject)
    var r = stringifySafe(reference)
    var message = s + ' should ' + verb + ' ' + r

    return new Error(message)
  }
})()

<commit_msg>[MINOR][ADD] custom toString functions to all asserters<commit_after>;(function () {
  'use strict'

  /* imports */
  var typeCheck = require('type-check').typeCheck
  var stringifySafe = require('json-stringify-safe')
  var deepEqual = require('deep-equal')

  /* exports */
  module.exports = {
    truthy: truthy(),
    falsey: falsey(),
    type: type,
    equal: equal,
    match: match,
    or: or,
    and: and,
    not: not
  }

  function truthy () {
    function asserter (subject) {
      if (!subject) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'be'

      return makeError(subject, verb, 'truthy')
    }

    asserter.error = error

    asserter.toString = function () {
      return 'isTruthy()'
    }

    return asserter
  }

  function falsey () {
    function asserter (subject) {
      if (subject) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'be'

      return makeError(subject, verb, 'falsey')
    }

    asserter.error = error

    asserter.toString = function () {
      return 'isFalsey()'
    }

    return asserter
  }

  function equal (reference) {
    function asserter (subject) {
      var ok = reference === subject

      if (typeCheck('Object|Array', reference)) {
        ok = deepEqual(subject, reference, {strict: true})
      }

      if (!ok) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'equal'

      return makeError(subject, verb, reference)
    }

    asserter.error = error

    asserter.toString = function () {
      return 'equal(' + reference + ')'
    }

    return asserter
  }

  function match (reference) {
    function asserter (subject) {
      var ok = reference.test(subject)

      if (!ok) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'match'

      return makeError(subject, verb, reference.source)
    }

    asserter.error = error

    asserter.toString = function () {
      return 'match(' + reference + ')'
    }

    return asserter
  }

  function type (reference) {
    function asserter (subject) {
      var ok = typeCheck(reference, subject)

      if (!ok) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var verb = 'have type'

      return makeError(subject, verb, reference)
    }

    asserter.error = error

    asserter.toString = function () {
      return 'hasType(' + reference + ')'
    }

    return asserter
  }

  function and (asserters) {
    function asserter (subject) {
      asserters.forEach(function (asserter) {
        try {
          asserter(subject)
        } catch (e) {
          throw error(subject)
        }
      })

      return subject
    }

    function error (subject) {
      var errors = asserters.map(function (asserter) {
        var error = asserter.error(subject)

        error.message = '(' + error.message + ')'

        return error
      })

      var combinedError = errors.reduce(function (combined, error) {
        combined.message += ' AND ' + error.message

        return combined
      })

      return combinedError
    }

    asserter.error = error

    asserter.toString = function () {
      return 'AND(' + asserters + ')'
    }

    return asserter
  }

  function or (asserters) {
    function asserter (subject) {
      var errors = asserters.reduce(function (results, asserter) {
        try {
          asserter(subject)
        } catch (error) {
          results.push(error)
        }

        return results
      }, [])

      if (errors.length === asserters.length) {
        throw error(subject)
      }

      return subject
    }

    function error (subject) {
      var errors = asserters.map(function (asserter) {
        var error = asserter.error(subject)

        error.message = '(' + error.message + ')'

        return error
      })

      var combinedError = errors.reduce(function (combined, error) {
        combined.message += ' OR ' + error.message

        return combined
      })

      return combinedError
    }

    asserter.error = error

    asserter.toString = function () {
      return 'OR(' + asserters + ')'
    }

    return asserter
  }

  function not (originalAsserter) {
    function asserter (subject) {
      try {
        originalAsserter(subject)
      } catch (error) {
        return subject
      }

      throw error(subject)
    }

    function error (subject) {
      var original = originalAsserter.error(subject)

      original.message = 'NOT(' + original.message + ')'
      return original
    }

    asserter.error = error

    asserter.toString = function () {
      return 'NOT(' + originalAsserter + ')'
    }

    return asserter
  }

  function makeError (subject, verb, reference) {
    var s = stringifySafe(subject)
    var r = stringifySafe(reference)
    var message = s + ' should ' + verb + ' ' + r

    return new Error(message)
  }
})()

<|endoftext|>


<commit_before>
/* Methods relate to limiting the number events for a given day on a DayGrid
----------------------------------------------------------------------------------------------------------------------*/
// NOTE: all the segs being passed around in here are foreground segs

DayGrid.mixin({

	segPopover: null, // the Popover that holds events that can't fit in a cell. null when not visible
	popoverSegs: null, // an array of segment objects that the segPopover holds. null when not visible

	removeSegPopover: function() {
		if (this.segPopover) {
			this.segPopover.hide(); // in handler, will call segPopover's removeElement
		}
	},

	// Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
	// `levelLimit` can be false (don't limit), a number, or true (should be computed).
	limitRows: function(levelLimit) {
		var rowStructs = this.rowStructs || [];
		var row; // row #
		var rowLevelLimit;

		for (row = 0; row < rowStructs.length; row++) {
			this.unlimitRow(row);

			if (!levelLimit) {
				rowLevelLimit = false;
			}
			else if (typeof levelLimit === 'number') {
				rowLevelLimit = levelLimit;
			}
			else {
				rowLevelLimit = this.computeRowLevelLimit(row);
			}

			if (rowLevelLimit !== false) {
				this.limitRow(row, rowLevelLimit);
			}
		}
	},

	// Computes the number of levels a row will accomodate without going outside its bounds.
	// Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
	// `row` is the row number.
	computeRowLevelLimit: function(row) {
		var rowEl = this.rowEls.eq(row); // the containing "fake" row div
		var rowHeight = rowEl.height(); // TODO: cache somehow?
		var trEls = this.rowStructs[row].tbodyEl.children();
		var i, trEl;
		var trHeight;

		function iterInnerHeights(i, childNode) {
			trHeight = Math.max(trHeight, $(childNode).outerHeight());
		}

		// Reveal one level
 at a time and stop when we find one out of bounds
		for (i = 0; i < trEls.length; i++) {
			trEl = trEls.eq(i).removeClass('fc-limited'); // reset to original state (reveal)

			// with rowspans>1 and IE8, trEl.outerHeight() would return the height of the largest cell,
			// so instead, find the tallest inner content element.
			trHeight = 0;
			trEl.find('> td > :first-child').each(iterInnerHeights);

			if (trEl.position().top + trHeight > rowHeight) {
				return i;
			}
		}

		return false; // should not limit at all
	},

	// Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
	// `row` is the row number.
	// `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
	limitRow: function(row, levelLimit) {
		var _this = this;
		var rowStruct = this.rowStructs[row];
		var moreNodes = []; // array of "more"  links and  DOM nodes
		var col = 0; // col #, left-to-right (not chronologically)
		var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
		var cellMatrix; // a matrix (by level, then column) of all  jQuery elements in the row
		var limitedNodes; // array of temporarily hidden level
 and segment  DOM nodes
		var i, seg;
		var segsBelow; // array of segment objects below `seg` in the current `col`
		var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
		var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
		var td, rowspan;
		var segMoreNodes; // array of "more"  cells that will stand-in for the current seg's cell
		var j;
		var moreTd, moreWrap, moreLink;

		// Iterates through empty level cells and places "more" links inside if need be
		function emptyCellsUntil(endCol) { // goes from current `col` to `endCol`
			while (col < endCol) {
				segsBelow = _this.getCellSegs(row, col, levelLimit);
				if (segsBelow.length) {
					td = cellMatrix[levelLimit - 1][col];
					moreLink = _this.renderMoreLink(row, col, segsBelow);
					moreWrap = $('
').append(moreLink);
					td.append(moreWrap);
					moreNodes.push(moreWrap[0]);
				}
				col++;
			}
		}

		if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
			levelSegs = rowStruct.segLevels[levelLimit - 1];
			cellMatrix = rowStruct.cellMatrix;

			limitedNodes = rowStruct.tbodyEl.children().slice(levelLimit) // get level
 elements past the limit
				.addClass('fc-limited').get(); // hide elements and get a simple DOM-nodes array

			// iterate though segments in the last allowable level
			for (i = 0; i < levelSegs.length; i++) {
				seg = levelSegs[i];
				emptyCellsUntil(seg.leftCol); // process empty cells before the segment

				// determine *all* segments below `seg` that occupy the same columns
				colSegsBelow = [];
				totalSegsBelow = 0;
				while (col <= seg.rightCol) {
					segsBelow = this.getCellSegs(row, col, levelLimit);
					colSegsBelow.push(segsBelow);
					totalSegsBelow += segsBelow.length;
					col++;
				}

				if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
					td = cellMatrix[levelLimit - 1][seg.leftCol]; // the segment's parent cell
					rowspan = td.attr('rowspan') || 1;
					segMoreNodes = [];

					// make a replacement  for each column the segment occupies. will be one for each colspan
					for (j = 0; j < colSegsBelow.length; j++) {
						moreTd = $('').attr('rowspan', rowspan);
						segsBelow = colSegsBelow[j];
						moreLink = this.renderMoreLink(
							row,
							seg.leftCol + j,
							[ seg ].concat(segsBelow) // count seg as hidden too
						);
						moreWrap = $('
').append(moreLink);
						moreTd.append(moreWrap);
						segMoreNodes.push(moreTd[0]);
						moreNodes.push(moreTd[0]);
					}

					td.addClass('fc-limited').after($(segMoreNodes)); // hide original  and inject replacements
					limitedNodes.push(td[0]);
				}
			}

			emptyCellsUntil(this.colCnt); // finish off the level
			rowStruct.moreEls = $(moreNodes); // for easy undoing later
			rowStruct.limitedEls = $(limitedNodes); // for easy undoing later
		}
	},

	// Reveals all levels and removes all "more"-related elements for a grid's row.
	// `row` is a row number.
	unlimitRow: function(row) {
		var rowStruct = this.rowStructs[row];

		if (rowStruct.moreEls) {
			rowStruct.moreEls.remove();
			rowStruct.moreEls = null;
		}

		if (rowStruct.limitedEls) {
			rowStruct.limitedEls.removeClass('fc-limited');
			rowStruct.limitedEls = null;
		}
	},

	// Renders an  element that represents hidden event element for a cell.
	// Responsible for attaching click handler as well.
	renderMoreLink: function(row, col, hiddenSegs) {
		var _this = this;
		var view = this.view;

		return $('')
			.text(
				this.getMoreLinkText(hiddenSegs.length)
			)
			.on('click', function(ev) {
				var clickOption = view.opt('eventLimitClick');
				var date = _this.getCellDate(row, col);
				var moreEl = $(this);
				var dayEl = _this.getCellEl(row, col);
				var allSegs = _this.getCellSegs(row, col);

				// rescope the segments to be within the cell's date
				var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
				var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);

				if (typeof clickOption === 'function') {
					// the returned value can be an atomic option
					clickOption = view.trigger('eventLimitClick', null, {
						date: date,
						dayEl: dayEl,
						moreEl: moreEl,
						segs: reslicedAllSegs,
						hiddenSegs: reslicedHiddenSegs
					}, ev);
				}

				if (clickOption === 'popover') {
					_this.showSegPopover(row, col, moreEl, reslicedAllSegs);
				}
				else if (typeof clickOption === 'string') { // a view name
					view.calendar.zoomTo(date, clickOption);
				}
			});
	},

	// Reveals the popover that displays all events within a cell
	showSegPopover: function(row, col, moreLink, segs) {
		var _this = this;
		var view = this.view;
		var moreWrap = moreLink.parent(); // the
 wrapper around the
		var topEl; // the element we want to match the top coordinate of
		var options;

		if (this.rowCnt == 1) {
			topEl = view.el; // will cause the popover to cover any sort of header
		}
		else {
			topEl = this.rowEls.eq(row); // will align with top of row
		}

		options = {
			className: 'fc-more-popover',
			content: this.renderSegPopoverContent(row, col, segs),
			parentEl: this.el,
			top: topEl.offset().top,
			autoHide: true, // when the user clicks elsewhere, hide the popover
			viewportConstrain: view.opt('popoverViewportConstrain'),
			hide: function() {
				// kill everything when the popover is hidden
				_this.segPopover.removeElement();
				_this.segPopover = null;
				_this.popoverSegs = null;
			}
		};

		// Determine horizontal coordinate.
		// We use the moreWrap instead of the  to avoid border confusion.
		if (this.isRTL) {
			options.right = moreWrap.offset().left + moreWrap.outerWidth() + 1; // +1 to be over cell border
		}
		else {
			options.left = moreWrap.offset().left - 1; // -1 to be over cell border
		}

		this.segPopover = new Popover(options);
		this.segPopover.show();
	},

	// Builds the inner DOM contents of the segment popover
	renderSegPopoverContent: function(row, col, segs) {
		var view = this.view;
		var isTheme = view.opt('theme');
		var title = this.getCellDate(row, col).format(view.opt('dayPopoverFormat'));
		var content = $(
			'
' +
				'' +
				'' +
					htmlEscape(title) +
				'' +
				'
' +
			'
' +
			'
' +
				'

' +
			'
'
		);
		var segContainer = content.find('.fc-event-container');
		var i;

		// render each seg's `el` and only return the visible segs
		segs = this.renderFgSegEls(segs, true); // disableResizing=true
		this.popoverSegs = segs;

		for (i = 0; i < segs.length; i++) {

			// because segments in the popover are not part of a grid coordinate system, provide a hint to any
			// grids that want to do drag-n-drop about which cell it came from
			this.prepareHits();
			segs[i].hit = this.getCellHit(row, col);
			this.releaseHits();

			segContainer.append(segs[i].el);
		}

		return content;
	},

	// Given the events within an array of segment objects, reslice them to be in a single day
	resliceDaySegs: function(segs, dayDate) {

		// build an array of the original events
		var events = $.map(segs, function(seg) {
			return seg.event;
		});

		var dayStart = dayDate.clone();
		var dayEnd = dayStart.clone().add(1, 'days');
		var dayRange = { start: dayStart, end: dayEnd };

		// slice the events with a custom slicing function
		segs = this.eventsToSegs(
			events,
			function(range) {
				var seg = intersectRanges(range, dayRange); // undefind if no intersection
				return seg ? [ seg ] : []; // must return an array of segments
			}
		);

		// force an order because eventsToSegs doesn't guarantee one
		this.sortEventSegs(segs);

		return segs;
	},

	// Generates the text that should be inside a "more" link, given the number of events it represents
	getMoreLinkText: function(num) {
		var opt = this.view.opt('eventLimitText');

		if (typeof opt === 'function') {
			return opt(num);
		}
		else {
			return '+' + num + ' ' + opt;
		}
	},

	// Returns segments within a given cell.
	// If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
	getCellSegs: function(row, col, startLevel) {
		var segMatrix = this.rowStructs[row].segMatrix;
		var level = startLevel || 0;
		var segs = [];
		var seg;

		while (level < segMatrix.length) {
			seg = segMatrix[level][col];
			if (seg) {
				segs.push(seg);
			}
			level++;
		}

		return segs;
	}

});
<commit_msg>more link popover now displayed outside scroll container<commit_after>
/* Methods relate to limiting the number events for a given day on a DayGrid
----------------------------------------------------------------------------------------------------------------------*/
// NOTE: all the segs being passed around in here are foreground segs

DayGrid.mixin({

	segPopover: null, // the Popover that holds events that can't fit in a cell. null when not visible
	popoverSegs: null, // an array of segment objects that the segPopover holds. null when not visible

	removeSegPopover: function() {
		if (this.segPopover) {
			this.segPopover.hide(); // in handler, will call segPopover's removeElement
		}
	},

	// Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
	// `levelLimit` can be false (don't limit), a number, or true (should be computed).
	limitRows: function(levelLimit) {
		var rowStructs = this.rowStructs || [];
		var row; // row #
		var rowLevelLimit;

		for (row = 0; row < rowStructs.length; row++) {
			this.unlimitRow(row);

			if (!levelLimit) {
				rowLevelLimit = false;
			}
			else if (typeof levelLimit === 'number') {
				rowLevelLimit = levelLimit;
			}
			else {
				rowLevelLimit = this.computeRowLevelLimit(row);
			}

			if (rowLevelLimit !== false) {
				this.limitRow(row, rowLevelLimit);
			}
		}
	},

	// Computes the number of levels a row will accomodate without going outside its bounds.
	// Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
	// `row` is the row number.
	computeRowLevelLimit: function(row) {
		var rowEl = this.rowEls.eq(row); // the containing "fake" row div
		var rowHeight = rowEl.height(); // TODO: cache somehow?
		var trEls = this.rowStructs[row].tbodyEl.children();
		var i, trEl;
		var trHeight;

		function iterInnerHeights(i, childNode) {
			trHeight = Math.max(trHeight, $(childNode).outerHeight());
		}

		// Reveal one level
 at a time and stop when we find one out of bounds
		for (i = 0; i < trEls.length; i++) {
			trEl = trEls.eq(i).removeClass('fc-limited'); // reset to original state (reveal)

			// with rowspans>1 and IE8, trEl.outerHeight() would return the height of the largest cell,
			// so instead, find the tallest inner content element.
			trHeight = 0;
			trEl.find('> td > :first-child').each(iterInnerHeights);

			if (trEl.position().top + trHeight > rowHeight) {
				return i;
			}
		}

		return false; // should not limit at all
	},

	// Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
	// `row` is the row number.
	// `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
	limitRow: function(row, levelLimit) {
		var _this = this;
		var rowStruct = this.rowStructs[row];
		var moreNodes = []; // array of "more"  links and  DOM nodes
		var col = 0; // col #, left-to-right (not chronologically)
		var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
		var cellMatrix; // a matrix (by level, then column) of all  jQuery elements in the row
		var limitedNodes; // array of temporarily hidden level
 and segment  DOM nodes
		var i, seg;
		var segsBelow; // array of segment objects below `seg` in the current `col`
		var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
		var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
		var td, rowspan;
		var segMoreNodes; // array of "more"  cells that will stand-in for the current seg's cell
		var j;
		var moreTd, moreWrap, moreLink;

		// Iterates through empty level cells and places "more" links inside if need be
		function emptyCellsUntil(endCol) { // goes from current `col` to `endCol`
			while (col < endCol) {
				segsBelow = _this.getCellSegs(row, col, levelLimit);
				if (segsBelow.length) {
					td = cellMatrix[levelLimit - 1][col];
					moreLink = _this.renderMoreLink(row, col, segsBelow);
					moreWrap = $('
').append(moreLink);
					td.append(moreWrap);
					moreNodes.push(moreWrap[0]);
				}
				col++;
			}
		}

		if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
			levelSegs = rowStruct.segLevels[levelLimit - 1];
			cellMatrix = rowStruct.cellMatrix;

			limitedNodes = rowStruct.tbodyEl.children().slice(levelLimit) // get level
 elements past the limit
				.addClass('fc-limited').get(); // hide elements and get a simple DOM-nodes array

			// iterate though segments in the last allowable level
			for (i = 0; i < levelSegs.length; i++) {
				seg = levelSegs[i];
				emptyCellsUntil(seg.leftCol); // process empty cells before the segment

				// determine *all* segments below `seg` that occupy the same columns
				colSegsBelow = [];
				totalSegsBelow = 0;
				while (col <= seg.rightCol) {
					segsBelow = this.getCellSegs(row, col, levelLimit);
					colSegsBelow.push(segsBelow);
					totalSegsBelow += segsBelow.length;
					col++;
				}

				if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
					td = cellMatrix[levelLimit - 1][seg.leftCol]; // the segment's parent cell
					rowspan = td.attr('rowspan') || 1;
					segMoreNodes = [];

					// make a replacement  for each column the segment occupies. will be one for each colspan
					for (j = 0; j < colSegsBelow.length; j++) {
						moreTd = $('').attr('rowspan', rowspan);
						segsBelow = colSegsBelow[j];
						moreLink = this.renderMoreLink(
							row,
							seg.leftCol + j,
							[ seg ].concat(segsBelow) // count seg as hidden too
						);
						moreWrap = $('
').append(moreLink);
						moreTd.append(moreWrap);
						segMoreNodes.push(moreTd[0]);
						moreNodes.push(moreTd[0]);
					}

					td.addClass('fc-limited').after($(segMoreNodes)); // hide original  and inject replacements
					limitedNodes.push(td[0]);
				}
			}

			emptyCellsUntil(this.colCnt); // finish off the level
			rowStruct.moreEls = $(moreNodes); // for easy undoing later
			rowStruct.limitedEls = $(limitedNodes); // for easy undoing later
		}
	},

	// Reveals all levels and removes all "more"-related elements for a grid's row.
	// `row` is a row number.
	unlimitRow: function(row) {
		var rowStruct = this.rowStructs[row];

		if (rowStruct.moreEls) {
			rowStruct.moreEls.remove();
			rowStruct.moreEls = null;
		}

		if (rowStruct.limitedEls) {
			rowStruct.limitedEls.removeClass('fc-limited');
			rowStruct.limitedEls = null;
		}
	},

	// Renders an  element that represents hidden event element for a cell.
	// Responsible for attaching click handler as well.
	renderMoreLink: function(row, col, hiddenSegs) {
		var _this = this;
		var view = this.view;

		return $('')
			.text(
				this.getMoreLinkText(hiddenSegs.length)
			)
			.on('click', function(ev) {
				var clickOption = view.opt('eventLimitClick');
				var date = _this.getCellDate(row, col);
				var moreEl = $(this);
				var dayEl = _this.getCellEl(row, col);
				var allSegs = _this.getCellSegs(row, col);

				// rescope the segments to be within the cell's date
				var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
				var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);

				if (typeof clickOption === 'function') {
					// the returned value can be an atomic option
					clickOption = view.trigger('eventLimitClick', null, {
						date: date,
						dayEl: dayEl,
						moreEl: moreEl,
						segs: reslicedAllSegs,
						hiddenSegs: reslicedHiddenSegs
					}, ev);
				}

				if (clickOption === 'popover') {
					_this.showSegPopover(row, col, moreEl, reslicedAllSegs);
				}
				else if (typeof clickOption === 'string') { // a view name
					view.calendar.zoomTo(date, clickOption);
				}
			});
	},

	// Reveals the popover that displays all events within a cell
	showSegPopover: function(row, col, moreLink, segs) {
		var _this = this;
		var view = this.view;
		var moreWrap = moreLink.parent(); // the
 wrapper around the
		var topEl; // the element we want to match the top coordinate of
		var options;

		if (this.rowCnt == 1) {
			topEl = view.el; // will cause the popover to cover any sort of header
		}
		else {
			topEl = this.rowEls.eq(row); // will align with top of row
		}

		options = {
			className: 'fc-more-popover',
			content: this.renderSegPopoverContent(row, col, segs),
			parentEl: this.view.el, // attach to root of view. guarantees outside of scrollbars.
			top: topEl.offset().top,
			autoHide: true, // when the user clicks elsewhere, hide the popover
			viewportConstrain: view.opt('popoverViewportConstrain'),
			hide: function() {
				// kill everything when the popover is hidden
				_this.segPopover.removeElement();
				_this.segPopover = null;
				_this.popoverSegs = null;
			}
		};

		// Determine horizontal coordinate.
		// We use the moreWrap instead of the  to avoid border confusion.
		if (this.isRTL) {
			options.right = moreWrap.offset().left + moreWrap.outerWidth() + 1; // +1 to be over cell border
		}
		else {
			options.left = moreWrap.offset().left - 1; // -1 to be over cell border
		}

		this.segPopover = new Popover(options);
		this.segPopover.show();

		// the popover doesn't live within the grid's container element, and thus won't get the event
		// delegated-handlers for free. attach event-related handlers to the popover.
		this.bindSegHandlersToEl(this.segPopover.el);
	},

	// Builds the inner DOM contents of the segment popover
	renderSegPopoverContent: function(row, col, segs) {
		var view = this.view;
		var isTheme = view.opt('theme');
		var title = this.getCellDate(row, col).format(view.opt('dayPopoverFormat'));
		var content = $(
			'
' +
				'' +
				'' +
					htmlEscape(title) +
				'' +
				'
' +
			'
' +
			'
' +
				'

' +
			'
'
		);
		var segContainer = content.find('.fc-event-container');
		var i;

		// render each seg's `el` and only return the visible segs
		segs = this.renderFgSegEls(segs, true); // disableResizing=true
		this.popoverSegs = segs;

		for (i = 0; i < segs.length; i++) {

			// because segments in the popover are not part of a grid coordinate system, provide a hint to any
			// grids that want to do drag-n-drop about which cell it came from
			this.prepareHits();
			segs[i].hit = this.getCellHit(row, col);
			this.releaseHits();

			segContainer.append(segs[i].el);
		}

		return content;
	},

	// Given the events within an array of segment objects, reslice them to be in a single day
	resliceDaySegs: function(segs, dayDate) {

		// build an array of the original events
		var events = $.map(segs, function(seg) {
			return seg.event;
		});

		var dayStart = dayDate.clone();
		var dayEnd = dayStart.clone().add(1, 'days');
		var dayRange = { start: dayStart, end: dayEnd };

		// slice the events with a custom slicing function
		segs = this.eventsToSegs(
			events,
			function(range) {
				var seg = intersectRanges(range, dayRange); // undefind if no intersection
				return seg ? [ seg ] : []; // must return an array of segments
			}
		);

		// force an order because eventsToSegs doesn't guarantee one
		this.sortEventSegs(segs);

		return segs;
	},

	// Generates the text that should be inside a "more" link, given the number of events it represents
	getMoreLinkText: function(num) {
		var opt = this.view.opt('eventLimitText');

		if (typeof opt === 'function') {
			return opt(num);
		}
		else {
			return '+' + num + ' ' + opt;
		}
	},

	// Returns segments within a given cell.
	// If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
	getCellSegs: function(row, col, startLevel) {
		var segMatrix = this.rowStructs[row].segMatrix;
		var level = startLevel || 0;
		var segs = [];
		var seg;

		while (level < segMatrix.length) {
			seg = segMatrix[level][col];
			if (seg) {
				segs.push(seg);
			}
			level++;
		}

		return segs;
	}

});
<|endoftext|>


<commit_before>function setupBabelPlugins(addon, options) {
  addon.options = addon.options || {};
  addon.options.babel = addon.options.babel || {};

  let plugins = addon.options.babel.plugins = addon.options.babel.plugins || [];

  let shouldThrowOnComputedOverride

  if (process.env.EMBER_DECORATORS_THROW_ON_COMPUTED_OVERRIDE) {
    shouldThrowOnComputedOverride = process.env.EMBER_DECORATORS_THROW_ON_COMPUTED_OVERRIDE === 'true';
  } else {
    shouldThrowOnComputedOverride = options && 'throwOnComputedOverride' in options
        ? options.throwOnComputedOverride
        : true;
  }

  let pluginOptions = {
    envFlags: {
      source: 'ember-decorators-flags',
      flags: {
        DEBUG: false,
      },
    },

    features: {
      name: 'ember-decorators-flags',
      source: 'ember-decorators-flags',
      flags: {
        THROW_ON_COMPUTED_OVERRIDE: shouldThrowOnComputedOverride,
      },
    },

    externalizeHelpers: {
      global: 'Ember',
    },

    debugTools: {
      source: 'ember-decorators-flags',
      assertPredicateIndex: 1,
    },
  };

  plugins.push([require.resolve('babel-plugin-debug-macros'), pluginOptions]);
}

module.exports = {
  name: '@ember-decorators/utils',

  included(includer) {
    this._super.apply(this, arguments);

    let host = this._findHost();
    let hostOptions = host.options ? host.options['@ember-decorators'] : null;

    setupBabelPlugins(this, hostOptions);
    setupBabelPlugins(includer, hostOptions);
  },
};
<commit_msg>Fix `_super` in included hook (#282)<commit_after>function setupBabelPlugins(addon, options) {
  addon.options = addon.options || {};
  addon.options.babel = addon.options.babel || {};

  let plugins = addon.options.babel.plugins = addon.options.babel.plugins || [];

  let shouldThrowOnComputedOverride

  if (process.env.EMBER_DECORATORS_THROW_ON_COMPUTED_OVERRIDE) {
    shouldThrowOnComputedOverride = process.env.EMBER_DECORATORS_THROW_ON_COMPUTED_OVERRIDE === 'true';
  } else {
    shouldThrowOnComputedOverride = options && 'throwOnComputedOverride' in options
        ? options.throwOnComputedOverride
        : true;
  }

  let pluginOptions = {
    envFlags: {
      source: 'ember-decorators-flags',
      flags: {
        DEBUG: false,
      },
    },

    features: {
      name: 'ember-decorators-flags',
      source: 'ember-decorators-flags',
      flags: {
        THROW_ON_COMPUTED_OVERRIDE: shouldThrowOnComputedOverride,
      },
    },

    externalizeHelpers: {
      global: 'Ember',
    },

    debugTools: {
      source: 'ember-decorators-flags',
      assertPredicateIndex: 1,
    },
  };

  plugins.push([require.resolve('babel-plugin-debug-macros'), pluginOptions]);
}

module.exports = {
  name: '@ember-decorators/utils',

  included(includer) {
    this._super.included.apply(this, arguments);

    let host = this._findHost();
    let hostOptions = host.options ? host.options['@ember-decorators'] : null;

    setupBabelPlugins(this, hostOptions);
    setupBabelPlugins(includer, hostOptions);
  },
};
<|endoftext|>


<commit_before>require('better-log/install');

const fs = require('fs');
const path = require('path');

function replaceTemplateUrlWithTemplate(node, basePath) {
	const propertyKey = node.key;
	const propertyValue = node.value;

	if (propertyKey.name !== 'templateUrl') {
		return;
	}

	const templatePath = path.join(basePath, propertyValue.value);

	let templateStr;
	try {
		templateStr = fs.readFileSync(templatePath).toString();
		propertyKey.name = 'template';
		propertyValue.value = templateStr;
	} catch(e) {
		if (e.code === 'ENOENT') {
			console.warn(`File not found: ${e.path}`);
		}
	}
}

module.exports = function() {
	return {
		visitor: {
			ObjectProperty(nodePath, state) {

			    // If basePath isn't specified, use the abs. file folder as base path,
                // to have the ability to work with relative templateUrl's
                const basePath = state.opts.basePath || state.file.opts.filename.split('/').slice(0, -1).join('/');

				replaceTemplateUrlWithTemplate(nodePath.node, basePath);
			}
		}
	};
};
<commit_msg>style: fix identation<commit_after>require('better-log/install');

const fs = require('fs');
const path = require('path');

function replaceTemplateUrlWithTemplate(node, basePath) {
	const propertyKey = node.key;
	const propertyValue = node.value;

	if (propertyKey.name !== 'templateUrl') {
		return;
	}

	const templatePath = path.join(basePath, propertyValue.value);

	let templateStr;
	try {
		templateStr = fs.readFileSync(templatePath).toString();
		propertyKey.name = 'template';
		propertyValue.value = templateStr;
	} catch(e) {
		if (e.code === 'ENOENT') {
			console.warn(`File not found: ${e.path}`);
		}
	}
}

module.exports = function() {
	return {
		visitor: {
			ObjectProperty(nodePath, state) {

				// If basePath isn't specified, use the abs. file folder as base path,
				// to have the ability to work with relative templateUrl's
				const basePath = state.opts.basePath || state.file.opts.filename.split('/').slice(0, -1).join('/');

				replaceTemplateUrlWithTemplate(nodePath.node, basePath);
			}
		}
	};
};
<|endoftext|>


<commit_before>/**
 * Pseudo-rule for metadata extraction: title.
 */

// 'self.name' would be 'metadata.title'

exports.name = "metadata.title";

exports.check = function(sr, done) {
    var title = sr.jsDocument.querySelector("body div.head h1");
    ;
    if (!title) {
        return done();
    } else {
        return done({title: sr.norm(title.innerHTML.replace(/:
/g, ": ").replace(/
/g, " - "))});
    }
};
<commit_msg>rm unnecessary semicolon<commit_after>/**
 * Pseudo-rule for metadata extraction: title.
 */

// 'self.name' would be 'metadata.title'

exports.name = "metadata.title";

exports.check = function(sr, done) {
    var title = sr.jsDocument.querySelector("body div.head h1");
    if (!title) {
        return done();
    } else {
        return done({title: sr.norm(title.innerHTML.replace(/:
/g, ": ").replace(/
/g, " - "))});
    }
};
<|endoftext|>


<commit_before>export * from './core';
<commit_msg>src: add bootstrap logic to index.js for webpack bundle<commit_after>import fs from 'fs';
import path from 'path';
import * as __modules__ from './core';

// only for webpack bundle
if (global.__WEBPACK__) {
  const argv = process.argv;
  const usage = 'Usage: node blinksocks.js -c/--config <json_file>';

  const conditions = [
    argv.length !== 4,
    (argv[2] !== '-c' && argv[2] !== '--config'),
    !argv[3].endsWith('.json')
  ];

  if (conditions.some((c) => c)) {
    console.log(usage);
    process.exit(0);
  }

  const file = path.resolve(process.cwd(), argv[3]);

  let json = null;
  try {
    const jsonFile = fs.readFileSync(file);
    json = JSON.parse(jsonFile);
  } catch (err) {
    throw Error(`fail to parse your '${file}': ${err.message}`);
  }

  const app = new __modules__.Hub(json);
  app.on('close', () => process.exit(0));
  app.run();

  process.on('SIGINT', () => app.terminate());
}

module.exports = __modules__;
<|endoftext|>


<commit_before>/**
 * @fileoverview Rule to flag declared but unused variables
 * @author Ilya Volodin
 */

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {

    var allowUnusedGlobals = context.options[0] === "all" ? false : true;

    var variables = [];

    function populateVariables(node) {
        var scope = context.getScope(),
            functionName = node && node.id && node.id.name,
            parent = context.getAncestors().pop(),

            // check for function foo(){}.bind(this)
            functionNameUsed = parent && parent.type === "MemberExpression";

        scope.variables.forEach(function(variable) {

            //filter out global variables that we add as part of eslint or arguments variable
            if (variable.identifiers.length > 0) {

                //make sure that this variable is not already in the array
                if (!variables.some(function(storedVariable) {
                    return storedVariable.name === variable.name && storedVariable.node === variable.identifiers[0];
                })) {

                    variables.push({
                        name: variable.name,
                        node: variable.identifiers[0],
                        used: (variable.name === functionName) && functionNameUsed
                    });
                }
            }
        });
    }

    function populateGlobalVariables() {
        if (!allowUnusedGlobals) {
            populateVariables();
        }
    }

    function findVariable(name) {
        var scope = context.getScope();
        var scopeVariable = [];

        function filter(variable) {
            return variable.name === name;
        }

        while (scopeVariable.length === 0) {
            scopeVariable = scope.variables.filter(filter);
            if (scopeVariable.length === 0) {
                if (!scope.upper) {
                    return null;
                }
                scope = scope.upper;
            }
        }
        return variables.filter(function(variable) {
            return variable.name === scopeVariable[0].name && scopeVariable[0].identifiers.some(function(identifier) {
                return variable.node === identifier;
            });
        })[0];
    }

    function isFunction(node) {
        return node && node.type && (node.type === "FunctionDeclaration" || node.type === "FunctionExpression");
    }

    function findFirstAncestorThatIsFunctionExpressionOrDeclaration(ancestors) {
        var currentAncestor;
        while (ancestors.length !== 0 && !isFunction(currentAncestor)) {
            currentAncestor = ancestors.pop();
        }
        return isFunction(currentAncestor) ? currentAncestor : undefined;
    }

    function markIgnorableUnusedVariables(usedVariable, ancestors) {
        /* When variables are declared as parameters in a FunctionExpression or
         * FunctionDeclaration, they can go unused so long as at least one
         * to the right of them is used.
         */

        // Find the FunctionExpressions and FunctionDeclarations in which this used variable
        // may be a parameter
        var ancestorFunctionNode = findFirstAncestorThatIsFunctionExpressionOrDeclaration(ancestors);
        if (ancestorFunctionNode) {
            // Get a list of the param names used in the ancestor Function
            var fnParamNames = ancestorFunctionNode.params.map(function(param){
                return param.name;
            });
            // Check if the used variable exists among those params
            var variableIndex = fnParamNames.indexOf(usedVariable.name);
            // This will be true if this variable appears in the param list of an ancestor Function Expression
            // or FunctionDeclaration.
            if (variableIndex !== -1) {
                // All params left of the used variables are ignorable.
                var ignorableVariables = fnParamNames.slice(0, variableIndex);
                // Mark them as ignorable.
                ignorableVariables.forEach(function(ignorableVariable){
                    variables.forEach(function(variable){
                        if (variable.name === ignorableVariable) {
                            variable.ignorable = true;
                        }
                    });
                });
            }
        }
    }

    return {
        "FunctionDeclaration": populateVariables,
        "FunctionExpression": populateVariables,
        "Program": populateGlobalVariables,
        "Identifier": function(node) {
            var ancestors = context.getAncestors(node);
            var parent = ancestors.pop();
            var grandparent = ancestors.pop();
            /*if it's not an assignment expression find corresponding
              *variable in the array and mark it as used
              */
            if ((parent.type !== "AssignmentExpression" || node !== parent.left) &&
                (parent.type !== "VariableDeclarator" || (parent.init && parent.init === node)) &&
                parent.type !== "FunctionDeclaration" &&
                (parent.type !== "FunctionExpression" ||
                (grandparent !== null && (grandparent.type === "CallExpression" || grandparent.type === "AssignmentExpression")))) {

                var variable = findVariable(node.name);
                if (variable) {
                    variable.used = true;
                    markIgnorableUnusedVariables(variable, ancestors);
                }

            }
        },

        "Program:after": function() {
            var unused = variables.filter(function(variable) {
                return !variable.used && !variable.ignorable;
            });
            unused.forEach(function(variable) {
                context.report(variable.node, "{{var}} is defined but never used", {"var": variable.name});
            });
        }
    };

};
<commit_msg>optimize findVariable() in no-unused-vars<commit_after>/**
 * @fileoverview Rule to flag declared but unused variables
 * @author Ilya Volodin
 */

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {

    var allowUnusedGlobals = context.options[0] === "all" ? false : true;

    var variables     = [],
        variableNames = {};

    function populateVariables(node) {
        var scope = context.getScope(),
            functionName = node && node.id && node.id.name,
            parent = context.getAncestors().pop(),

            // check for function foo(){}.bind(this)
            functionNameUsed = parent && parent.type === "MemberExpression";

        scope.variables.forEach(function(variable) {
            var index;

            //filter out global variables that we add as part of eslint or arguments variable
            if (variable.identifiers.length > 0) {

                //make sure that this variable is not already in the array
                if (!variables.some(function(storedVariable) {
                    return storedVariable.name === variable.name && storedVariable.node === variable.identifiers[0];
                })) {

                    index = variables.push({
                        name: variable.name,
                        node: variable.identifiers[0],
                        used: (variable.name === functionName) && functionNameUsed
                    });
                    if (!Object.prototype.hasOwnProperty.call(variableNames, variable.name)) {
                        variableNames[variable.name] = [index - 1];
                    } else {
                        variableNames[variable.name].push(index - 1);
                    }
                }
            }
        });
    }

    function populateGlobalVariables() {
        if (!allowUnusedGlobals) {
            populateVariables();
        }
    }

    function findVariable(name) {
        var scope = context.getScope();
        var scopeVariable = [];

        function filter(variable) {
            return variable.name === name;
        }

        while (scopeVariable.length === 0) {
            scopeVariable = scope.variables.filter(filter);
            if (scopeVariable.length === 0) {
                if (!scope.upper) {
                    return null;
                }
                scope = scope.upper;
            }
        }

        if (!Object.prototype.hasOwnProperty.call(variableNames, scopeVariable[0].name)) {
            return null;
        }
        return variableNames[scopeVariable[0].name].map(function (index) {
            return variables[index];
        }).filter(function(variable) {
            return variable.name === scopeVariable[0].name && scopeVariable[0].identifiers.some(function(identifier) {
                return variable.node === identifier;
            });
        })[0];
    }

    function isFunction(node) {
        return node && node.type && (node.type === "FunctionDeclaration" || node.type === "FunctionExpression");
    }

    function findFirstAncestorThatIsFunctionExpressionOrDeclaration(ancestors) {
        var currentAncestor;
        while (ancestors.length !== 0 && !isFunction(currentAncestor)) {
            currentAncestor = ancestors.pop();
        }
        return isFunction(currentAncestor) ? currentAncestor : undefined;
    }

    function markIgnorableUnusedVariables(usedVariable, ancestors) {
        /* When variables are declared as parameters in a FunctionExpression or
         * FunctionDeclaration, they can go unused so long as at least one
         * to the right of them is used.
         */

        // Find the FunctionExpressions and FunctionDeclarations in which this used variable
        // may be a parameter
        var ancestorFunctionNode = findFirstAncestorThatIsFunctionExpressionOrDeclaration(ancestors);
        if (ancestorFunctionNode) {
            // Get a list of the param names used in the ancestor Function
            var fnParamNames = ancestorFunctionNode.params.map(function(param){
                return param.name;
            });
            // Check if the used variable exists among those params
            var variableIndex = fnParamNames.indexOf(usedVariable.name);
            // This will be true if this variable appears in the param list of an ancestor Function Expression
            // or FunctionDeclaration.
            if (variableIndex !== -1) {
                // All params left of the used variables are ignorable.
                var ignorableVariables = fnParamNames.slice(0, variableIndex);
                // Mark them as ignorable.
                ignorableVariables.forEach(function(ignorableVariable){
                    variables.forEach(function(variable){
                        if (variable.name === ignorableVariable) {
                            variable.ignorable = true;
                        }
                    });
                });
            }
        }
    }

    return {
        "FunctionDeclaration": populateVariables,
        "FunctionExpression": populateVariables,
        "Program": populateGlobalVariables,
        "Identifier": function(node) {
            var ancestors = context.getAncestors(node);
            var parent = ancestors.pop();
            var grandparent = ancestors.pop();
            /*if it's not an assignment expression find corresponding
              *variable in the array and mark it as used
              */
            if ((parent.type !== "AssignmentExpression" || node !== parent.left) &&
                (parent.type !== "VariableDeclarator" || (parent.init && parent.init === node)) &&
                parent.type !== "FunctionDeclaration" &&
                (parent.type !== "FunctionExpression" ||
                (grandparent !== null && (grandparent.type === "CallExpression" || grandparent.type === "AssignmentExpression")))) {

                var variable = findVariable(node.name);
                if (variable) {
                    variable.used = true;
                    markIgnorableUnusedVariables(variable, ancestors);
                }

            }
        },

        "Program:after": function() {
            var unused = variables.filter(function(variable) {
                return !variable.used && !variable.ignorable;
            });
            unused.forEach(function(variable) {
                context.report(variable.node, "{{var}} is defined but never used", {"var": variable.name});
            });
        }
    };

};
<|endoftext|>


<commit_before>/**
 * <%= pluginName %> plugin for Craft CMS
 *
 * <%= pluginHandle %><%= fieldName[index] %>FieldType JS
 *
 * @author    <%= pluginAuthorName %>
 * @copyright <%= copyrightNotice %>
 * @link      <%= pluginAuthorUrl %>
 * @package   <%= pluginHandle %>
 * @since     <%= pluginVersion %>
 */

 ;(function ( $, window, document, undefined ) {

    var pluginName = "<%= pluginHandle %>_<%= fieldName %>FieldType",
        defaults = {
        };

    // Plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype = {

        init: function(id) {
            var _this = this;

            $(function () {

/* -- _this.options gives us access to the $jsonVars that our FieldType passed down to us */

            });
        }
    };

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName,
                new Plugin( this, options ));
            }
        });
    };

})( jQuery, window, document );
<commit_msg>fixed FieldType JS<commit_after>/**
 * <%= pluginName %> plugin for Craft CMS
 *
 * <%= pluginHandle %><%= fieldName[index] %>FieldType JS
 *
 * @author    <%= pluginAuthorName %>
 * @copyright <%= copyrightNotice %>
 * @link      <%= pluginAuthorUrl %>
 * @package   <%= pluginHandle %>
 * @since     <%= pluginVersion %>
 */

 ;(function ( $, window, document, undefined ) {

    var pluginName = "<%= pluginHandle %><%= fieldName %>FieldType",
        defaults = {
        };

    // Plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype = {

        init: function(id) {
            var _this = this;

            $(function () {

/* -- _this.options gives us access to the $jsonVars that our FieldType passed down to us */

            });
        }
    };

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName,
                new Plugin( this, options ));
            }
        });
    };

})( jQuery, window, document );
<|endoftext|>


<commit_before>/* @flow */

import invariant from 'assert'
import PoolWorker from './worker'

export default class RangePool {
  length: number;
  workers: Set<PoolWorker>;

  constructor(length: number) {
    invariant(typeof length === 'number', 'length is not a number')
    invariant(Number.isFinite(length), 'length can not be infinite')
    invariant(length > 0, 'length must be greater than zero')

    this.length = length
    this.workers = new Set()
  }
  createWorker(): PoolWorker {
    let lazyWorker = null
    let lazyDiff = 0
    let lazyPercentage = 101

    for (const worker of this.workers) {
      if (!worker.hasCompleted()) {
        if (!worker.getActive()) {
          return worker.setActive(true)
        }

        const percentage = worker.getCompletionPercentage()
        const diff = worker.getLimitIndex() - worker.getCurrentIndex()
        if (percentage < lazyPercentage) {
          lazyWorker = worker
          lazyPercentage = percentage
          lazyDiff = diff
        } else if (lazyDiff < diff) {
          lazyWorker = worker
          lazyPercentage = percentage
          lazyDiff = diff
        }
      }
    }

    if (!lazyWorker) {
      if (this.hasCompleted()) {
        throw new Error('Can not add a new worker on a completed pool')
      }
      return this.registerWorker(new PoolWorker(this.getCompletedSteps(), this.length)).setActive(true)
    }

    const workLeft = lazyWorker.getRemaining()
    const indexForNewWorker = Math.ceil(lazyWorker.currentIndex + (workLeft / 2))
    const newWorker = new PoolWorker(indexForNewWorker, lazyWorker.limitIndex)
    lazyWorker.limitIndex = indexForNewWorker
    return this.registerWorker(newWorker).setActive(true)
  }
  hasCompleted(): boolean {
    return this.getCompletedSteps() === this.length
  }
  getWorkingWorker(): ?PoolWorker {
    for (const worker of this.workers) {
      if (!worker.hasCompleted() && worker.setActive(true)) {
        return worker
      }
    }
    return null
  }
  hasWorkingWorker(): boolean {
    return this.getWorkingWorker() !== null
  }
  getCompletedSteps(): number {
    let completedSteps = 0
    for (const worker of this.workers) {
      completedSteps += worker.currentIndex - worker.startIndex
    }
    return completedSteps
  }
  getRemaining(): number {
    return this.length - this.getCompletedSteps()
  }
  // Private function registerWorker
  registerWorker(worker: PoolWorker): PoolWorker {
    this.workers.add(worker)
    return worker
  }
  dispose() {
    this.workers.clear()
  }
  serialize(): string {
    const workers = []
    for (const worker of this.workers) {
      workers.push(worker.serialize())
    }
    return JSON.stringify({
      length: this.length,
      workers,
    }, function(key: string, value: any) {
      return value === Infinity ? 'Infinity' : value
    })
  }
  static unserialize(serialized: string): RangePool {
    invariant(typeof serialized === 'string', 'Serialized content must be a string')

    const unserialized = JSON.parse(serialized, function(key: string, value: any) {
      return value === 'Infinity' ? Infinity : value
    })
    const pool = new RangePool(unserialized.length)
    for (let i = 0, length = unserialized.workers.length; i < length; ++i) {
      pool.workers.add(PoolWorker.unserialize(unserialized.workers[i]))
    }
    return pool
  }
}
<commit_msg>:bug: Fix several ::createWorker related bugs in PoolWorker<commit_after>/* @flow */

import invariant from 'assert'
import PoolWorker from './worker'

export default class RangePool {
  length: number;
  workers: Set<PoolWorker>;

  constructor(length: number) {
    invariant(typeof length === 'number', 'length is not a number')
    invariant(Number.isFinite(length), 'length can not be infinite')
    invariant(length > 0, 'length must be greater than zero')

    this.length = length
    this.workers = new Set()
  }
  createWorker(): ?PoolWorker {
    if (this.hasCompleted()) {
      throw new Error('Can not add a new worker on a completed pool')
    }

    let lazy: ?PoolWorker = null

    for (const worker of this.workers) {
      if (worker.hasCompleted()) {
        continue
      }
      if (!worker.getActive()) {
        return worker.setActive(true)
      }
      if (!lazy || worker.getCompletionPercentage() < lazy.getCompletionPercentage() || worker.getRemaining() > lazy.getRemaining()) {
        lazy = worker
      }
    }

    invariant(lazy, 'No lazy worker found?!')
    const workLeft = lazy.getRemaining()
    const indexForNewWorker = Math.ceil(lazy.currentIndex + (workLeft / 2))
    const newWorker = new PoolWorker(indexForNewWorker, lazy.limitIndex)
    this.workers.add(newWorker)
    lazy.limitIndex = indexForNewWorker
    return newWorker.setActive(true)
  }
  hasCompleted(): boolean {
    return this.getCompletedSteps() === this.length
  }
  hasAliveWorker(): boolean {
    for (const worker of this.workers) {
      if (!worker.hasCompleted() && worker.getActive()) {
        return true
      }
    }
    return false
  }
  getCompletedSteps(): number {
    let completedSteps = 0
    for (const worker of this.workers) {
      completedSteps += worker.currentIndex - worker.startIndex
    }
    return completedSteps
  }
  getRemaining(): number {
    return this.length - this.getCompletedSteps()
  }
  dispose() {
    this.workers.clear()
  }
  serialize(): string {
    const workers = []
    for (const worker of this.workers) {
      workers.push(worker.serialize())
    }
    return JSON.stringify({
      length: this.length,
      workers,
    }, function(key: string, value: any) {
      return value === Infinity ? 'Infinity' : value
    })
  }
  static unserialize(serialized: string): RangePool {
    invariant(typeof serialized === 'string', 'Serialized content must be a string')

    const unserialized = JSON.parse(serialized, function(key: string, value: any) {
      return value === 'Infinity' ? Infinity : value
    })
    const pool = new RangePool(unserialized.length)
    for (let i = 0, length = unserialized.workers.length; i < length; ++i) {
      pool.workers.add(PoolWorker.unserialize(unserialized.workers[i]))
    }
    return pool
  }
}
<|endoftext|>


<commit_before>import DIFFICULTIES from './DIFFICULTIES';

export default function getDifficulty(fight) {
  return DIFFICULTIES[fight.difficulty];
}
<commit_msg>Fix undefined difficulty<commit_after>import DIFFICULTIES from './DIFFICULTIES';

export default function getDifficulty(fight) {
  return DIFFICULTIES[fight.difficulty] || ''; // difficulty may be undefined if we couldn't find it, which happens for things like trash
}
<|endoftext|>


<commit_before>var _ = require("lodash");
var url = require("url");
var path = require("path");
var express = require("express");
var leveldown = require("leveldown");
var bodyParser = require("body-parser");
var PicoEngine = require("pico-engine-core");
var RulesetLoader = require("./RulesetLoader");
var compiler = require("krl-compiler");

////////////////////////////////////////////////////////////////////////////////
var port = process.env.PORT || 8080;
var pico_engine_home = process.env.PICO_ENGINE_HOME || path.resolve(__dirname, "..");
////////////////////////////////////////////////////////////////////////////////

PicoEngine({
  compileAndLoadRuleset: RulesetLoader({
    rulesets_dir: path.resolve(pico_engine_home, "rulesets")
  }),
  db: {
    db: leveldown,
    location: path.join(pico_engine_home, "db")
  }
}, function(err, pe){
  if(err){
    throw err;
  }

  var logs = {};
  var logRID = "io.picolabs.logging";
  var logEntry = function(context,message){
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      episode.logs.push(timestamp+" "+message);
    } else {
      console.log("[ERROR]","no episode found for",eci);
    }
  };
  var logEpisode = function(pico_id,context,callback){
    var eci = context.eci;
    var episode = logs[eci];
    if (!episode) {
      console.log("[ERROR]","no episode found for",eci);
    }
    pe.db.getEntVar(pico_id,logRID,"status",function(e,status){
      if (status) {
        pe.db.getEntVar(pico_id,logRID,"logs",function(e,data){
          data[episode.key] = episode.logs;
          pe.db.putEntVar(pico_id,logRID,"logs",data,function(e){
            callback(delete logs[eci]);
          });
        });
      } else {
        callback(delete logs[eci]);
      }
    });
  };
  pe.emitter.on("episode_start", function(context){
    console.log("EPISODE_START",context);
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      console.log("[ERROR]","episode already exists for",eci);
    } else {
      episode = {};
      episode.key = (
        timestamp + " - " + eci
          + " - " + ((context.event) ? context.event.eid : "query")
        ).replace(/[.]/g, "-");
      episode.logs = [];
      logs[eci] = episode;
    }
  });
  pe.emitter.on("klog", function(context, val, message){
    console.log("[KLOG]", message, val);
    logEntry(context,"[KLOG] "+message+" "+val);
  });
  pe.emitter.on("debug", function(context, message){
    console.log("[DEBUG]", context, message);
    var prefix = "";
    if (/^event rec..ved/.test(message)) {
      prefix = context.event.domain + "/" + context.event.type + " ";
    } else if (/^query rec..ved/.test(message)) {
      prefix = context.query.rid + "/" + context.query.name + " ";
    }
    logEntry(context,prefix+message);
  });
  pe.emitter.on("episode_stop", function(context){
    console.log("EPISODE_STOP",context);
    var callback = function(outcome){
      console.log("[EPISODE_REMOVED]",outcome);
    };
    logEpisode(context.pico_id,context,callback);
  });

  var app = express();
  app.use(express.static(path.resolve(__dirname, "..", "public")));
  app.use(bodyParser.json({type: "application/*+json"}));
  app.use(bodyParser.urlencoded({type: "application/x-www-form-urlencoded", extended: false}));

  var errResp = function(res, err){
    res.statusCode = err.statusCode || 500;
    res.end(err.message);
  };

  app.all("/sky/event/:eci/:eid/:domain/:type", function(req, res){
    var event = {
      eci: req.params.eci,
      eid: req.params.eid,
      domain: req.params.domain,
      type: req.params.type,
      attrs: req.query
    };
    pe.signalEvent(event, function(err, response){
      if(err) return errResp(res, err);
      res.json(response);
    });
  });

  app.all("/sky/cloud/:eci/:rid/:function", function(req, res){
    var query = {
      eci: req.params.eci,
      rid: req.params.rid,
      name: req.params["function"],
      args: req.query
    };
    pe.runQuery(query, function(err, data){
      if(err) return errResp(res, err);
      if(_.isFunction(data)){
        data(res);
      }else{
        res.json(data);
      }
    });
  });

  app.all("/api/db-dump", function(req, res){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);
      res.json(db_data);
    });
  });

  app.all("/old", function(req, res){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);

      var html = "";
      html += "\n\n";
      html += "
http://localhost:" + port + "
\n";
      html += "
Picos
\n";
      _.each(db_data.pico, function(pico){
        html += "
\n";
        html += "
"+pico.id+"
\n";
        html += "
\n";

        html += "
Channels
\n";
        html += "
\n";
        _.each(pico.channel, function(chan){
          var rm_link = "/api/pico/"+pico.id+"/rm-channel/"+chan.id;
          html += "
"+JSON.stringify(chan)+" del
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/new-channel\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"name\" placeholder=\"name...\">\n";
        html += "<input type=\"text\" name=\"type\" placeholder=\"type...\">\n";
        html += "<button type=\"submit\">add channel</button>\n";
        html += "</form>\n";

        html += "
Rulesets
\n";
        html += "
\n";
        _.each(pico.ruleset, function(d, rid){
          var rm_link = "/api/pico/"+pico.id+"/rm-ruleset/"+rid;
          html += "
"+rid+" del
\n";
          html += "
\n";
          _.each(_.get(db_data, ["pico", pico.id, rid, "vars"]),
                 function(v,k){
                   html += "
"+k+"="+JSON.stringify(v)+"
\n";
                 });
          html += "
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/add-ruleset\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"rid\" placeholder=\"Ruleset id...\">\n";
        html += "<button type=\"submit\">add ruleset</button>\n";
        html += "</form>\n";

        html += "
\n";
        html += "
\n";
      });
      html += "
\n";
      html += "add pico\n";
      html += "
\n";
      html += "
Rulesets
\n";
      _.each(_.get(db_data, ["rulesets", "versions"]), function(versions, rid){
        var enabled_hash = _.get(db_data, ["rulesets", "enabled", rid, "hash"]);
        html += "
\n";
        html += "
"+rid+"
\n";
        _.each(versions, function(hashes, timestamp){
          _.each(hashes, function(is_there, hash){
            if(!is_there){
              return;
            }
            html += "
\n";
            html += timestamp + " | " + hash + " | ";
            if(hash === enabled_hash){
              html += "disable";
              html += " | ";
              if(pe.isInstalled(rid)){
                html += "uninstall";
              }else{
                html += "install";
              }
              var the_krl_src = _.get(db_data, ["rulesets", "krl", enabled_hash, "src"]);
              html += "
" + the_krl_src + "
\n";
            }else{
              html += "enable";
            }
            html += "
\n";
          });
        });
        html += "
\n";
      });
      html += "<form action=\"/api/ruleset/register\" method=\"GET\">\n";
      html += "<textarea name=\"src\"></textarea>\n";
      html += "<button type=\"submit\">register ruleset</button>\n";
      html += "</form>\n";
      html += "
\n";
      html += "raw database dump\n";
  //    html += "
\n" + JSON.stringify(db_data, undefined, 2) + "\n
\n";
      html += "\n\n";
      res.end(html);
    });
  });

  app.all("/api/owner-channel", function(req, res){
    pe.db.getFirstChannel(function(err, first_channel){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(first_channel, undefined, 2));
    });
  });

  app.all("/api/new-pico", function(req, res){
    pe.db.newPico({}, function(err, new_pico){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(new_pico, undefined, 2));
    });
  });

  app.all("/api/rm-pico/:id", function(req, res){
    pe.db.removePico(req.params.id, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/pico/:id/new-channel", function(req, res){
    pe.db.newChannel({
      pico_id: req.params.id,
      name: req.query.name,
      type: req.query.type
    }, function(err, new_channel){
      if(err) return errResp(res, err);
      res.json(new_channel);
    });
  });

  app.all("/api/pico/:id/rm-channel/:eci", function(req, res){
    pe.db.removeChannel(req.params.id, req.params.eci, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/pico/:id/rm-ruleset/:rid", function(req, res){
    pe.db.removeRuleset(req.params.id, req.params.rid, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/pico/:id/add-ruleset", function(req, res){
    pe.db.addRuleset({pico_id: req.params.id, rid: req.query.rid}, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/compile", function(req, res){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);
    try{
      res.json({ code: compiler(src).code});
    }catch(err){
      res.json({ error: err.toString() });
    }
  });

  app.all("/api/ruleset/register", function(req, res){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);

    pe.db.registerRuleset(src, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/enable/:hash", function(req, res){
    pe.db.enableRuleset(req.params.hash, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/install/:rid", function(req, res){
    pe.installRID(req.params.rid, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/disable/:rid", function(req, res){
    pe.db.disableRuleset(req.params.rid, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.listen(port, function () {
    console.log("http://localhost:" + port);
  });
});
<commit_msg>give body parameters precedence _.assign({}, req.query, req.body)<commit_after>var _ = require("lodash");
var url = require("url");
var path = require("path");
var express = require("express");
var leveldown = require("leveldown");
var bodyParser = require("body-parser");
var PicoEngine = require("pico-engine-core");
var RulesetLoader = require("./RulesetLoader");
var compiler = require("krl-compiler");

////////////////////////////////////////////////////////////////////////////////
var port = process.env.PORT || 8080;
var pico_engine_home = process.env.PICO_ENGINE_HOME || path.resolve(__dirname, "..");
////////////////////////////////////////////////////////////////////////////////

PicoEngine({
  compileAndLoadRuleset: RulesetLoader({
    rulesets_dir: path.resolve(pico_engine_home, "rulesets")
  }),
  db: {
    db: leveldown,
    location: path.join(pico_engine_home, "db")
  }
}, function(err, pe){
  if(err){
    throw err;
  }

  var logs = {};
  var logRID = "io.picolabs.logging";
  var logEntry = function(context,message){
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      episode.logs.push(timestamp+" "+message);
    } else {
      console.log("[ERROR]","no episode found for",eci);
    }
  };
  var logEpisode = function(pico_id,context,callback){
    var eci = context.eci;
    var episode = logs[eci];
    if (!episode) {
      console.log("[ERROR]","no episode found for",eci);
    }
    pe.db.getEntVar(pico_id,logRID,"status",function(e,status){
      if (status) {
        pe.db.getEntVar(pico_id,logRID,"logs",function(e,data){
          data[episode.key] = episode.logs;
          pe.db.putEntVar(pico_id,logRID,"logs",data,function(e){
            callback(delete logs[eci]);
          });
        });
      } else {
        callback(delete logs[eci]);
      }
    });
  };
  pe.emitter.on("episode_start", function(context){
    console.log("EPISODE_START",context);
    var eci = context.eci;
    var timestamp = (new Date()).toISOString();
    var episode = logs[eci];
    if (episode) {
      console.log("[ERROR]","episode already exists for",eci);
    } else {
      episode = {};
      episode.key = (
        timestamp + " - " + eci
          + " - " + ((context.event) ? context.event.eid : "query")
        ).replace(/[.]/g, "-");
      episode.logs = [];
      logs[eci] = episode;
    }
  });
  pe.emitter.on("klog", function(context, val, message){
    console.log("[KLOG]", message, val);
    logEntry(context,"[KLOG] "+message+" "+val);
  });
  pe.emitter.on("debug", function(context, message){
    console.log("[DEBUG]", context, message);
    var prefix = "";
    if (/^event rec..ved/.test(message)) {
      prefix = context.event.domain + "/" + context.event.type + " ";
    } else if (/^query rec..ved/.test(message)) {
      prefix = context.query.rid + "/" + context.query.name + " ";
    }
    logEntry(context,prefix+message);
  });
  pe.emitter.on("episode_stop", function(context){
    console.log("EPISODE_STOP",context);
    var callback = function(outcome){
      console.log("[EPISODE_REMOVED]",outcome);
    };
    logEpisode(context.pico_id,context,callback);
  });

  var app = express();
  app.use(express.static(path.resolve(__dirname, "..", "public")));
  app.use(bodyParser.json({type: "application/json"}));
  app.use(bodyParser.urlencoded({type: "application/x-www-form-urlencoded", extended: false}));

  var errResp = function(res, err){
    res.statusCode = err.statusCode || 500;
    res.end(err.message);
  };

  app.all("/sky/event/:eci/:eid/:domain/:type", function(req, res){
    var event = {
      eci: req.params.eci,
      eid: req.params.eid,
      domain: req.params.domain,
      type: req.params.type,
      attrs: _.assign({}, req.query, req.body)
    };
    pe.signalEvent(event, function(err, response){
      if(err) return errResp(res, err);
      res.json(response);
    });
  });

  app.all("/sky/cloud/:eci/:rid/:function", function(req, res){
    var query = {
      eci: req.params.eci,
      rid: req.params.rid,
      name: req.params["function"],
      args: _.assign({}, req.query, req.body)
    };
    pe.runQuery(query, function(err, data){
      if(err) return errResp(res, err);
      if(_.isFunction(data)){
        data(res);
      }else{
        res.json(data);
      }
    });
  });

  app.all("/api/db-dump", function(req, res){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);
      res.json(db_data);
    });
  });

  app.all("/old", function(req, res){
    pe.db.toObj(function(err, db_data){
      if(err) return errResp(res, err);

      var html = "";
      html += "\n\n";
      html += "
http://localhost:" + port + "
\n";
      html += "
Picos
\n";
      _.each(db_data.pico, function(pico){
        html += "
\n";
        html += "
"+pico.id+"
\n";
        html += "
\n";

        html += "
Channels
\n";
        html += "
\n";
        _.each(pico.channel, function(chan){
          var rm_link = "/api/pico/"+pico.id+"/rm-channel/"+chan.id;
          html += "
"+JSON.stringify(chan)+" del
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/new-channel\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"name\" placeholder=\"name...\">\n";
        html += "<input type=\"text\" name=\"type\" placeholder=\"type...\">\n";
        html += "<button type=\"submit\">add channel</button>\n";
        html += "</form>\n";

        html += "
Rulesets
\n";
        html += "
\n";
        _.each(pico.ruleset, function(d, rid){
          var rm_link = "/api/pico/"+pico.id+"/rm-ruleset/"+rid;
          html += "
"+rid+" del
\n";
          html += "
\n";
          _.each(_.get(db_data, ["pico", pico.id, rid, "vars"]),
                 function(v,k){
                   html += "
"+k+"="+JSON.stringify(v)+"
\n";
                 });
          html += "
\n";
        });
        html += "
\n";

        html += "<form action=\"/api/pico/"+pico.id+"/add-ruleset\" method=\"GET\">\n";
        html += "<input type=\"text\" name=\"rid\" placeholder=\"Ruleset id...\">\n";
        html += "<button type=\"submit\">add ruleset</button>\n";
        html += "</form>\n";

        html += "
\n";
        html += "
\n";
      });
      html += "
\n";
      html += "add pico\n";
      html += "
\n";
      html += "
Rulesets
\n";
      _.each(_.get(db_data, ["rulesets", "versions"]), function(versions, rid){
        var enabled_hash = _.get(db_data, ["rulesets", "enabled", rid, "hash"]);
        html += "
\n";
        html += "
"+rid+"
\n";
        _.each(versions, function(hashes, timestamp){
          _.each(hashes, function(is_there, hash){
            if(!is_there){
              return;
            }
            html += "
\n";
            html += timestamp + " | " + hash + " | ";
            if(hash === enabled_hash){
              html += "disable";
              html += " | ";
              if(pe.isInstalled(rid)){
                html += "uninstall";
              }else{
                html += "install";
              }
              var the_krl_src = _.get(db_data, ["rulesets", "krl", enabled_hash, "src"]);
              html += "
" + the_krl_src + "
\n";
            }else{
              html += "enable";
            }
            html += "
\n";
          });
        });
        html += "
\n";
      });
      html += "<form action=\"/api/ruleset/register\" method=\"GET\">\n";
      html += "<textarea name=\"src\"></textarea>\n";
      html += "<button type=\"submit\">register ruleset</button>\n";
      html += "</form>\n";
      html += "
\n";
      html += "raw database dump\n";
  //    html += "
\n" + JSON.stringify(db_data, undefined, 2) + "\n
\n";
      html += "\n\n";
      res.end(html);
    });
  });

  app.all("/api/owner-channel", function(req, res){
    pe.db.getFirstChannel(function(err, first_channel){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(first_channel, undefined, 2));
    });
  });

  app.all("/api/new-pico", function(req, res){
    pe.db.newPico({}, function(err, new_pico){
      if(err) return errResp(res, err);
      res.end(JSON.stringify(new_pico, undefined, 2));
    });
  });

  app.all("/api/rm-pico/:id", function(req, res){
    pe.db.removePico(req.params.id, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/pico/:id/new-channel", function(req, res){
    pe.db.newChannel({
      pico_id: req.params.id,
      name: req.query.name,
      type: req.query.type
    }, function(err, new_channel){
      if(err) return errResp(res, err);
      res.json(new_channel);
    });
  });

  app.all("/api/pico/:id/rm-channel/:eci", function(req, res){
    pe.db.removeChannel(req.params.id, req.params.eci, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/pico/:id/rm-ruleset/:rid", function(req, res){
    pe.db.removeRuleset(req.params.id, req.params.rid, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/pico/:id/add-ruleset", function(req, res){
    pe.db.addRuleset({pico_id: req.params.id, rid: req.query.rid}, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/compile", function(req, res){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);
    try{
      res.json({ code: compiler(src).code});
    }catch(err){
      res.json({ error: err.toString() });
    }
  });

  app.all("/api/ruleset/register", function(req, res){
    var src = _.get(url.parse(req.url, true), ["query", "src"]);

    pe.db.registerRuleset(src, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/enable/:hash", function(req, res){
    pe.db.enableRuleset(req.params.hash, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/install/:rid", function(req, res){
    pe.installRID(req.params.rid, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.all("/api/ruleset/disable/:rid", function(req, res){
    pe.db.disableRuleset(req.params.rid, function(err){
      if(err) return errResp(res, err);
      res.json({ok: true});
    });
  });

  app.listen(port, function () {
    console.log("http://localhost:" + port);
  });
});
<|endoftext|>


<commit_before>import path from 'path';
import fs from 'fs-extra';
import chalk from 'chalk';
import * as util from './util.js';
import * as resolve from './resolve.js';
import * as git from './git.js';
import flavio from './index.js';

/**
 *
 *
 */
async function clone( repo, options = {} ) {
	await util.readConfigFile( options.cwd );
	const repoUrl = util.parseRepositoryUrl( repo );
	// clone the repo first so it'll be on master, then checkout to the target object.
	// that way we can use the 'master' clone to list tags and so on so we can resolve the correct target without any temporary
	// clones
	let cwd = options.cwd;
	if ( !cwd ) {
		const gitname = util.getGitProjectNameFromUrl( repo );
		cwd = path.join( process.cwd(), gitname || 'project' );
	}
	if ( fs.existsSync( cwd ) ) {
		throw new Error( `Target directory ${cwd} already exists!` );
	}
	console.log( util.formatConsoleDependencyName( 'main' ), `Cloning main respository to ${chalk.yellow(cwd)}` );
	await git.clone( repoUrl.url, cwd, { master: true } );
	const targetObj = await resolve.getTargetFromRepoUrl( repo, cwd );
	try {
		await git.checkout( cwd, targetObj );
	} catch ( err ) {
		console.error( `Could not checkout target (${targetObj.branch || targetObj.tag || targetObj.commit}). Using 'master'...` );
	}
	console.log( util.formatConsoleDependencyName( 'main' ), `Clone complete, executing update...` );
	options.cwd = cwd;
	options.skipMain = true;
	await flavio.commands.update( options );
}

export default clone;
<commit_msg>Allow using current directory to clone to<commit_after>import path from 'path';
import fs from 'fs-extra';
import chalk from 'chalk';
import * as util from './util.js';
import * as resolve from './resolve.js';
import * as git from './git.js';
import flavio from './index.js';

/**
 *
 *
 */
async function clone( repo, options = {} ) {
	await util.readConfigFile( options.cwd );
	const repoUrl = util.parseRepositoryUrl( repo );
	// clone the repo first so it'll be on master, then checkout to the target object.
	// that way we can use the 'master' clone to list tags and so on so we can resolve the correct target without any temporary
	// clones
	let cwd = options.cwd;
	if ( !cwd ) {
		const gitname = util.getGitProjectNameFromUrl( repo );
		cwd = path.join( process.cwd(), gitname || 'project' );
	}
	if ( cwd !== '.' && fs.existsSync( cwd ) ) {
		throw new Error( `Target directory ${cwd} already exists!` );
	}
	console.log( util.formatConsoleDependencyName( 'main' ), `Cloning main respository to ${chalk.yellow(cwd)}` );
	await git.clone( repoUrl.url, cwd, { master: true } );
	const targetObj = await resolve.getTargetFromRepoUrl( repo, cwd );
	try {
		await git.checkout( cwd, targetObj );
	} catch ( err ) {
		console.error( `Could not checkout target (${targetObj.branch || targetObj.tag || targetObj.commit}). Using 'master'...` );
	}
	console.log( util.formatConsoleDependencyName( 'main' ), `Clone complete, executing update...` );
	options.cwd = cwd;
	options.skipMain = true;
	await flavio.commands.update( options );
}

export default clone;
<|endoftext|>