<commit_before>/**
 * Copyright (c) 2013, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
 * additional grant of patent rights can be found in the PATENTS file in
 * the same directory.
 */

(function(
  // Reliable reference to the global object (i.e. window in browsers).
  global,

  // Dummy constructor that we use as the .constructor property for
  // functions that return Generator objects.
  GeneratorFunction
) {
  var hasOwn = Object.prototype.hasOwnProperty;

  if (global.wrapGenerator) {
    return;
  }

  function wrapGenerator(innerFn, self, tryList) {
    return new Generator(innerFn, self || null, tryList || []);
  }

  global.wrapGenerator = wrapGenerator;
  if (typeof exports !== "undefined") {
    exports.wrapGenerator = wrapGenerator;
  }

  var GenStateSuspendedStart = "suspendedStart";
  var GenStateSuspendedYield = "suspendedYield";
  var GenStateExecuting = "executing";
  var GenStateCompleted = "completed";

  // Returning this object from the innerFn has the same effect as
  // breaking out of the dispatch switch statement.
  var ContinueSentinel = {};

  wrapGenerator.mark = function(genFun) {
    genFun.constructor = GeneratorFunction;
    return genFun;
  };

  // Ensure isGeneratorFunction works when Function#name not supported.
  if (GeneratorFunction.name !== "GeneratorFunction") {
    GeneratorFunction.name = "GeneratorFunction";
  }

  wrapGenerator.isGeneratorFunction = function(genFun) {
    var ctor = genFun && genFun.constructor;
    return ctor ? GeneratorFunction.name === ctor.name : false;
  };

  function Generator(innerFn, self, tryList) {
    var generator = this;
    var context = new Context(tryList);
    var state = GenStateSuspendedStart;

    function invoke(method, arg) {
      if (state === GenStateExecuting) {
        throw new Error("Generator is already running");
      }

      if (state === GenStateCompleted) {
        throw new Error("Generator has already finished");
      }

      while (true) {
        var delegate = context.delegate;
        if (delegate) {
          try {
            var info = delegate.generator[method](arg);

            // Delegate generator ran and handled its own exceptions so
            // regardless of what the method was, we continue as if it is
            // "next" with an undefined arg.
            method = "next";
            arg = void 0;

          } catch (uncaught) {
            context.delegate = null;

            // Like returning generator.throw(uncaught), but without the
            // overhead of an extra function call.
            method = "throw";
            arg = uncaught;

            continue;
          }

          if (info.done) {
            context[delegate.resultName] = info.value;
            context.next = delegate.nextLoc;
          } else {
            state = GenStateSuspendedYield;
            return info;
          }

          context.delegate = null;
        }

        if (method === "next") {
          if (state === GenStateSuspendedStart &&
              typeof arg !== "undefined") {
            // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
            throw new TypeError(
              "attempt to send " + JSON.stringify(arg) + " to newborn generator"
            );
          }

          if (state === GenStateSuspendedYield) {
            context.sent = arg;
          } else {
            delete context.sent;
          }

        } else if (method === "throw") {
          if (state === GenStateSuspendedStart) {
            state = GenStateCompleted;
            throw arg;
          }

          if (context.dispatchException(arg)) {
            // If the dispatched exception was caught by a catch block,
            // then let that catch block handle the exception normally.
            method = "next";
            arg = void 0;
          }
        }

        state = GenStateExecuting;

        try {
          var value = innerFn.call(self, context);

          // If an exception is thrown from innerFn, we leave state ===
          // GenStateExecuting and loop back for another invocation.
          state = context.done
            ? GenStateCompleted
            : GenStateSuspendedYield;

          var info = {
            value: value,
            done: context.done
          };

          if (value === ContinueSentinel) {
            if (context.delegate && method === "next") {
              // Deliberately forget the last sent value so that we don't
              // accidentally pass it on to the delegate.
              arg = void 0;
            }
          } else {
            return info;
          }

        } catch (thrown) {
          if (method === "next") {
            context.dispatchException(thrown);
          } else {
            arg = thrown;
          }
        }
      }
    }

    generator.next = invoke.bind(generator, "next");
    generator.throw = invoke.bind(generator, "throw");
  }

  Generator.prototype.toString = function() {
    return "[object Generator]";
  };

  function pushTryEntry(triple) {
    var entry = { tryLoc: triple[0] };

    if (1 in triple) {
      entry.catchLoc = triple[1];
    }

    if (2 in triple) {
      entry.finallyLoc = triple[2];
    }

    this.tryEntries.push(entry);
  }

  function resetTryEntry(entry, i) {
    var record = entry.completion || {};
    record.type = i === 0 ? "normal" : "return";
    delete record.arg;
    entry.completion = record;
  }

  function Context(tryList) {
    // The root entry object (effectively a try statement without a catch
    // or a finally block) gives us a place to store values thrown from
    // locations where there is no enclosing try statement.
    this.tryEntries = [{ tryLoc: "root" }];
    tryList.forEach(pushTryEntry, this);
    this.reset();
  }

  Context.prototype = {
    constructor: Context,

    reset: function() {
      this.prev = 0;
      this.next = 0;
      this.sent = void 0;
      this.done = false;
      this.delegate = null;

      this.tryEntries.forEach(resetTryEntry);

      // Pre-initialize at least 20 temporary variables to enable hidden
      // class optimizations for simple generators.
      for (var tempIndex = 0, tempName;
           hasOwn.call(this, tempName = "t" + tempIndex) || tempIndex < 20;
           ++tempIndex) {
        this[tempName] = null;
      }
    },

    stop: function() {
      this.done = true;

      var rootEntry = this.tryEntries[0];
      var rootRecord = rootEntry.completion;
      if (rootRecord.type === "throw") {
        throw rootRecord.arg;
      }

      return this.rval;
    },

    keys: function(object) {
      return Object.keys(object).reverse();
    },

    dispatchException: function(exception) {
      if (this.done) {
        throw exception;
      }

      var context = this;
      function handle(loc, caught) {
        record.type = "throw";
        record.arg = exception;
        context.next = loc;
        return !!caught;
      }

      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        var record = entry.completion;

        if (entry.tryLoc === "root") {
          // Exception thrown outside of any try block that could handle
          // it, so set the completion value of the entire function to
          // throw the exception.
          return handle("end");
        }

        if (entry.tryLoc <= this.prev) {
          var hasCatch = hasOwn.call(entry, "catchLoc");
          var hasFinally = hasOwn.call(entry, "finallyLoc");

          if (hasCatch && hasFinally) {
            if (this.prev < entry.catchLoc) {
              return handle(entry.catchLoc, true);
            } else if (this.prev < entry.finallyLoc) {
              return handle(entry.finallyLoc);
            }

          } else if (hasCatch) {
            if (this.prev < entry.catchLoc) {
              return handle(entry.catchLoc, true);
            }

          } else if (hasFinally) {
            if (this.prev < entry.finallyLoc) {
              return handle(entry.finallyLoc);
            }

          } else {
            throw new Error("try statement without catch or finally");
          }
        }
      }
    },

    _findFinallyEntry: function(finallyLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.tryLoc <= this.prev &&
            hasOwn.call(entry, "finallyLoc") && (
              entry.finallyLoc === finallyLoc ||
              this.prev < entry.finallyLoc)) {
          return entry;
        }
      }
    },

    abrupt: function(type, arg) {
      var entry = this._findFinallyEntry();
      var record = entry ? entry.completion : {};

      record.type = type;
      record.arg = arg;

      if (entry) {
        this.next = entry.finallyLoc;
      } else {
        this.complete(record);
      }

      return ContinueSentinel;
    },

    complete: function(record) {
      if (record.type === "throw") {
        throw record.arg;
      }

      if (record.type === "break" ||
          record.type === "continue") {
        this.next = record.arg;
      } else if (record.type === "return") {
        this.rval = record.arg;
        this.next = "end";
      }

      return ContinueSentinel;
    },

    finish: function(finallyLoc) {
      var entry = this._findFinallyEntry(finallyLoc);
      return this.complete(entry.completion);
    },

    "catch": function(tryLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.tryLoc === tryLoc) {
          var record = entry.completion;
          if (record.type === "throw") {
            var thrown = record.arg;
            resetTryEntry(entry, i);
          }
          return thrown;
        }
      }

      // The context.catch method must only be called with a location
      // argument that corresponds to a known catch block.
      throw new Error("illegal catch attempt");
    },

    delegateYield: function(generator, resultName, nextLoc) {
      this.delegate = {
        generator: generator,
        resultName: resultName,
        nextLoc: nextLoc
      };

      return ContinueSentinel;
    }
  };
}).apply(this, Function("return [this, function GeneratorFunction(){}]")());
<commit_msg>Copy latest runtime/dev.js from the master branch.<commit_after>/**
 * Copyright (c) 2013, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
 * additional grant of patent rights can be found in the PATENTS file in
 * the same directory.
 */

(function(
  // Reliable reference to the global object (i.e. window in browsers).
  global,

  // Dummy constructor that we use as the .constructor property for
  // functions that return Generator objects.
  GeneratorFunction
) {
  var hasOwn = Object.prototype.hasOwnProperty;

  if (global.wrapGenerator) {
    return;
  }

  function wrapGenerator(innerFn, self, tryList) {
    return new Generator(innerFn, self || null, tryList || []);
  }

  global.wrapGenerator = wrapGenerator;
  if (typeof exports !== "undefined") {
    exports.wrapGenerator = wrapGenerator;
  }

  var GenStateSuspendedStart = "suspendedStart";
  var GenStateSuspendedYield = "suspendedYield";
  var GenStateExecuting = "executing";
  var GenStateCompleted = "completed";

  // Returning this object from the innerFn has the same effect as
  // breaking out of the dispatch switch statement.
  var ContinueSentinel = {};

  wrapGenerator.mark = function(genFun) {
    genFun.constructor = GeneratorFunction;
    return genFun;
  };

  // Ensure isGeneratorFunction works when Function#name not supported.
  if (GeneratorFunction.name !== "GeneratorFunction") {
    GeneratorFunction.name = "GeneratorFunction";
  }

  wrapGenerator.isGeneratorFunction = function(genFun) {
    var ctor = genFun && genFun.constructor;
    return ctor ? GeneratorFunction.name === ctor.name : false;
  };

  function Generator(innerFn, self, tryList) {
    var generator = this;
    var context = new Context(tryList);
    var state = GenStateSuspendedStart;

    function invoke(method, arg) {
      if (state === GenStateExecuting) {
        throw new Error("Generator is already running");
      }

      if (state === GenStateCompleted) {
        throw new Error("Generator has already finished");
      }

      while (true) {
        var delegate = context.delegate;
        if (delegate) {
          try {
            var info = delegate.generator[method](arg);

            // Delegate generator ran and handled its own exceptions so
            // regardless of what the method was, we continue as if it is
            // "next" with an undefined arg.
            method = "next";
            arg = void 0;

          } catch (uncaught) {
            context.delegate = null;

            // Like returning generator.throw(uncaught), but without the
            // overhead of an extra function call.
            method = "throw";
            arg = uncaught;

            continue;
          }

          if (info.done) {
            context[delegate.resultName] = info.value;
            context.next = delegate.nextLoc;
          } else {
            state = GenStateSuspendedYield;
            return info;
          }

          context.delegate = null;
        }

        if (method === "next") {
          if (state === GenStateSuspendedStart &&
              typeof arg !== "undefined") {
            // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
            throw new TypeError(
              "attempt to send " + JSON.stringify(arg) + " to newborn generator"
            );
          }

          if (state === GenStateSuspendedYield) {
            context.sent = arg;
          } else {
            delete context.sent;
          }

        } else if (method === "throw") {
          if (state === GenStateSuspendedStart) {
            state = GenStateCompleted;
            throw arg;
          }

          if (context.dispatchException(arg)) {
            // If the dispatched exception was caught by a catch block,
            // then let that catch block handle the exception normally.
            method = "next";
            arg = void 0;
          }
        }

        state = GenStateExecuting;

        try {
          var value = innerFn.call(self, context);

          // If an exception is thrown from innerFn, we leave state ===
          // GenStateExecuting and loop back for another invocation.
          state = context.done
            ? GenStateCompleted
            : GenStateSuspendedYield;

          var info = {
            value: value,
            done: context.done
          };

          if (value === ContinueSentinel) {
            if (context.delegate && method === "next") {
              // Deliberately forget the last sent value so that we don't
              // accidentally pass it on to the delegate.
              arg = void 0;
            }
          } else {
            return info;
          }

        } catch (thrown) {
          if (method === "next") {
            context.dispatchException(thrown);
          } else {
            arg = thrown;
          }
        }
      }
    }

    generator.next = invoke.bind(generator, "next");
    generator.throw = invoke.bind(generator, "throw");
  }

  Generator.prototype.toString = function() {
    return "[object Generator]";
  };

  function pushTryEntry(triple) {
    var entry = { tryLoc: triple[0] };

    if (1 in triple) {
      entry.catchLoc = triple[1];
    }

    if (2 in triple) {
      entry.finallyLoc = triple[2];
    }

    this.tryEntries.push(entry);
  }

  function resetTryEntry(entry, i) {
    var record = entry.completion || {};
    record.type = i === 0 ? "normal" : "return";
    delete record.arg;
    entry.completion = record;
  }

  function Context(tryList) {
    // The root entry object (effectively a try statement without a catch
    // or a finally block) gives us a place to store values thrown from
    // locations where there is no enclosing try statement.
    this.tryEntries = [{ tryLoc: "root" }];
    tryList.forEach(pushTryEntry, this);
    this.reset();
  }

  Context.prototype = {
    constructor: Context,

    reset: function() {
      this.prev = 0;
      this.next = 0;
      this.sent = void 0;
      this.done = false;
      this.delegate = null;

      this.tryEntries.forEach(resetTryEntry);

      // Pre-initialize at least 20 temporary variables to enable hidden
      // class optimizations for simple generators.
      for (var tempIndex = 0, tempName;
           hasOwn.call(this, tempName = "t" + tempIndex) || tempIndex < 20;
           ++tempIndex) {
        this[tempName] = null;
      }
    },

    stop: function() {
      this.done = true;

      var rootEntry = this.tryEntries[0];
      var rootRecord = rootEntry.completion;
      if (rootRecord.type === "throw") {
        throw rootRecord.arg;
      }

      return this.rval;
    },

    keys: function(object) {
      var keys = [];
      for (var key in object) {
        keys.push(key);
      }
      keys.reverse();

      // The same { value, done } object can be reused between iterations,
      // because we control the generated code, and we know it doesn't
      // need a new object each time.
      var info = {};

      // Rather than returning an object with a next method, we keep
      // things simple and return the next function itself.
      return function next() {
        while (keys.length) {
          var key = keys.pop();
          if (key in object) {
            info.value = key;
            info.done = false;
            return info;
          }
        }

        info.done = true;
        return info;
      };
    },

    dispatchException: function(exception) {
      if (this.done) {
        throw exception;
      }

      var context = this;
      function handle(loc, caught) {
        record.type = "throw";
        record.arg = exception;
        context.next = loc;
        return !!caught;
      }

      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        var record = entry.completion;

        if (entry.tryLoc === "root") {
          // Exception thrown outside of any try block that could handle
          // it, so set the completion value of the entire function to
          // throw the exception.
          return handle("end");
        }

        if (entry.tryLoc <= this.prev) {
          var hasCatch = hasOwn.call(entry, "catchLoc");
          var hasFinally = hasOwn.call(entry, "finallyLoc");

          if (hasCatch && hasFinally) {
            if (this.prev < entry.catchLoc) {
              return handle(entry.catchLoc, true);
            } else if (this.prev < entry.finallyLoc) {
              return handle(entry.finallyLoc);
            }

          } else if (hasCatch) {
            if (this.prev < entry.catchLoc) {
              return handle(entry.catchLoc, true);
            }

          } else if (hasFinally) {
            if (this.prev < entry.finallyLoc) {
              return handle(entry.finallyLoc);
            }

          } else {
            throw new Error("try statement without catch or finally");
          }
        }
      }
    },

    _findFinallyEntry: function(finallyLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.tryLoc <= this.prev &&
            hasOwn.call(entry, "finallyLoc") && (
              entry.finallyLoc === finallyLoc ||
              this.prev < entry.finallyLoc)) {
          return entry;
        }
      }
    },

    abrupt: function(type, arg) {
      var entry = this._findFinallyEntry();
      var record = entry ? entry.completion : {};

      record.type = type;
      record.arg = arg;

      if (entry) {
        this.next = entry.finallyLoc;
      } else {
        this.complete(record);
      }

      return ContinueSentinel;
    },

    complete: function(record) {
      if (record.type === "throw") {
        throw record.arg;
      }

      if (record.type === "break" ||
          record.type === "continue") {
        this.next = record.arg;
      } else if (record.type === "return") {
        this.rval = record.arg;
        this.next = "end";
      }

      return ContinueSentinel;
    },

    finish: function(finallyLoc) {
      var entry = this._findFinallyEntry(finallyLoc);
      return this.complete(entry.completion);
    },

    "catch": function(tryLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.tryLoc === tryLoc) {
          var record = entry.completion;
          if (record.type === "throw") {
            var thrown = record.arg;
            resetTryEntry(entry, i);
          }
          return thrown;
        }
      }

      // The context.catch method must only be called with a location
      // argument that corresponds to a known catch block.
      throw new Error("illegal catch attempt");
    },

    delegateYield: function(generator, resultName, nextLoc) {
      this.delegate = {
        generator: generator,
        resultName: resultName,
        nextLoc: nextLoc
      };

      return ContinueSentinel;
    }
  };
}).apply(this, Function("return [this, function GeneratorFunction(){}]")());
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
!function(t){function e(t,e){return new n(t,e||null)}function n(t,e){function n(){f=h;do var n=t.call(e,u);while(n===s);return f=u.done?c:a,{value:n,done:u.done}}function i(){if(f===h)throw new Error("Generator is already running");if(f===c)throw new Error("Generator has already finished")}var l=this,u=new r,f=o;l.next=function(t){if(i(),u.delegate){var e=u.delegate.next(t);if(!e.done)return e;u.delegate=null}for(f===a&&(u.sent=t);;)try{return n()}catch(r){u.dispatchException(r)}},l.throw=function(t){if(i(),u.delegate){var e=u.delegate.throw(t);if(!e.done)return e;u.delegate=null}if(f===o)throw f=c,t;for(;;)try{return u.dispatchException(t),n()}catch(r){t=r}}}function r(){this.reset()}var i=Object.prototype.hasOwnProperty;if(!t.wrapGenerator){t.wrapGenerator=e,"undefined"!=typeof exports&&(exports.wrapGenerator=e);var o="suspendedStart",a="suspendedYield",h="executing",c="completed",s={};r.prototype={constructor:r,reset:function(){this.next=0,this.sent=void 0,this.tryStack=[],this.done=!1,this.delegate=null;for(var t,e=0;i.call(this,t="t"+e)||20>e;++e)this[t]=null},stop:function(){if(i.call(this,"thrown")){var t=this.thrown;throw delete this.thrown,t}return this.done=!0,this.rval},keys:function(t){return Object.keys(t).reverse()},pushTry:function(t,e,n){e&&this.tryStack.push({finallyLoc:e,finallyTempVar:n}),t&&this.tryStack.push({catchLoc:t})},popCatch:function(t){var e=this.tryStack.length-1,n=this.tryStack[e];n&&n.catchLoc===t&&(this.tryStack.length=e)},popFinally:function(t){var e=this.tryStack.length-1,n=this.tryStack[e];n&&i.call(n,"finallyLoc")||(n=this.tryStack[--e]),n&&n.finallyLoc===t&&(this.tryStack.length=e)},dispatchException:function(t){var e,n=[],r=!1;if(this.done)throw t;for(var i=this.tryStack.length-1;i>=0;--i){if(e=this.tryStack[i],e.catchLoc){this.thrown=t,this.next=e.catchLoc,r=!0;break}e.finallyLoc&&(n.push(e),r=!0)}if(!r)throw t;for(;e=n.pop();)this[e.finallyTempVar]=this.next,this.next=e.finallyLoc},delegateYield:function(t,e){this.next=e;var n=t.next(this.sent);return n.done?(this.delegate=null,s):(this.delegate=t,n.value)}}}}(Function("return this")());<commit_msg>Regenerate runtime/min.js to incorporate fix for #44.<commit_after>/**
 * Copyright (c) 2013, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
!function(t){function e(t,e){return new n(t,e||null)}function n(t,e){function n(){f=h;do var n=t.call(e,u);while(n===s);return f=u.done?c:a,{value:n,done:u.done}}function i(){if(f===h)throw new Error("Generator is already running");if(f===c)throw new Error("Generator has already finished")}var l=this,u=new r,f=o;l.next=function(t){if(i(),u.delegate){var e=u.delegate.next(t);if(!e.done)return e;u.delegate=null}for(f===a&&(u.sent=t);;)try{return n()}catch(r){u.dispatchException(r)}},l.throw=function(t){if(i(),u.delegate){var e=u.delegate.throw(t);if(!e.done)return e;u.delegate=null}if(f===o)throw f=c,t;for(;;){u.dispatchException(t);try{return n()}catch(r){t=r}}}}function r(){this.reset()}var i=Object.prototype.hasOwnProperty;if(!t.wrapGenerator){t.wrapGenerator=e,"undefined"!=typeof exports&&(exports.wrapGenerator=e);var o="suspendedStart",a="suspendedYield",h="executing",c="completed",s={};r.prototype={constructor:r,reset:function(){this.next=0,this.sent=void 0,this.tryStack=[],this.done=!1,this.delegate=null;for(var t,e=0;i.call(this,t="t"+e)||20>e;++e)this[t]=null},stop:function(){if(i.call(this,"thrown")){var t=this.thrown;throw delete this.thrown,t}return this.done=!0,this.rval},keys:function(t){return Object.keys(t).reverse()},pushTry:function(t,e,n){e&&this.tryStack.push({finallyLoc:e,finallyTempVar:n}),t&&this.tryStack.push({catchLoc:t})},popCatch:function(t){var e=this.tryStack.length-1,n=this.tryStack[e];n&&n.catchLoc===t&&(this.tryStack.length=e)},popFinally:function(t){var e=this.tryStack.length-1,n=this.tryStack[e];n&&i.call(n,"finallyLoc")||(n=this.tryStack[--e]),n&&n.finallyLoc===t&&(this.tryStack.length=e)},dispatchException:function(t){var e,n=[],r=!1;if(this.done)throw t;for(var i=this.tryStack.length-1;i>=0;--i){if(e=this.tryStack[i],e.catchLoc){this.thrown=t,this.next=e.catchLoc,r=!0;break}e.finallyLoc&&(n.push(e),r=!0)}if(!r)throw t;for(;e=n.pop();)this[e.finallyTempVar]=this.next,this.next=e.finallyLoc},delegateYield:function(t,e){this.next=e;var n=t.next(this.sent);return n.done?(this.delegate=null,s):(this.delegate=t,n.value)}}}}(Function("return this")());<|endoftext|>


<commit_before>/**
 * MediaKeys namespace.
 */
if (typeof MediaKeys == "undefined") var MediaKeys = {};

MediaKeys.playButton = "//*[@data-qa='play_button' or @class='playButton' and not(contains(@style,'none'))]";
MediaKeys.pauseButton = "//*[@data-qa='pause_button' or @class='pauseButton' and not(contains(@style,'none'))]";
MediaKeys.previousButton = "//*[@data-qa='replay_button' or @class='skipButton']";
MediaKeys.skipButton = "//*[@data-qa='skip_button']";
MediaKeys.trackInfoContainer = "//*[contains(@data-reactid,'NowPlaying') or @id='trackInfoContainer']";
MediaKeys.trackInfo = "//*[class='nowPlayingTopInfo__current' or contains(@class,'trackData')]";<commit_msg>missed skipButton legacy support for Pandora<commit_after>/**
 * MediaKeys namespace.
 */
if (typeof MediaKeys == "undefined") var MediaKeys = {};

MediaKeys.playButton = "//*[@data-qa='play_button' or @class='playButton' and not(contains(@style,'none'))]";
MediaKeys.pauseButton = "//*[@data-qa='pause_button' or @class='pauseButton' and not(contains(@style,'none'))]";
MediaKeys.previousButton = "//*[@data-qa='replay_button' or @class='skipButton']";
MediaKeys.skipButton = "//*[@data-qa='skip_button' or @class='skipButton']";
MediaKeys.trackInfoContainer = "//*[contains(@data-reactid,'NowPlaying') or @id='trackInfoContainer']";
MediaKeys.trackInfo = "//*[class='nowPlayingTopInfo__current' or contains(@class,'trackData')]";<|endoftext|>


<commit_before>import restler{spaceForNamedImports} from 'restler'
import config${spaceForNamedImports} from '../config'
import * as commandsHelper${spaceForNamedImports} from '../utils/commands'
import { read, write } from '../utils/files'

const BASE_API_ADDRESS = 'http://mymemory.translated.net/api/get';

function unescapeHtml(text) {
  return text
      .replace("&", "&")
      .replace("<", "<")
      .replace(">", ">")
      .replace(""", '"')
      .replace("'", "'")
      .replace("'", "'");
}

function changeUserData(userId, data) {
  let users = read('users');

  // Find user in store
  let user = users.findIndex(tmpUser => {
    return tmpUser.id == userId;
  });

  // If it's already there!
  if (user !== -1) {
    users[user] = Object.assign(users[user], data);
  } else {
    users.push(Object.assign({id: userId}, data));
  }
  write('users', users);
}

function swapLang(userId) {
  let users = read('users');

  // Find user in store
  let user = users.findIndex(tmpUser => {
    return tmpUser.id == userId;
  });

  // If it's already there!
  if (user !== -1) {
    let src = users[user].source;
    let dst = users[user].destination;
    users[user].source = dst;
    users[user].destination = src;
    write('users', users);
    return `Source and destination languages swapped!
Source: ${dst}
Destination: ${src}`;
  }

  return 'You must set languages first.';
}

export default class Translate {
  static tl(params) {

    let userId = params.userId,
        text = params.params,
        sourceLang = undefined,
        destinationLang = undefined;

    // read src,dest from params
    let lang = text.split(' ').shift();
    if (lang.indexOf(':')) {
      let tmp = lang.split(':');
      if (tmp.length === 2) {
        sourceLang = tmp[0];
        destinationLang = tmp[1];
        text = text.replace(lang + ' ', '');
      }
    }

    if (!destinationLang) {
      // read user config
      let users = read('users');

      let user = users.find(tmpUser => {
        return tmpUser.id === userId;
      });

      // default
      if (!user) {
        sourceLang = 'en';
        destinationLang = 'fa';
      } else {
        sourceLang = user.source;
        destinationLang = user.destination;
      }

    }

    let query = {
      q: text,
      mt: 1,
      langpair: `${sourceLang}|${destinationLang}`
    }
    //console.log(query);

    return new Promise((res, rej) => {
      restler.get(BASE_API_ADDRESS, {
        query: query
      }).on('complete', response => {
        if (response instanceof Error) {
          return rej(response);
        }
        //console.log(response.matches);
        let tl = 'Nothing found. :(';
        let maxQuality = 0;
        let maxMatch = 0;
        if (!response.matches) {
          return rej('Oops!');
        }
        for (let i = 0, max = response.matches.length; i < max; i++) {
          if (response.matches[i].match > maxMatch && response.matches[i].quality > maxQuality) {
            maxQuality = response.matches[i].quality;
            maxMatch = response.matches[i].match;
            tl = response.matches[i].translation;
          }
          if (response.matches[i]['created-by'] === 'MT!' && response.matches[i].match > maxMatch) {
            tl = response.matches[i].translation;
            break;
          }
        }
        return res(unescapeHtml(tl));
      });
    })
  }

  static src(params) {
    let userId = params.userId,
        lang   = params.params;
    changeUserData(userId, {source: lang.trim()});
    return new Promise((res, rej) => {
      res(`Source language changed to ${lang}!`);
    });
  }

  static dest(params) {
    let userId = params.userId,
        lang   = params.params;
    changeUserData(userId, {destination: lang.trim()});
    return new Promise((res, rej) => {
      res(`Destination language changed to ${lang}!`);
    });
  }

  static swp(params) {
    let userId = params.userId;
    return new Promise((res, rej) => {
      res(swapLang(userId));
    });
  }

  static start(params) {
    return this.help(params);
  }

  static help(params) {
    let command = params.params;
    return new Promise((res, rej) => {
      res(commandsHelper.help(command));
    });
  }

  static feedback(params) {
    let user = params.user,
        bot = params.bot,
        message = params.params;
    bot.sendMessage(config.masterId, `New feedback from
${user.first_name || ''} ${user.last_name || ''} @${user.username || ''} <#${user.id}>
${message}`);
    return new Promise((res, rej) => {
      res('Thank you so much for giving us your feedback! ^^');
    })
  }

}
<commit_msg>remove some atom plugin code that ruined the imports<commit_after>import restler from 'restler'
import config from '../config'
import * as commandsHelper from '../utils/commands'
import { read, write } from '../utils/files'

const BASE_API_ADDRESS = 'http://mymemory.translated.net/api/get';

function unescapeHtml(text) {
  return text
      .replace("&", "&")
      .replace("<", "<")
      .replace(">", ">")
      .replace(""", '"')
      .replace("'", "'")
      .replace("'", "'");
}

function changeUserData(userId, data) {
  let users = read('users');

  // Find user in store
  let user = users.findIndex(tmpUser => {
    return tmpUser.id == userId;
  });

  // If it's already there!
  if (user !== -1) {
    users[user] = Object.assign(users[user], data);
  } else {
    users.push(Object.assign({id: userId}, data));
  }
  write('users', users);
}

function swapLang(userId) {
  let users = read('users');

  // Find user in store
  let user = users.findIndex(tmpUser => {
    return tmpUser.id == userId;
  });

  // If it's already there!
  if (user !== -1) {
    let src = users[user].source;
    let dst = users[user].destination;
    users[user].source = dst;
    users[user].destination = src;
    write('users', users);
    return `Source and destination languages swapped!
Source: ${dst}
Destination: ${src}`;
  }

  return 'You must set languages first.';
}

export default class Translate {
  static tl(params) {

    let userId = params.userId,
        text = params.params,
        sourceLang = undefined,
        destinationLang = undefined;

    // read src,dest from params
    let lang = text.split(' ').shift();
    if (lang.indexOf(':')) {
      let tmp = lang.split(':');
      if (tmp.length === 2) {
        sourceLang = tmp[0];
        destinationLang = tmp[1];
        text = text.replace(lang + ' ', '');
      }
    }

    if (!destinationLang) {
      // read user config
      let users = read('users');

      let user = users.find(tmpUser => {
        return tmpUser.id === userId;
      });

      // default
      if (!user) {
        sourceLang = 'en';
        destinationLang = 'fa';
      } else {
        sourceLang = user.source;
        destinationLang = user.destination;
      }

    }

    let query = {
      q: text,
      mt: 1,
      langpair: `${sourceLang}|${destinationLang}`
    }
    //console.log(query);

    return new Promise((res, rej) => {
      restler.get(BASE_API_ADDRESS, {
        query: query
      }).on('complete', response => {
        if (response instanceof Error) {
          return rej(response);
        }
        //console.log(response.matches);
        let tl = 'Nothing found. :(';
        let maxQuality = 0;
        let maxMatch = 0;
        if (!response.matches) {
          return rej('Oops!');
        }
        for (let i = 0, max = response.matches.length; i < max; i++) {
          if (response.matches[i].match > maxMatch && response.matches[i].quality > maxQuality) {
            maxQuality = response.matches[i].quality;
            maxMatch = response.matches[i].match;
            tl = response.matches[i].translation;
          }
          if (response.matches[i]['created-by'] === 'MT!' && response.matches[i].match > maxMatch) {
            tl = response.matches[i].translation;
            break;
          }
        }
        return res(unescapeHtml(tl));
      });
    })
  }

  static src(params) {
    let userId = params.userId,
        lang   = params.params;
    changeUserData(userId, {source: lang.trim()});
    return new Promise((res, rej) => {
      res(`Source language changed to ${lang}!`);
    });
  }

  static dest(params) {
    let userId = params.userId,
        lang   = params.params;
    changeUserData(userId, {destination: lang.trim()});
    return new Promise((res, rej) => {
      res(`Destination language changed to ${lang}!`);
    });
  }

  static swp(params) {
    let userId = params.userId;
    return new Promise((res, rej) => {
      res(swapLang(userId));
    });
  }

  static start(params) {
    return this.help(params);
  }

  static help(params) {
    let command = params.params;
    return new Promise((res, rej) => {
      res(commandsHelper.help(command));
    });
  }

  static feedback(params) {
    let user = params.user,
        bot = params.bot,
        message = params.params;
    bot.sendMessage(config.masterId, `New feedback from
${user.first_name || ''} ${user.last_name || ''} @${user.username || ''} <#${user.id}>
${message}`);
    return new Promise((res, rej) => {
      res('Thank you so much for giving us your feedback! ^^');
    })
  }

}
<|endoftext|>


<commit_before>'use strict';
const l10nFile = __dirname + '/../l10n/commands/inventory.yml';
const l10n = require('../src/l10n')(l10nFile);
const _    = require('../src/helpers');
const util = require('util');

exports.command = (rooms, items, players, npcs, Commands) => {
  return (args, player) => {
    const inventory   = player.getInventory();
    const equipped    = player.getEquipped();
    const equipment   = new Map();

    for (let slot in equipped) {
      equipment.set(slot, items.get(equipped[slot]));
    }

    if (!equipment.size) {
      return player.warn(`You're stark naked, with nothing to your name...`);
    }

    player.say(
      `<bold>Your inventory:</bold>
      `);

    const displayListItem = item => player.say(`<cyan>${_.leftPad(nestingLevel)} - ${item.getShortDesc()}</cyan>`)

    for (let [slot, item] of equipment) {
      player.say(`<magenta><${slot}></magenta> <bold>${item.getShortDesc()}</bold> <cyan>weight: ${item.getWeight()} gravets</cyan>`);
      if (item.isContainer()) {
        displayContainer(item, 0);
      }
    }

    function displayContainerContents(item, nestingLevel) {
      const contents = container.getInventory();
        if (!contents.length) { return; }

        player.say("<bold>CONTENTS: </bold>");
        contents.forEach(item => item.isContainer() ?
          displayContainerContents(item, nestingLevel + 1) :
          displayListItem(item, nestingLevel));
    }

  };
};
<commit_msg>Dynamically pad inventory display so weight stuff lines up.<commit_after>'use strict';
const l10nFile = __dirname + '/../l10n/commands/inventory.yml';
const l10n = require('../src/l10n')(l10nFile);
const _    = require('../src/helpers');
const util = require('util');

exports.command = (rooms, items, players, npcs, Commands) => {
  return (args, player) => {
    const inventory   = player.getInventory();
    const equipped    = player.getEquipped();
    const equipment   = new Map();

    let longest = 0;

    for (let slot in equipped) {
      const item     = items.get(equipped[slot]);
      const name     = item.getShortDesc();
      const weight   = item.getWeight();
      const contents = item.isContainer() ? item.getInventory() : false;
      equipment.set(slot, { name, weight, contents });

      longest = item.getShortDesc().length > longest ?
        item.getShortDesc().length :
        longest;
    }

    if (!equipment.size) {
      return player.warn(`You're stark naked, with nothing to your name...`);
    }

    player.say(
      `<bold>Your inventory:</bold>
      `);

    const displayListItem = item => player.say(`<cyan>${_.leftPad(nestingLevel)} - ${item.getShortDesc()}</cyan>`)

    for (let [slot, details] of equipment) {
      const details = { name, weight, contents };
      const padding = _.leftPad(longest - name.length);
      player.say(`<magenta><${slot}></magenta> <bold>${name}</bold> ${padding}<cyan>weight: ${weight} gravets</cyan>`);
      if (contents) {
        displayContainer(contents, 0);
      }
    }

    function displayContainerContents(item, nestingLevel) {
      const contents = container.getInventory();
        if (!contents.length) { return; }

        player.say("<bold>CONTENTS: </bold>");
        contents.forEach(item => item.isContainer() ?
          displayContainerContents(item, nestingLevel + 1) :
          displayListItem(item, nestingLevel));
    }

  };
};
<|endoftext|>


<commit_before>module.exports.name = 'languages';

module.exports.alias = [
  'lang'
];

module.exports.isAllowed = (message, server) => {
  return server.guild.id == '189571157446492161';
};

module.exports.help = '`,lang [ minMessage=100 ] `';

const NE = '197100137665921024';
const NJ = '196765998706196480';
const FE = '241997079168155649';
const FJ = '270391106955509770';
const OL = '248982130246418433';

module.exports.command = async (message, content, bot, server) => {
  let min = parseInt(content);
  if (min !== 0 && !min) {
    min = 100;
  }
  const users = server.users;
  const langs = [0, 0, 0, 0, 0];
  for (let user in users) {
    let res = users[user].totalStats();
    if (res >= min) {
      const mem = server.guild.member(user);
      if (mem) {
        const roles = mem.roles;
        if (roles.has(NE)) ++langs[0];
        if (roles.has(NJ)) ++langs[1];
        if (roles.has(FE)) ++langs[2];
        if (roles.has(FJ)) ++langs[3];
        if (roles.has(OL)) ++langs[4];
      }
    }
  }
  message.channel.send(`Out of people who have sent more than ${min} messages,\n${langs[0]} are Native English\n${langs[1]} are Native Japanese\n${langs[2]} are Fluent English\n${langs[3]} are Fluent Japanese\n${langs[4]} are Other Language`);
};
<commit_msg>wording<commit_after>module.exports.name = 'languages';

module.exports.alias = [
  'lang'
];

module.exports.isAllowed = (message, server) => {
  return server.guild.id == '189571157446492161';
};

module.exports.help = '`,lang [ minMessage=100 ] `';

const NE = '197100137665921024';
const NJ = '196765998706196480';
const FE = '241997079168155649';
const FJ = '270391106955509770';
const OL = '248982130246418433';

module.exports.command = async (message, content, bot, server) => {
  let min = parseInt(content);
  if (min !== 0 && !min) {
    min = 100;
  }
  const users = server.users;
  const langs = [0, 0, 0, 0, 0];
  for (let user in users) {
    let res = users[user].totalStats();
    if (res >= min) {
      const mem = server.guild.member(user);
      if (mem) {
        const roles = mem.roles;
        if (roles.has(NE)) ++langs[0];
        if (roles.has(NJ)) ++langs[1];
        if (roles.has(FE)) ++langs[2];
        if (roles.has(FJ)) ++langs[3];
        if (roles.has(OL)) ++langs[4];
      }
    }
  }
  message.channel.send(`Out of people who have sent more than ${min} messages in the past 30 days,\n${langs[0]} are Native English\n${langs[1]} are Native Japanese\n${langs[2]} are Fluent English\n${langs[3]} are Fluent Japanese\n${langs[4]} are Other Language`);
};
<|endoftext|>


<commit_before>import BulkMessage from 'telegram-api/types/BulkMessage';
import Message from 'telegram-api/types/Message';

import FeedParser from 'feedparser';
import request from 'request';

import {read, write} from '../utils/files';

export default function subscribe(bot) {
  const users = read('users');
  const feeds = read('feeds');
  const time = read('time');

  const refresh = () => {
    return new Promise((resolve, reject) => {
      for (let feed of feeds) {
        const req = request(feed.url);
        req.setHeader('user-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10)');
        req.setHeader('accept', 'text/html,application/xhtml+xml');

        const parser = new FeedParser();

        req.on('response', res => res.pipe(parser));
        req.on('error', reject);

        let posts = [];

        console.log(time.time);

        parser.on('data', function listener(post) {
          const date = new Date(post.date);

          console.log(date);

          if (date > time.time) {
            parser.removeListener('data', listener);

            write('time', {time: new Date()});

            resolve(posts);
            return;
          }
          posts.push(post);
        });

        parser.on('error', reject);
      }
    });
  };

  const cb = function(posts) {
    for (let post of posts) {
      const msg = new BulkMessage().text(post.title + '\n' + post.link)
                                   .to(users);
      bot.send(msg);
    }
  };

  refresh().then(cb);
  setInterval(refresh.bind(null, cb), 1000 * 60 * 5);

  const success = new Message().text('You\'ve been successfuly subscribed!');
  const duplicate = new Message().text('You are already subscribed!');
  bot.command('subscribe', message => {
    if (users.indexOf(message.chat.id) > -1) {
      bot.send(duplicate.to(message.chat.id));
      return;
    }

    users.push(message.chat.id);
    write('users', users);

    bot.send(success.to(message.chat.id));
  });

  const no = new Message().text('You are not subscribed at all!');
  const unsubscribed = new Message().text('You\'ve been unsubscribed.');
  bot.command('unsubscribe', message => {
    const index = users.indexOf(message.chat.id);
    if (index === -1) {
      bot.send(no.to(message.chat.id));
    } else {
      users.splice(index, 1);
      write('users', users);
      bot.send(unsubscribed.to(message.chat.id));
    }
  });
}
<commit_msg>Convert to date after reading time<commit_after>import BulkMessage from 'telegram-api/types/BulkMessage';
import Message from 'telegram-api/types/Message';

import FeedParser from 'feedparser';
import request from 'request';

import {read, write} from '../utils/files';

export default function subscribe(bot) {
  const users = read('users');
  const feeds = read('feeds');
  const time = read('time');

  time.time = new Date(time);

  const refresh = () => {
    return new Promise((resolve, reject) => {
      for (let feed of feeds) {
        const req = request(feed.url);
        req.setHeader('user-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10)');
        req.setHeader('accept', 'text/html,application/xhtml+xml');

        const parser = new FeedParser();

        req.on('response', res => res.pipe(parser));
        req.on('error', reject);

        let posts = [];

        console.log(time.time);

        parser.on('data', function listener(post) {
          const date = new Date(post.date);

          console.log(date);

          if (date > time.time) {
            parser.removeListener('data', listener);

            write('time', {time: new Date()});

            resolve(posts);
            return;
          }
          posts.push(post);
        });

        parser.on('error', reject);
      }
    });
  };

  const cb = function(posts) {
    for (let post of posts) {
      const msg = new BulkMessage().text(post.title + '\n' + post.link)
                                   .to(users);
      bot.send(msg);
    }
  };

  refresh().then(cb);
  setInterval(refresh.bind(null, cb), 1000 * 60 * 5);

  const success = new Message().text('You\'ve been successfuly subscribed!');
  const duplicate = new Message().text('You are already subscribed!');
  bot.command('subscribe', message => {
    if (users.indexOf(message.chat.id) > -1) {
      bot.send(duplicate.to(message.chat.id));
      return;
    }

    users.push(message.chat.id);
    write('users', users);

    bot.send(success.to(message.chat.id));
  });

  const no = new Message().text('You are not subscribed at all!');
  const unsubscribed = new Message().text('You\'ve been unsubscribed.');
  bot.command('unsubscribe', message => {
    const index = users.indexOf(message.chat.id);
    if (index === -1) {
      bot.send(no.to(message.chat.id));
    } else {
      users.splice(index, 1);
      write('users', users);
      bot.send(unsubscribed.to(message.chat.id));
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var _ = require('lodash');
var glob = require('glob');
var fs = require('fs');
var util = require('util');

function SassUnpack(options) {

  this.filepath = path.resolve(options.src);

  if (fs.lstatSync(this.filepath).isFile()) {

    options = processOptions(options);

    this.dest = options.dest || false ;
    this.dir = path.resolve(path.dirname(this.filepath));
    this.loadPaths = options.loadPaths || [];
    this.extensions = options.extensions || [];
    this.index = [];
    this.link = [];

  }
};

SassUnpack.prototype.unpackTo = function(options) {

	var toPath = path.resolve(options.dest);
	var urlRoot = options.urlRoot;

  var SassMap = require('sass-map');

  var mapSass =  new SassMap(this.filepath);

  fs.writeFileSync(path.resolve('./') + '/dist/mapsass.json', util.inspect(mapSass, { showHidden: true, depth: null }));

  var files = this.cutSourceFileWithMap(this.filepath, mapSass);

  this.dir = path.resolve(toPath);

  return this.generateFiles(files, mapSass, this.dir, urlRoot);

};

SassUnpack.prototype.cutSourceFileWithMap = function(srcFilePath, mapSass) {

  var result = {
    main: {
      source: '',
    },
    packages: []
  };

  var content = fs.readFileSync(srcFilePath, 'utf8');
  content = content.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');

  var position = 0;
  var regImport = /\@import [\'|\"]([a-zA-Z0-9-\._\/]+)[\'|\"]/;

  var cssClass = [];
  var packages = [];
  var source = [];

  		 var loadPaths = _([this.dir]).concat(this.loadPaths).filter().uniq().value();

  content.split('\n').forEach(function(line, iLine) {

    line = line.trim();
    var matchImport = regImport.exec(line);

    if (matchImport) {

      var importFilePath = resolveSassPath(matchImport[1].trim(), loadPaths, this.extensions);

      if (importFilePath) {
        var importLine = '@import \'' + importFilePath + '\';';

        var file = {
          line: importLine,
          index: iLine,
          path:  importFilePath,
          css: cssClass.slice(0, cssClass.length)
        };

        if (mapSass.index[this.filepath].dependencies.indexOf(importFilePath) >= 0) {
          source.push(importLine);
        } else {
          packages.push(file);
        }
      }else {
        throw new Error('Impossible to resolve Sass Path  in ' + this.filepath + ' - line : ' + iLine + ' \n ' + line);
      }

    } else {
      source.push(line);
    }

    var open = line.match(/\{/g) || [];
    var close = line.match(/\}/g) || [];
    position += open.length;
    position -= close.length;

    if (position != cssClass.length) {
      if (position > cssClass.length) {
        cssClass.push(line);
      } else {
        cssClass.pop();
      }
    }
  }.bind(this));

  result.main.source = source.join('\n');
  result.packages = packages;

  return result;

};

function addToIndex(mapIndex, filepath, link) {
  if (mapIndex[filepath] === undefined) {
    mapIndex[filepath] = [];
  }

  if (mapIndex[filepath].indexOf(link) == -1) {
    mapIndex[filepath].push(link);
  }
}

SassUnpack.prototype.generateFiles = function(files, mapSass, toPath, urlRoot) {

  var mkdirp = require('mkdirp');

  var mapIndex = [];
  var indexFile = 0;
  var map = [];

  mkdirp.sync(toPath + '/dev/scss/');
  mkdirp.sync(toPath + '/dev/css/');

  var devFilePath = toPath + '/dev/scss/index.scss';
  var devFileCSSUrl = urlRoot+'/dev/css/index.css';

  map.push({
    file: devFilePath,
    href: devFileCSSUrl
  });

  fs.writeFileSync(devFilePath, files.main.source);

  files.packages.forEach(function(file) {

    //console.log(mapSass[file.path]);
    //

    file = _.assign(mapSass.index[file.path], file);

    var fileName =  file.path.replace(path.resolve('./')+ '/', '')
                            .replace(/\//g, '-')
                            .replace(path.extname(file.path),'');

    var devFileCSSUrl = urlRoot + '/dev/css/' + fileName + '.css';
    var devFilePath = toPath + '/dev/scss/' + fileName + '.scss';

    addToIndex(mapIndex, file.path, devFilePath);

    var fileContent = [];

    file.dependencies.forEach(function(item) {
      if (file.path !== item) {
      	addToIndex(mapIndex, item, devFilePath);
        fileContent.push('@import \'' + item + '\';');
      }
    });

    file.imports.forEach(function(item) {
      addToIndex(mapIndex, item, devFilePath);
    });

    file.extended.forEach(function(item) {
       if (file.path !== item) {
      	addToIndex(mapIndex, item, devFilePath);
        fileContent.push('@import \'' + item + '\';');
      }
    }.bind(this));

    fileContent.push('/* unsass */');

    var cssContent = [];
    file.css.forEach(function(cssClass) {
      cssContent.push(cssClass);
    });

    cssContent.push(file.line);

    file.css.forEach(function(cssClass) {
      cssContent.push('}');
    });

    fileContent.push(cssContent.join('\n'));

    fs.writeFileSync(devFilePath, fileContent.join('\n'));

    map.push({
      file: devFilePath,
      href: devFileCSSUrl
    });

  }.bind(this));

  var buf  = [];

  for (var i in mapIndex) {
    buf.push({
      index: i,
      links: _.uniq(mapIndex[i])
    });
  }

  return {
    href: map,
    sass: buf
  };
}

// resolve a sass module to a path

function resolveSassPath(sassPath, loadPaths, extensions) {
  // trim sass file extensions
  var re = new RegExp('(\.(' + extensions.join('|') + '))$', 'i');
  var sassPathName = sassPath.replace(re, '');

  // check all load paths
  //

  var i, j, length = loadPaths.length,
	scssPath, partialPath;
  for (i = 0; i < length; i++) {
    for (j = 0; j < extensions.length; j++) {
      scssPath = path.normalize(loadPaths[i] + '/' + sassPathName + '.' + extensions[j]);
      if (fs.existsSync(scssPath)) {
        return scssPath;
      }
    }

    // special case for _partials
    for (j = 0; j < extensions.length; j++) {
      scssPath = path.normalize(loadPaths[i] + '/' + sassPathName + '.' + extensions[j]);
      partialPath = path.join(path.dirname(scssPath), '_' + path.basename(scssPath));
      if (fs.existsSync(partialPath)) {
        return partialPath;
      }
    }
  }

  // File to import not found or unreadable so we assume this is a custom import
  return false;
}

function processOptions(options) {
  return _.assign({
    loadPaths: [process.cwd()],
    extensions: ['scss', 'css'],
  }, options);
}

module.exports =  SassUnpack;

<commit_msg>remove debug code<commit_after>'use strict';

var path = require('path');
var _ = require('lodash');
var glob = require('glob');
var fs = require('fs');
var util = require('util');

function SassUnpack(options) {

  this.filepath = path.resolve(options.src);

  if (fs.lstatSync(this.filepath).isFile()) {

    options = processOptions(options);

    this.dest = options.dest || false ;
    this.dir = path.resolve(path.dirname(this.filepath));
    this.loadPaths = options.loadPaths || [];
    this.extensions = options.extensions || [];
    this.index = [];
    this.link = [];

  }
};

SassUnpack.prototype.unpackTo = function(options) {

	var toPath = path.resolve(options.dest);
	var urlRoot = options.urlRoot;

  var SassMap = require('sass-map');

  var mapSass =  new SassMap(this.filepath);

  var files = this.cutSourceFileWithMap(this.filepath, mapSass);

  this.dir = path.resolve(toPath);

  return this.generateFiles(files, mapSass, this.dir, urlRoot);

};

SassUnpack.prototype.cutSourceFileWithMap = function(srcFilePath, mapSass) {

  var result = {
    main: {
      source: '',
    },
    packages: []
  };

  var content = fs.readFileSync(srcFilePath, 'utf8');
  content = content.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');

  var position = 0;
  var regImport = /\@import [\'|\"]([a-zA-Z0-9-\._\/]+)[\'|\"]/;

  var cssClass = [];
  var packages = [];
  var source = [];

  		 var loadPaths = _([this.dir]).concat(this.loadPaths).filter().uniq().value();

  content.split('\n').forEach(function(line, iLine) {

    line = line.trim();
    var matchImport = regImport.exec(line);

    if (matchImport) {

      var importFilePath = resolveSassPath(matchImport[1].trim(), loadPaths, this.extensions);

      if (importFilePath) {
        var importLine = '@import \'' + importFilePath + '\';';

        var file = {
          line: importLine,
          index: iLine,
          path:  importFilePath,
          css: cssClass.slice(0, cssClass.length)
        };

        if (mapSass.index[this.filepath].dependencies.indexOf(importFilePath) >= 0) {
          source.push(importLine);
        } else {
          packages.push(file);
        }
      }else {
        throw new Error('Impossible to resolve Sass Path  in ' + this.filepath + ' - line : ' + iLine + ' \n ' + line);
      }

    } else {
      source.push(line);
    }

    var open = line.match(/\{/g) || [];
    var close = line.match(/\}/g) || [];
    position += open.length;
    position -= close.length;

    if (position != cssClass.length) {
      if (position > cssClass.length) {
        cssClass.push(line);
      } else {
        cssClass.pop();
      }
    }
  }.bind(this));

  result.main.source = source.join('\n');
  result.packages = packages;

  return result;

};

function addToIndex(mapIndex, filepath, link) {
  if (mapIndex[filepath] === undefined) {
    mapIndex[filepath] = [];
  }

  if (mapIndex[filepath].indexOf(link) == -1) {
    mapIndex[filepath].push(link);
  }
}

SassUnpack.prototype.generateFiles = function(files, mapSass, toPath, urlRoot) {

  var mkdirp = require('mkdirp');

  var mapIndex = [];
  var indexFile = 0;
  var map = [];

  mkdirp.sync(toPath + '/dev/scss/');
  mkdirp.sync(toPath + '/dev/css/');

  var devFilePath = toPath + '/dev/scss/index.scss';
  var devFileCSSUrl = urlRoot+'/dev/css/index.css';

  map.push({
    file: devFilePath,
    href: devFileCSSUrl
  });

  fs.writeFileSync(devFilePath, files.main.source);

  files.packages.forEach(function(file) {

    //console.log(mapSass[file.path]);
    //

    file = _.assign(mapSass.index[file.path], file);

    var fileName =  file.path.replace(path.resolve('./')+ '/', '')
                            .replace(/\//g, '-')
                            .replace(path.extname(file.path),'');

    var devFileCSSUrl = urlRoot + '/dev/css/' + fileName + '.css';
    var devFilePath = toPath + '/dev/scss/' + fileName + '.scss';

    addToIndex(mapIndex, file.path, devFilePath);

    var fileContent = [];

    file.dependencies.forEach(function(item) {
      if (file.path !== item) {
      	addToIndex(mapIndex, item, devFilePath);
        fileContent.push('@import \'' + item + '\';');
      }
    });

    file.imports.forEach(function(item) {
      addToIndex(mapIndex, item, devFilePath);
    });

    file.extended.forEach(function(item) {
       if (file.path !== item) {
      	addToIndex(mapIndex, item, devFilePath);
        fileContent.push('@import \'' + item + '\';');
      }
    }.bind(this));

    fileContent.push('/* unsass */');

    var cssContent = [];
    file.css.forEach(function(cssClass) {
      cssContent.push(cssClass);
    });

    cssContent.push(file.line);

    file.css.forEach(function(cssClass) {
      cssContent.push('}');
    });

    fileContent.push(cssContent.join('\n'));

    fs.writeFileSync(devFilePath, fileContent.join('\n'));

    map.push({
      file: devFilePath,
      href: devFileCSSUrl
    });

  }.bind(this));

  var buf  = [];

  for (var i in mapIndex) {
    buf.push({
      index: i,
      links: _.uniq(mapIndex[i])
    });
  }

  return {
    href: map,
    sass: buf
  };
}

// resolve a sass module to a path

function resolveSassPath(sassPath, loadPaths, extensions) {
  // trim sass file extensions
  var re = new RegExp('(\.(' + extensions.join('|') + '))$', 'i');
  var sassPathName = sassPath.replace(re, '');

  // check all load paths
  //

  var i, j, length = loadPaths.length,
	scssPath, partialPath;
  for (i = 0; i < length; i++) {
    for (j = 0; j < extensions.length; j++) {
      scssPath = path.normalize(loadPaths[i] + '/' + sassPathName + '.' + extensions[j]);
      if (fs.existsSync(scssPath)) {
        return scssPath;
      }
    }

    // special case for _partials
    for (j = 0; j < extensions.length; j++) {
      scssPath = path.normalize(loadPaths[i] + '/' + sassPathName + '.' + extensions[j]);
      partialPath = path.join(path.dirname(scssPath), '_' + path.basename(scssPath));
      if (fs.existsSync(partialPath)) {
        return partialPath;
      }
    }
  }

  // File to import not found or unreadable so we assume this is a custom import
  return false;
}

function processOptions(options) {
  return _.assign({
    loadPaths: [process.cwd()],
    extensions: ['scss', 'css'],
  }, options);
}

module.exports =  SassUnpack;

<|endoftext|>


<commit_before>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
//            Portions ©2008-2009 Apple, Inc. All rights reserved.
// License:   Licened under MIT license (see license.js)
// ==========================================================================

sc_require('views/list') ;
sc_require('views/source_list_group');

SC.BENCHMARK_SOURCE_LIST_VIEW = YES ;

/** @class

  Displays a source list like the source list in iTunes.  SourceList views
  are very similar to ListView's but come preconfigured with the correct
  appearance and default behaviors of a source list.

  @extends SC.ListView
  @since SproutCore 1.0
*/
SC.SourceListView = SC.ListView.extend(
/** @scope SC.SourceListView.prototype */ {

  /**
    Add class name to HTML for styling.
  */
  classNames: ['sc-source-list'],

  /**
    Default row height for source list items is larger.
  */
  rowHeight: 32,

  /**
    By default source lists should not select on mouse down since you will
    often want to drag an item instead of selecting it.
  */
  selectOnMouseDown: NO

});
<commit_msg>SourceListView sends action on select by default<commit_after>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
//            Portions ©2008-2009 Apple, Inc. All rights reserved.
// License:   Licened under MIT license (see license.js)
// ==========================================================================

sc_require('views/list') ;
sc_require('views/source_list_group');

SC.BENCHMARK_SOURCE_LIST_VIEW = YES ;

/** @class

  Displays a source list like the source list in iTunes.  SourceList views
  are very similar to ListView's but come preconfigured with the correct
  appearance and default behaviors of a source list.

  @extends SC.ListView
  @since SproutCore 1.0
*/
SC.SourceListView = SC.ListView.extend(
/** @scope SC.SourceListView.prototype */ {

  /**
    Add class name to HTML for styling.
  */
  classNames: ['sc-source-list'],

  /**
    Default row height for source list items is larger.
  */
  rowHeight: 32,

  /**
    By default source lists should not select on mouse down since you will
    often want to drag an item instead of selecting it.
  */
  selectOnMouseDown: NO,

  /**
    By default, SourceListView's trigger any action you set whenever the user
    clicks on an item.  This gives the SourceList a "menu" like behavior.
  */
  actOnSelect: YES

});
<|endoftext|>


<commit_before>
QUnit.test("test: Event", function (assert) {
	let done = assert.async();

	// number of asserts
	assert.expect(4);

	const subject = '_Test Event 1';
	const datetime = frappe.datetime.now_datetime();
	const hex = '#6be273';
	const rgb = 'rgb(107, 226, 115)';

	frappe.run_serially([
		// insert a new Event
		() => frappe.tests.make('Event', [
			// values to be set
			{subject: subject},
			{starts_on: datetime},
			{color: hex}
		]),
		() => {
			assert.equal(cur_frm.doc.subject, subject, 'Subject correctly set');
			assert.equal(cur_frm.doc.starts_on, datetime, 'Date correctly set');
			assert.equal(cur_frm.doc.color, hex, 'Color correctly set');
		},
		() => frappe.set_route('List', 'Event', 'Calendar'),
		() => frappe.timeout(2),
		() => {
			const bg_color = $(`.result-list:visible .fc-day-grid-event:contains("${subject}")`)
				.css('background-color');
			assert.equal(bg_color, rgb, 'Event background color is set correctly');
		},
		() => done()
	]);

});
<commit_msg>fix event test (#3868)<commit_after>
QUnit.test("test: Event", function (assert) {
	let done = assert.async();

	// number of asserts
	assert.expect(4);

	const subject = '_Test Event 1';
	const datetime = frappe.datetime.now_datetime();
	const hex = '#6be273';
	const rgb = 'rgb(107, 226, 115)';

	frappe.run_serially([
		// insert a new Event
		() => frappe.tests.make('Event', [
			// values to be set
			{subject: subject},
			{starts_on: datetime},
			{color: hex},
			{event_type: 'Private'}
		]),
		() => {
			assert.equal(cur_frm.doc.subject, subject, 'Subject correctly set');
			assert.equal(cur_frm.doc.starts_on, datetime, 'Date correctly set');
			assert.equal(cur_frm.doc.color, hex, 'Color correctly set');

			// set filters explicitly for list view
			frappe.route_options = {
				event_type: 'Private'
			};
		},
		() => frappe.set_route('List', 'Event', 'Calendar'),
		() => frappe.timeout(2),
		() => {
			const bg_color = $(`.result-list:visible .fc-day-grid-event:contains("${subject}")`)
				.css('background-color');
			assert.equal(bg_color, rgb, 'Event background color is set correctly');
		},
		() => done()
	]);

});
<|endoftext|>


<commit_before>import React            from 'react'
import {connect}        from 'react-redux'
import {Link}           from 'react-router-dom'
import {browserHistory} from 'react-router'
import moment           from 'moment'

//import event from '../../events'
import {redirectFromThanks} from '../actions.js'
import {
    Row,
    Col,
    Table
}                           from 'reactstrap';
import ReactMarkdown        from 'react-markdown'
import ageFactory           from "../../age";
import feeFactory           from '../../../shared/fee/feeFactory.js'

//confirmation page for bookings

class ThanksPage extends React.Component {

    constructor(props) {
        super(props);

        this.event = this.props.Event.toJS();
        this.user = this.props.User.toJS();
        this.booking = this.props.Booking.toJS();

        this.ageWidgets = ageFactory(this.event);
        this.fees = feeFactory(this.event);

    }

    render() {

        const event = this.props.Event.toJS();
        const user = this.props.User.toJS();

        const ageWidgets = ageFactory(event);

        //this is some unholy hack to get the thanks page to redirect back to the booking form if the user does not have a booking and will never actually come up in the real world.

        const booking = this.props.Booking.toJS();

        const participants = booking.participants.map(p => {
            p.age = ageWidgets.displayAgeMoment(p.age, event);
            return p;
        }).map(p => <ParticipantRow key={p.id} {...p} />);

        return (<React.Fragment>
            <Row>
            <Col>

Thanks for booking for {event.name}

You can come back and <Link to={"/event/" + event.id + "/book"}>edit</Link> your booking at any time
                    before the deadline

Participants booked

                        Name
                        Age
                        Diet

                    {participants}

            </Col>
            </Row>
            <this.fees.ThanksRow
                event={this.event}
                booking={booking}/>
            <Row>
                <ReactMarkdown escapeHtml={true} source={event.paymentInfo}/>
            </Row>
        </React.Fragment>);
    }
}

const ParticipantRow = props =>

    {props.name}
    {props.age}
    {props.diet}

;

class ThanksPageWrapper extends React.Component {

    constructor(props) {
        super(props);
        this.hasBooking = this.props.Booking
    }

    render() {
        if (this.props.Booking) return <ThanksPage {...this.props}/>;
        else {
            //this is some unholy hack to get the thanks page to redirect back to the booking form if the user does not have a booking and will never actually come up in the real world.
            setImmediate(this.props.redirectFromThanks, this.props.Event.get('id'));
        }
    }
}

const mapStateToProps = (state, props) => {
    let User = state.getIn(["User", "user"]);
    let Event = state.getIn(["Events", "events", parseInt(props.match.params.eventId)]);
    let Booking = state.getIn(["Bookings", "bookings"]).find(b => b.get("userId") === User.get("id") && b.get("eventId") === Event.get("id"));
    return {User, Event, Booking}
};

//const getEvent = event.actions.getEvent
const mapDispatchToProps = {redirectFromThanks};

const VisibleThanksPage = connect(
    mapStateToProps,
    mapDispatchToProps
)(ThanksPageWrapper);

export default VisibleThanksPage;<commit_msg>Fix Fee calculation on Thanks page<commit_after>import React            from 'react'
import {connect}        from 'react-redux'
import {Link}           from 'react-router-dom'
import {browserHistory} from 'react-router'
import moment           from 'moment'

//import event from '../../events'
import {redirectFromThanks} from '../actions.js'
import {
    Row,
    Col,
    Table
}                           from 'reactstrap';
import ReactMarkdown        from 'react-markdown'
import ageFactory           from "../../age";
import feeFactory           from '../../../shared/fee/feeFactory.js'
import W                    from "../../../shared/woodcraft";

//confirmation page for bookings

class ThanksPage extends React.Component {

    constructor(props) {
        super(props);

        this.event = this.props.Event.toJS();
        this.user = this.props.User.toJS();
        this.booking = this.props.Booking.toJS();

        this.ageWidgets = ageFactory(this.event);
        this.fees = feeFactory(this.event);

    }

    render() {

        const event = this.props.Event.toJS();
        const user = this.props.User.toJS();

        const ageWidgets = ageFactory(event);

        //this is some unholy hack to get the thanks page to redirect back to the booking form if the user does not have a booking and will never actually come up in the real world.

        const booking = this.props.Booking.toJS();
        const startDate = moment(event.startDate);

        booking.participants.forEach(p => {
            p.ageAtStart = startDate.diff(moment(p.age), 'years');
            p.ageGroup = W.find(w => w.filter(p.ageAtStart)).singular;
            p.displayAge = ageWidgets.displayAgeParticipant(p);
        });

        const participants = booking.participants.map(p => <ParticipantRow key={p.id} {...p} />);

        return (<React.Fragment>
            <Row>
            <Col>

Thanks for booking for {event.name}

You can come back and <Link to={"/event/" + event.id + "/book"}>edit</Link> your booking at any time
                    before the deadline

Participants booked

                        Name
                        Age
                        Diet

                    {participants}

            </Col>
            </Row>
            <this.fees.ThanksRow
                event={this.event}
                booking={booking}/>
            <Row>
                <ReactMarkdown escapeHtml={true} source={event.paymentInfo}/>
            </Row>
        </React.Fragment>);
    }
}

const ParticipantRow = props =>

    {props.name}
    {props.displayAge}
    {props.diet}

;

class ThanksPageWrapper extends React.Component {

    constructor(props) {
        super(props);
        this.hasBooking = this.props.Booking
    }

    render() {
        if (this.props.Booking) return <ThanksPage {...this.props}/>;
        else {
            //this is some unholy hack to get the thanks page to redirect back to the booking form if the user does not have a booking and will never actually come up in the real world.
            setImmediate(this.props.redirectFromThanks, this.props.Event.get('id'));
        }
    }
}

const mapStateToProps = (state, props) => {
    let User = state.getIn(["User", "user"]);
    let Event = state.getIn(["Events", "events", parseInt(props.match.params.eventId)]);
    let Booking = state.getIn(["Bookings", "bookings"]).find(b => b.get("userId") === User.get("id") && b.get("eventId") === Event.get("id"));
    return {User, Event, Booking}
};

//const getEvent = event.actions.getEvent
const mapDispatchToProps = {redirectFromThanks};

const VisibleThanksPage = connect(
    mapStateToProps,
    mapDispatchToProps
)(ThanksPageWrapper);

export default VisibleThanksPage;<|endoftext|>


<commit_before>// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @ts-nocheck
// TODO(crbug.com/1011811): Enable TypeScript compiler checks

import * as Common from '../common/common.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';

import {createLayoutPane, Element} from './LayoutPane_bridge.js';  // eslint-disable-line no-unused-vars

/**
 * @param {!Array<!SDK.DOMModel.DOMNode>} nodes
 * @return {!Array<!Element>}
 */
const gridNodesToElements = nodes => {
  return nodes.map(node => {
    const className = node.getAttribute('class');
    return {
      id: node.id,
      name: node.localName(),
      domId: node.getAttribute('id'),
      domClasses: className ? className.split(/\s+/) : null,
      enabled: node.domModel().overlayModel().isHighlightedGridInPersistentOverlay(node.id)
    };
  });
};

/**
 * @unrestricted
 */
export class LayoutSidebarPane extends UI.ThrottledWidget.ThrottledWidget {
  constructor() {
    super(true /* isWebComponent */);
    this._layoutPane = createLayoutPane();
    this.contentElement.appendChild(this._layoutPane);
    this._settings = [
      'showGridBorder', 'showGridLines', 'showGridLineNumbers', 'showGridGaps', 'showGridAreas', 'showGridTrackSizes'
    ];
    this._boundOnSettingChanged = this.onSettingChanged.bind(this);
    this._boundOnOverlayChanged = this.onOverlayChanged.bind(this);
    this._pullNode();
  }

  _pullNode() {
    this._node = self.UI.context.flavor(SDK.DOMModel.DOMNode);
  }

  async _fetchGridNodes() {
    const nodeIds = await this._node.domModel().getNodesByStyle(
        [{name: 'display', value: 'grid'}, {name: 'display', value: 'inline-grid'}], true /* pierce */);
    const nodes = nodeIds.map(id => this._node.domModel().nodeForId(id)).filter(node => node !== null);
    return nodes;
  }

  _mapSettings() {
    return this._settings
        .map(settingName => {
          const setting = Common.Settings.Settings.instance().moduleSetting(settingName);
          const ext = setting.extension();
          if (!ext) {
            return null;
          }
          const descriptor = ext.descriptor();
          return {
            type: descriptor.settingType,
            name: descriptor.settingName,
            title: descriptor.title,
            value: setting.get(),
            options: descriptor.options.map(opt => ({
                                              title: opt.text,
                                              value: opt.value,
                                            }))
          };
        })
        .filter(descriptor => descriptor !== null);
  }

  /**
   * @override
   * @protected
   * @return {!Promise<void>}
   */
  async doUpdate() {
    this._pullNode();
    this._layoutPane.data = {
      gridElements: gridNodesToElements(await this._fetchGridNodes()),
      settings: this._mapSettings(),
    };
  }

  /**
   * @param {*} event
   */
  onSettingChanged(event) {
    Common.Settings.Settings.instance().moduleSetting(event.data.setting).set(event.data.value);
  }

  /**
   * @param {*} event
   */
  onOverlayChanged(event) {
    const node = this._node.domModel().nodeForId(event.data.id);
    if (event.data.value) {
      node.domModel().overlayModel().highlightGridInPersistentOverlay(event.data.id);
    } else {
      node.domModel().overlayModel().hideGridInPersistentOverlay(event.data.id);
    }
  }

  /**
   * @override
   */
  wasShown() {
    for (const setting of this._settings) {
      Common.Settings.Settings.instance().moduleSetting(setting).addChangeListener(this.update, this);
    }
    this._layoutPane.addEventListener('setting-changed', this._boundOnSettingChanged);
    this._layoutPane.addEventListener('overlay-changed', this._boundOnOverlayChanged);
    const overlayModel = this._node.domModel().overlayModel();
    overlayModel.addEventListener(SDK.OverlayModel.Events.PersistentGridOverlayCleared, this.update, this);
    overlayModel.addEventListener(SDK.OverlayModel.Events.PersistentGridOverlayStateChanged, this.update, this);
    self.UI.context.addFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);
    this.update();
  }

  /**
   * @override
   */
  willHide() {
    for (const setting of this._settings) {
      Common.Settings.Settings.instance().moduleSetting(setting).removeChangeListener(this.update, this);
    }
    this._layoutPane.removeEventListener('setting-changed', this._boundOnSettingChanged);
    this._layoutPane.removeEventListener('overlay-changed', this._boundOnOverlayChanged);
    const overlayModel = this._node.domModel().overlayModel();
    overlayModel.removeEventListener(SDK.OverlayModel.Events.PersistentGridOverlayCleared, this.update, this);
    overlayModel.removeEventListener(SDK.OverlayModel.Events.PersistentGridOverlayStateChanged, this.update, this);
    self.UI.context.removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);
  }
}
<commit_msg>Layout: Remove the Grid Border setting from the layout pane<commit_after>// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @ts-nocheck
// TODO(crbug.com/1011811): Enable TypeScript compiler checks

import * as Common from '../common/common.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';

import {createLayoutPane, Element} from './LayoutPane_bridge.js';  // eslint-disable-line no-unused-vars

/**
 * @param {!Array<!SDK.DOMModel.DOMNode>} nodes
 * @return {!Array<!Element>}
 */
const gridNodesToElements = nodes => {
  return nodes.map(node => {
    const className = node.getAttribute('class');
    return {
      id: node.id,
      name: node.localName(),
      domId: node.getAttribute('id'),
      domClasses: className ? className.split(/\s+/) : null,
      enabled: node.domModel().overlayModel().isHighlightedGridInPersistentOverlay(node.id)
    };
  });
};

/**
 * @unrestricted
 */
export class LayoutSidebarPane extends UI.ThrottledWidget.ThrottledWidget {
  constructor() {
    super(true /* isWebComponent */);
    this._layoutPane = createLayoutPane();
    this.contentElement.appendChild(this._layoutPane);
    this._settings = ['showGridLines', 'showGridLineNumbers', 'showGridGaps', 'showGridAreas', 'showGridTrackSizes'];
    this._boundOnSettingChanged = this.onSettingChanged.bind(this);
    this._boundOnOverlayChanged = this.onOverlayChanged.bind(this);
    this._pullNode();
  }

  _pullNode() {
    this._node = self.UI.context.flavor(SDK.DOMModel.DOMNode);
  }

  async _fetchGridNodes() {
    const nodeIds = await this._node.domModel().getNodesByStyle(
        [{name: 'display', value: 'grid'}, {name: 'display', value: 'inline-grid'}], true /* pierce */);
    const nodes = nodeIds.map(id => this._node.domModel().nodeForId(id)).filter(node => node !== null);
    return nodes;
  }

  _mapSettings() {
    return this._settings
        .map(settingName => {
          const setting = Common.Settings.Settings.instance().moduleSetting(settingName);
          const ext = setting.extension();
          if (!ext) {
            return null;
          }
          const descriptor = ext.descriptor();
          return {
            type: descriptor.settingType,
            name: descriptor.settingName,
            title: descriptor.title,
            value: setting.get(),
            options: descriptor.options.map(opt => ({
                                              title: opt.text,
                                              value: opt.value,
                                            }))
          };
        })
        .filter(descriptor => descriptor !== null);
  }

  /**
   * @override
   * @protected
   * @return {!Promise<void>}
   */
  async doUpdate() {
    this._pullNode();
    this._layoutPane.data = {
      gridElements: gridNodesToElements(await this._fetchGridNodes()),
      settings: this._mapSettings(),
    };
  }

  /**
   * @param {*} event
   */
  onSettingChanged(event) {
    Common.Settings.Settings.instance().moduleSetting(event.data.setting).set(event.data.value);
  }

  /**
   * @param {*} event
   */
  onOverlayChanged(event) {
    const node = this._node.domModel().nodeForId(event.data.id);
    if (event.data.value) {
      node.domModel().overlayModel().highlightGridInPersistentOverlay(event.data.id);
    } else {
      node.domModel().overlayModel().hideGridInPersistentOverlay(event.data.id);
    }
  }

  /**
   * @override
   */
  wasShown() {
    for (const setting of this._settings) {
      Common.Settings.Settings.instance().moduleSetting(setting).addChangeListener(this.update, this);
    }
    this._layoutPane.addEventListener('setting-changed', this._boundOnSettingChanged);
    this._layoutPane.addEventListener('overlay-changed', this._boundOnOverlayChanged);
    const overlayModel = this._node.domModel().overlayModel();
    overlayModel.addEventListener(SDK.OverlayModel.Events.PersistentGridOverlayCleared, this.update, this);
    overlayModel.addEventListener(SDK.OverlayModel.Events.PersistentGridOverlayStateChanged, this.update, this);
    self.UI.context.addFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);
    this.update();
  }

  /**
   * @override
   */
  willHide() {
    for (const setting of this._settings) {
      Common.Settings.Settings.instance().moduleSetting(setting).removeChangeListener(this.update, this);
    }
    this._layoutPane.removeEventListener('setting-changed', this._boundOnSettingChanged);
    this._layoutPane.removeEventListener('overlay-changed', this._boundOnOverlayChanged);
    const overlayModel = this._node.domModel().overlayModel();
    overlayModel.removeEventListener(SDK.OverlayModel.Events.PersistentGridOverlayCleared, this.update, this);
    overlayModel.removeEventListener(SDK.OverlayModel.Events.PersistentGridOverlayStateChanged, this.update, this);
    self.UI.context.removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);
  }
}
<|endoftext|>