<commit_before>"use strict";
(function(window) {
    var config = {
      silent: false
    }

    /**
    * Converts attributes into key-value pairs
    * @param {Node} node
    * @return {Object} Key-Value pairs of Attributes
    */
    var extractAttrs = function(node) {
      var attrs = {};
      if(!node.attributes) return attrs;
      var rawAttrs = node.attributes;
      for(var i = 0; i < rawAttrs.length; i++) {
        attrs[rawAttrs[i].name] = rawAttrs[i].value
      }

      return attrs;
    }

    /**
    * Compiles a template with given data
    * @param {String} template
    * @param {Object} data
    * @return {String} Template with data rendered
    */
    var compileTemplate = function(template, data) {
      var code = template,
          re = /{{([A-Za-z0-9_.\[\]]+)}}/gi;
      code.replace(re, function(match, p) {
        code = code.replace(match, "` + data." + p + " + `");
      });
      var compile = new Function("data", "var out = `" + code + "`; return out");
      return compile(data);
    }

    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        var self = this;
        this.$el = document.querySelector(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        /**
        * Logs a Message
        * @param {String} msg
        */
        this.log = function(msg) {
          if(!config.silent) console.log(msg);
        }

        /**
        * Throws an Error
        * @param {String} msg
        */
        this.error = function(msg) {
          console.log("Moon ERR: " + msg);
        }

        /**
        * Creates an object to be used in a Virtual DOM
        * @param {String} type
        * @param {Array} children
        * @param {String} val
        * @param {Object} props
        * @param {Node} node
        * @return {Object} Object usable in Virtual DOM
        */
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        /**
        * Create Elements Recursively For all Children
        * @param {Array} children
        * @return {Array} Array of elements usable in Virtual DOM
        */
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        /**
        * Creates Virtual DOM
        * @param {Node} node
        */
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        /**
        * Turns Custom Components into their Corresponding Templates
        */
        this.componentsToHTML = function() {
          for(var component in this.components) {
            var componentsFound = document.getElementsByTagName(component);
            componentsFound = Array.prototype.slice.call(componentsFound);
            for(var i = 0; i < componentsFound.length; i++) {
              var componentFound = componentsFound[i];
              var componentProps = extractAttrs(componentFound);
              var componentDummy = document.createElement('div');
              componentDummy.innerHTML = this.components[component].template;
              componentDummy = componentDummy.firstChild;

              for(var attr in componentProps) {
                componentDummy.setAttribute(attr, componentProps[attr]);
              }

              componentFound.outerHTML = componentDummy.outerHTML;
            }
          }
        }

        /**
        * Compiles all Directives
        */
        this.compileDirectives = function() {

        }

        /**
        * Sets Value in Data
        * @param {String} key
        * @param {String} val
        */
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        /**
        * Gets Value in Data
        * @param {String} key
        * @return {String} Value of key in data
        */
        this.get = function(key) {
          return this.$data[key];
        }

        /**
        * Makes an AJAX Request
        * @param {String} method
        * @param {String} url
        * @param {Object} params
        * @param {Function} cb
        */
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        /**
        * Calls a method
        * @param {String} method
        */
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
        }

        // Default Directives
        directives["m-if"] = function(el, val, vdom) {
          var evaluated = new Function("return " + val);
          if(!evaluated()) {
            el.textContent = "";
          } else {
            el.textContent = compileTemplate(vdom.val, self.$data);
          }
        }

        directives["m-on"] = function(el, val, vdom) {
          var splitVal = val.split(":");
          var eventToCall = splitVal[0];
          var methodToCall = splitVal[1];
          el.addEventListener(eventToCall, function() {
            self.method(methodToCall);
          });
          el.removeAttribute("m-on");
          delete vdom.props["m-on"];
        }

        directives["m-model"] = function(el, val, vdom) {
          el.value = self.get(val);
          el.addEventListener("input", function() {
            self.set(val, el.value);
          });
          el.removeAttribute("m-model");
          delete vdom.props["m-model"];
        }

        directives["m-once"] = function(el, val, vdom) {
          vdom.val = el.textContent;
          for(var child in vdom.children) {
            vdom.children[child].val = compileTemplate(vdom.children[child].val, self.$data);
          }
        }

        // directives["m-for"] = function(el, val, vdom) {
        //   var splitVal = val.split(" in ");
        //   var alias = splitVal[0];
        //   var arr = self.get(splitVal[1]);
        //   var clone = el.cloneNode(true);
        //   var compilable = vdom.val.replace(new RegExp(alias, "gi"), splitVal[1] + '[0]');
        //   el.innerHTML = compilable;
        //   for(var i = 1; i < arr.length; i++) {
        //     var newClone = clone.cloneNode(true);
        //     newClone.innerHTML = vdom.val.replace(new RegExp(alias, "gi"), splitVal[1] + '[' + i + ']');
        //     var parent = el.parentNode;
        //     parent.appendChild(newClone);
        //   }
        //   vdom.val = el.textContent;
        //   delete vdom.props["m-for"];
        // }

        /**
        * Builds the DOM With Data
        * @param {Array} children
        */
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty, el);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        /**
        * Initializes Moon
        */
        this.init = function() {
          this.log("======= Moon =======");
          this.componentsToHTML();
          this.createVirtualDOM(this.$el);
          this.build(this.dom.children);
        }

        // Initialize 🎉
        this.init();
    }

    /**
    * Sets the Configuration of Moon
    * @param {Object} opts
    */
    Moon.config = function(opts) {
      if(opts.silent) {
        config.silent = opts.silent;
      }
    }

    /**
    * Runs an external Plugin
    * @param {Object} plugin
    */
    Moon.use = function(plugin) {
      plugin.init(Moon);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<commit_msg>remove compile directives<commit_after>"use strict";
(function(window) {
    var config = {
      silent: false
    }

    /**
    * Converts attributes into key-value pairs
    * @param {Node} node
    * @return {Object} Key-Value pairs of Attributes
    */
    var extractAttrs = function(node) {
      var attrs = {};
      if(!node.attributes) return attrs;
      var rawAttrs = node.attributes;
      for(var i = 0; i < rawAttrs.length; i++) {
        attrs[rawAttrs[i].name] = rawAttrs[i].value
      }

      return attrs;
    }

    /**
    * Compiles a template with given data
    * @param {String} template
    * @param {Object} data
    * @return {String} Template with data rendered
    */
    var compileTemplate = function(template, data) {
      var code = template,
          re = /{{([A-Za-z0-9_.\[\]]+)}}/gi;
      code.replace(re, function(match, p) {
        code = code.replace(match, "` + data." + p + " + `");
      });
      var compile = new Function("data", "var out = `" + code + "`; return out");
      return compile(data);
    }

    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        var self = this;
        this.$el = document.querySelector(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        /**
        * Logs a Message
        * @param {String} msg
        */
        this.log = function(msg) {
          if(!config.silent) console.log(msg);
        }

        /**
        * Throws an Error
        * @param {String} msg
        */
        this.error = function(msg) {
          console.log("Moon ERR: " + msg);
        }

        /**
        * Creates an object to be used in a Virtual DOM
        * @param {String} type
        * @param {Array} children
        * @param {String} val
        * @param {Object} props
        * @param {Node} node
        * @return {Object} Object usable in Virtual DOM
        */
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        /**
        * Create Elements Recursively For all Children
        * @param {Array} children
        * @return {Array} Array of elements usable in Virtual DOM
        */
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        /**
        * Creates Virtual DOM
        * @param {Node} node
        */
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        /**
        * Turns Custom Components into their Corresponding Templates
        */
        this.componentsToHTML = function() {
          for(var component in this.components) {
            var componentsFound = document.getElementsByTagName(component);
            componentsFound = Array.prototype.slice.call(componentsFound);
            for(var i = 0; i < componentsFound.length; i++) {
              var componentFound = componentsFound[i];
              var componentProps = extractAttrs(componentFound);
              var componentDummy = document.createElement('div');
              componentDummy.innerHTML = this.components[component].template;
              componentDummy = componentDummy.firstChild;

              for(var attr in componentProps) {
                componentDummy.setAttribute(attr, componentProps[attr]);
              }

              componentFound.outerHTML = componentDummy.outerHTML;
            }
          }
        }

        /**
        * Sets Value in Data
        * @param {String} key
        * @param {String} val
        */
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        /**
        * Gets Value in Data
        * @param {String} key
        * @return {String} Value of key in data
        */
        this.get = function(key) {
          return this.$data[key];
        }

        /**
        * Makes an AJAX Request
        * @param {String} method
        * @param {String} url
        * @param {Object} params
        * @param {Function} cb
        */
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        /**
        * Calls a method
        * @param {String} method
        */
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
        }

        // Default Directives
        directives["m-if"] = function(el, val, vdom) {
          var evaluated = new Function("return " + val);
          if(!evaluated()) {
            el.textContent = "";
          } else {
            el.textContent = compileTemplate(vdom.val, self.$data);
          }
        }

        directives["m-on"] = function(el, val, vdom) {
          var splitVal = val.split(":");
          var eventToCall = splitVal[0];
          var methodToCall = splitVal[1];
          el.addEventListener(eventToCall, function() {
            self.method(methodToCall);
          });
          el.removeAttribute("m-on");
          delete vdom.props["m-on"];
        }

        directives["m-model"] = function(el, val, vdom) {
          el.value = self.get(val);
          el.addEventListener("input", function() {
            self.set(val, el.value);
          });
          el.removeAttribute("m-model");
          delete vdom.props["m-model"];
        }

        directives["m-once"] = function(el, val, vdom) {
          vdom.val = el.textContent;
          for(var child in vdom.children) {
            vdom.children[child].val = compileTemplate(vdom.children[child].val, self.$data);
          }
        }

        // directives["m-for"] = function(el, val, vdom) {
        //   var splitVal = val.split(" in ");
        //   var alias = splitVal[0];
        //   var arr = self.get(splitVal[1]);
        //   var clone = el.cloneNode(true);
        //   var compilable = vdom.val.replace(new RegExp(alias, "gi"), splitVal[1] + '[0]');
        //   el.innerHTML = compilable;
        //   for(var i = 1; i < arr.length; i++) {
        //     var newClone = clone.cloneNode(true);
        //     newClone.innerHTML = vdom.val.replace(new RegExp(alias, "gi"), splitVal[1] + '[' + i + ']');
        //     var parent = el.parentNode;
        //     parent.appendChild(newClone);
        //   }
        //   vdom.val = el.textContent;
        //   delete vdom.props["m-for"];
        // }

        /**
        * Builds the DOM With Data
        * @param {Array} children
        */
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty, el);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        /**
        * Initializes Moon
        */
        this.init = function() {
          this.log("======= Moon =======");
          this.componentsToHTML();
          this.createVirtualDOM(this.$el);
          this.build(this.dom.children);
        }

        // Initialize 🎉
        this.init();
    }

    /**
    * Sets the Configuration of Moon
    * @param {Object} opts
    */
    Moon.config = function(opts) {
      if(opts.silent) {
        config.silent = opts.silent;
      }
    }

    /**
    * Runs an external Plugin
    * @param {Object} plugin
    */
    Moon.use = function(plugin) {
      plugin.init(Moon);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<|endoftext|>


<commit_before>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        this.$el = document.getElementById(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        // Utility: Raw Attributes -> Key Value Pairs
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        // Utility: Compile a template and return html
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([.]?\w+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        // Utility: Create Elements Recursively For all Children
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        // Utility: Create Virtual DOM Instance
        this.createVirtualDOM = function(node) {
          // if(this.components[node.nodeName.toLowerCase()]) {
          //   var component = this.components[type.toLowerCase()].template;
          // }
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        // Build the DOM with $data
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = this.directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Create Virtual DOM Object from Params
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        // Set any value in $data
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        // Get any value in $data
        this.get = function(key) {
          return this.$data[key];
        }

        // Make AJAX GET/POST requests
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        // Call a method defined in _methods
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
          this.build(this.dom.children);
        }

        // Default Directives
        var dirSelf = this;
        directives["m-if"] = function(el, val) {
          var evaluated = new Function("return " + val);
          if(!evaluated) {
            el.textContent = "";
          }
        }

        // Initialize
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<commit_msg>no need for dirself<commit_after>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        this.$el = document.getElementById(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        // Utility: Raw Attributes -> Key Value Pairs
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        // Utility: Compile a template and return html
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([.]?\w+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        // Utility: Create Elements Recursively For all Children
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        // Utility: Create Virtual DOM Instance
        this.createVirtualDOM = function(node) {
          // if(this.components[node.nodeName.toLowerCase()]) {
          //   var component = this.components[type.toLowerCase()].template;
          // }
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        // Build the DOM with $data
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = this.directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Create Virtual DOM Object from Params
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        // Set any value in $data
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        // Get any value in $data
        this.get = function(key) {
          return this.$data[key];
        }

        // Make AJAX GET/POST requests
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        // Call a method defined in _methods
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
          this.build(this.dom.children);
        }

        // Default Directives
        directives["m-if"] = function(el, val) {
          var evaluated = new Function("return " + val);
          if(!evaluated) {
            el.textContent = "";
          }
        }

        // Initialize
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<|endoftext|>


<commit_before>/**
 * PowerTip Core
 *
 * @fileoverview  Core variables, plugin object, and API.
 * @link          http://stevenbenner.github.com/jquery-powertip/
 * @author        Steven Benner (http://stevenbenner.com/)
 * @requires      jQuery 1.7+
 */

// useful private variables
var $document = $(document),
	$window = $(window),
	$body = $('body');

// constants
var DATA_DISPLAYCONTROLLER = 'displayController',
	DATA_HASACTIVEHOVER = 'hasActiveHover',
	DATA_HASMOUSEENTER = 'hasMouseEnter',
	DATA_FORCEDOPEN = 'forcedOpen',
	DATA_HASMOUSEMOVE = 'hasMouseMove',
	DATA_MOUSEONTOTIP = 'mouseOnToPopup',
	DATA_ORIGINALTITLE = 'originalTitle',
	DATA_POWERTIP = 'powertip',
	DATA_POWERTIPJQ = 'powertipjq',
	DATA_POWERTIPTARGET = 'powertiptarget',
	EVENT_NAMESPACE = '.powertip',
	RAD2DEG = 180 / Math.PI;

/**
 * Session data
 * Private properties global to all powerTip instances
 */
var session = {
	elements: null,
	tooltips: null,
	isTipOpen: false,
	isFixedTipOpen: false,
	isClosing: false,
	tipOpenImminent: false,
	activeHover: null,
	currentX: 0,
	currentY: 0,
	previousX: 0,
	previousY: 0,
	desyncTimeout: null,
	closeDelayTimeout: null,
	mouseTrackingActive: false,
	delayInProgress: false,
	windowWidth: 0,
	windowHeight: 0,
	scrollTop: 0,
	scrollLeft: 0
};

/**
 * Collision enumeration
 * @enum {number}
 */
var Collision = {
	none: 0,
	top: 1,
	bottom: 2,
	left: 4,
	right: 8
};

/**
 * Display hover tooltips on the matched elements.
 * @param {(Object|string)} opts The options object to use for the plugin, or
 *     the name of a method to invoke on the first matched element.
 * @param {*=} [arg] Argument for an invoked method (optional).
 * @return {jQuery} jQuery object for the matched selectors.
 */
$.fn.powerTip = function(opts, arg) {
	var targetElements = this,
		options,
		tipController;

	// don't do any work if there were no matched elements
	if (!targetElements.length) {
		return targetElements;
	}

	// handle api method calls on the plugin, e.g. powerTip('hide')
	if ($.type(opts) === 'string' && $.powerTip[opts]) {
		return $.powerTip[opts].call(targetElements, targetElements, arg);
	}

	// extend options and instantiate TooltipController
	options = $.extend({}, $.fn.powerTip.defaults, opts);
	tipController = new TooltipController(options);

	// hook mouse and viewport dimension tracking
	initTracking();

	// setup the elements
	targetElements.each(function elementSetup() {
		var $this = $(this),
			dataPowertip = $this.data(DATA_POWERTIP),
			dataElem = $this.data(DATA_POWERTIPJQ),
			dataTarget = $this.data(DATA_POWERTIPTARGET),
			title;

		// handle repeated powerTip calls on the same element by destroying the
		// original instance hooked to it and replacing it with this call
		if ($this.data(DATA_DISPLAYCONTROLLER)) {
			$.powerTip.destroy($this);
		}

		// attempt to use title attribute text if there is no data-powertip,
		// data-powertipjq or data-powertiptarget. If we do use the title
		// attribute, delete the attribute so the browser will not show it
		title = $this.attr('title');
		if (!dataPowertip && !dataTarget && !dataElem && title) {
			$this.data(DATA_POWERTIP, title);
			$this.data(DATA_ORIGINALTITLE, title);
			$this.removeAttr('title');
		}

		// create hover controllers for each element
		$this.data(
			DATA_DISPLAYCONTROLLER,
			new DisplayController($this, options, tipController)
		);
	});

	// attach events to matched elements if the manual option is not enabled
	if (!options.manual) {
		// attach open events
		$.each(options.openEvents, function(idx, evt) {
			if ($.inArray(evt, options.closeEvents) > -1) {
				// event is in both openEvents and closeEvents, so toggle it
				targetElements.on(evt + EVENT_NAMESPACE, function elementToggle(event) {
					$.powerTip.toggle(this, event);
				});
			} else {
				targetElements.on(evt + EVENT_NAMESPACE, function elementOpen(event) {
					// pass mouse events (for hover intent and mouse tracking)
					$.powerTip.show(this, typeof event.pageX === 'number' ? event : null);
				});
			}
		});

		// attach close events
		$.each(options.closeEvents, function(idx, evt) {
			if ($.inArray(evt, options.openEvents) < 0) {
				targetElements.on(evt + EVENT_NAMESPACE, function elementClose(event) {
					// set immediate to true for any event without mouse info
					$.powerTip.hide(this, typeof event.pageX !== 'number');
				});
			}
		});

		// attach escape key close event
		targetElements.on('keydown' + EVENT_NAMESPACE, function elementKeyDown(event) {
			// always close tooltip when the escape key is pressed
			if (event.keyCode === 27) {
				$.powerTip.hide(this, true);
			}
		});
	}

	// remember elements that the plugin is attached to
	session.elements = session.elements ? session.elements.add(targetElements) : targetElements;

	return targetElements;
};

/**
 * Default options for the powerTip plugin.
 */
$.fn.powerTip.defaults = {
	fadeInTime: 200,
	fadeOutTime: 100,
	followMouse: false,
	popupId: 'powerTip',
	intentSensitivity: 7,
	intentPollInterval: 100,
	closeDelay: 100,
	placement: 'n',
	smartPlacement: false,
	offset: 10,
	mouseOnToPopup: false,
	manual: false,
	openEvents: [ 'mouseenter', 'focus' ],
	closeEvents: [ 'mouseleave', 'blur' ]
};

/**
 * Default smart placement priority lists.
 * The first item in the array is the highest priority, the last is the lowest.
 * The last item is also the default, which will be used if all previous options
 * do not fit.
 */
$.fn.powerTip.smartPlacementLists = {
	n: ['n', 'ne', 'nw', 's'],
	e: ['e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e'],
	s: ['s', 'se', 'sw', 'n'],
	w: ['w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w'],
	nw: ['nw', 'w', 'sw', 'n', 's', 'se', 'nw'],
	ne: ['ne', 'e', 'se', 'n', 's', 'sw', 'ne'],
	sw: ['sw', 'w', 'nw', 's', 'n', 'ne', 'sw'],
	se: ['se', 'e', 'ne', 's', 'n', 'nw', 'se'],
	'nw-alt': ['nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e'],
	'ne-alt': ['ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w'],
	'sw-alt': ['sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e'],
	'se-alt': ['se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w']
};

/**
 * Public API
 */
$.powerTip = {
	/**
	 * Attempts to show the tooltip for the specified element.
	 * @param {jQuery|Element} element The element to open the tooltip for.
	 * @param {jQuery.Event=} event jQuery event for hover intent and mouse
	 *     tracking (optional).
	 * @return {jQuery|Element} The original jQuery object or DOM Element.
	 */
	show: function apiShowTip(element, event) {
		if (event) {
			trackMouse(event);
			session.previousX = event.pageX;
			session.previousY = event.pageY;
			$(element).data(DATA_DISPLAYCONTROLLER).show();
		} else {
			$(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true);
		}
		return element;
	},

	/**
	 * Repositions the tooltip on the element.
	 * @param {jQuery|Element} element The element the tooltip is shown for.
	 * @return {jQuery|Element} The original jQuery object or DOM Element.
	 */
	reposition: function apiResetPosition(element) {
		$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();
		return element;
	},

	/**
	 * Attempts to close any open tooltips.
	 * @param {(jQuery|Element)=} element The element with the tooltip that
	 *     should be closed (optional).
	 * @param {boolean=} immediate Disable close delay (optional).
	 * @return {jQuery|Element|undefined} The original jQuery object or DOM
	 *     Element, if one was specified.
	 */
	hide: function apiCloseTip(element, immediate) {
		if (element) {
			$(element).first().data(DATA_DISPLAYCONTROLLER).hide(immediate);
		} else {
			if (session.activeHover) {
				session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true);
			}
		}
		return element;
	},

	/**
	 * Toggles the tooltip for the specified element. This will open a closed
	 * tooltip, or close and open tooltip.
	 * @param {(jQuery|Element)} element The element with the tooltip that
	 *     should be toggled.
	 * @param {jQuery.Event=} event jQuery event for hover intent and mouse
	 *     tracking (optional).
	 */
	toggle: function apiToggle(element, event) {
		if (session.activeHover && element[0] === session.activeHover[0]) {
			// tooltip for element is active, so close it
			$.powerTip.hide(element, event);
		} else {
			// tooltip for element is not active, so open it
			$.powerTip.show(element, event);
		}
	},

	/**
	 * Destroy and roll back any powerTip() instance on the specified elements.
	 * If no elements are specified then all elements that the plugin is
	 * currently attached to will be rolled back.
	 * @param {(jQuery|Element)=} element The element with the powerTip instance.
	 * @return {jQuery|Element|undefined} The original jQuery object or DOM
	 *     Element, if one was specified.
	 */
	destroy: function apiDestroy(element) {
		var $element = element ? $(element) : session.elements;

		// if the plugin is not hooked to any elements then there is no point
		// trying to destroy anything, or dealing with the possible errors
		if (!session.elements || session.elements.length === 0) {
			return element;
		}

		// unhook events and destroy plugin changes to each element
		$element.off(EVENT_NAMESPACE).each(function destroy() {
			var $this = $(this),
				dataAttributes = [
					DATA_ORIGINALTITLE,
					DATA_DISPLAYCONTROLLER,
					DATA_HASACTIVEHOVER,
					DATA_FORCEDOPEN
				];

			// revert title attribute
			if ($this.data(DATA_ORIGINALTITLE)) {
				$this.attr('title', $this.data(DATA_ORIGINALTITLE));
				dataAttributes.push(DATA_POWERTIP);
			}

			// remove data attributes
			$this.removeData(dataAttributes);
		});

		// remove destroyed element from active elements collection
		session.elements = session.elements.not($element);

		// if there are no active elements left then we will unhook all of the
		// events that we've bound code to and remove the tooltip elements
		if (session.elements.length === 0) {
			$window.off(EVENT_NAMESPACE);
			$document.off(EVENT_NAMESPACE);
			session.mouseTrackingActive = false;
			session.tooltips.remove();
			session.tooltips = null;
		}

		return element;
	}
};

// API aliasing
$.powerTip.showTip = $.powerTip.show;
$.powerTip.closeTip = $.powerTip.hide;
<commit_msg>Added mouse event checking to API show() method.<commit_after>/**
 * PowerTip Core
 *
 * @fileoverview  Core variables, plugin object, and API.
 * @link          http://stevenbenner.github.com/jquery-powertip/
 * @author        Steven Benner (http://stevenbenner.com/)
 * @requires      jQuery 1.7+
 */

// useful private variables
var $document = $(document),
	$window = $(window),
	$body = $('body');

// constants
var DATA_DISPLAYCONTROLLER = 'displayController',
	DATA_HASACTIVEHOVER = 'hasActiveHover',
	DATA_HASMOUSEENTER = 'hasMouseEnter',
	DATA_FORCEDOPEN = 'forcedOpen',
	DATA_HASMOUSEMOVE = 'hasMouseMove',
	DATA_MOUSEONTOTIP = 'mouseOnToPopup',
	DATA_ORIGINALTITLE = 'originalTitle',
	DATA_POWERTIP = 'powertip',
	DATA_POWERTIPJQ = 'powertipjq',
	DATA_POWERTIPTARGET = 'powertiptarget',
	EVENT_NAMESPACE = '.powertip',
	RAD2DEG = 180 / Math.PI;

/**
 * Session data
 * Private properties global to all powerTip instances
 */
var session = {
	elements: null,
	tooltips: null,
	isTipOpen: false,
	isFixedTipOpen: false,
	isClosing: false,
	tipOpenImminent: false,
	activeHover: null,
	currentX: 0,
	currentY: 0,
	previousX: 0,
	previousY: 0,
	desyncTimeout: null,
	closeDelayTimeout: null,
	mouseTrackingActive: false,
	delayInProgress: false,
	windowWidth: 0,
	windowHeight: 0,
	scrollTop: 0,
	scrollLeft: 0
};

/**
 * Collision enumeration
 * @enum {number}
 */
var Collision = {
	none: 0,
	top: 1,
	bottom: 2,
	left: 4,
	right: 8
};

/**
 * Display hover tooltips on the matched elements.
 * @param {(Object|string)} opts The options object to use for the plugin, or
 *     the name of a method to invoke on the first matched element.
 * @param {*=} [arg] Argument for an invoked method (optional).
 * @return {jQuery} jQuery object for the matched selectors.
 */
$.fn.powerTip = function(opts, arg) {
	var targetElements = this,
		options,
		tipController;

	// don't do any work if there were no matched elements
	if (!targetElements.length) {
		return targetElements;
	}

	// handle api method calls on the plugin, e.g. powerTip('hide')
	if ($.type(opts) === 'string' && $.powerTip[opts]) {
		return $.powerTip[opts].call(targetElements, targetElements, arg);
	}

	// extend options and instantiate TooltipController
	options = $.extend({}, $.fn.powerTip.defaults, opts);
	tipController = new TooltipController(options);

	// hook mouse and viewport dimension tracking
	initTracking();

	// setup the elements
	targetElements.each(function elementSetup() {
		var $this = $(this),
			dataPowertip = $this.data(DATA_POWERTIP),
			dataElem = $this.data(DATA_POWERTIPJQ),
			dataTarget = $this.data(DATA_POWERTIPTARGET),
			title;

		// handle repeated powerTip calls on the same element by destroying the
		// original instance hooked to it and replacing it with this call
		if ($this.data(DATA_DISPLAYCONTROLLER)) {
			$.powerTip.destroy($this);
		}

		// attempt to use title attribute text if there is no data-powertip,
		// data-powertipjq or data-powertiptarget. If we do use the title
		// attribute, delete the attribute so the browser will not show it
		title = $this.attr('title');
		if (!dataPowertip && !dataTarget && !dataElem && title) {
			$this.data(DATA_POWERTIP, title);
			$this.data(DATA_ORIGINALTITLE, title);
			$this.removeAttr('title');
		}

		// create hover controllers for each element
		$this.data(
			DATA_DISPLAYCONTROLLER,
			new DisplayController($this, options, tipController)
		);
	});

	// attach events to matched elements if the manual option is not enabled
	if (!options.manual) {
		// attach open events
		$.each(options.openEvents, function(idx, evt) {
			if ($.inArray(evt, options.closeEvents) > -1) {
				// event is in both openEvents and closeEvents, so toggle it
				targetElements.on(evt + EVENT_NAMESPACE, function elementToggle(event) {
					$.powerTip.toggle(this, event);
				});
			} else {
				targetElements.on(evt + EVENT_NAMESPACE, function elementOpen(event) {
					// pass mouse events (for hover intent and mouse tracking)
					$.powerTip.show(this, typeof event.pageX === 'number' ? event : null);
				});
			}
		});

		// attach close events
		$.each(options.closeEvents, function(idx, evt) {
			if ($.inArray(evt, options.openEvents) < 0) {
				targetElements.on(evt + EVENT_NAMESPACE, function elementClose(event) {
					// set immediate to true for any event without mouse info
					$.powerTip.hide(this, typeof event.pageX !== 'number');
				});
			}
		});

		// attach escape key close event
		targetElements.on('keydown' + EVENT_NAMESPACE, function elementKeyDown(event) {
			// always close tooltip when the escape key is pressed
			if (event.keyCode === 27) {
				$.powerTip.hide(this, true);
			}
		});
	}

	// remember elements that the plugin is attached to
	session.elements = session.elements ? session.elements.add(targetElements) : targetElements;

	return targetElements;
};

/**
 * Default options for the powerTip plugin.
 */
$.fn.powerTip.defaults = {
	fadeInTime: 200,
	fadeOutTime: 100,
	followMouse: false,
	popupId: 'powerTip',
	intentSensitivity: 7,
	intentPollInterval: 100,
	closeDelay: 100,
	placement: 'n',
	smartPlacement: false,
	offset: 10,
	mouseOnToPopup: false,
	manual: false,
	openEvents: [ 'mouseenter', 'focus' ],
	closeEvents: [ 'mouseleave', 'blur' ]
};

/**
 * Default smart placement priority lists.
 * The first item in the array is the highest priority, the last is the lowest.
 * The last item is also the default, which will be used if all previous options
 * do not fit.
 */
$.fn.powerTip.smartPlacementLists = {
	n: ['n', 'ne', 'nw', 's'],
	e: ['e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e'],
	s: ['s', 'se', 'sw', 'n'],
	w: ['w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w'],
	nw: ['nw', 'w', 'sw', 'n', 's', 'se', 'nw'],
	ne: ['ne', 'e', 'se', 'n', 's', 'sw', 'ne'],
	sw: ['sw', 'w', 'nw', 's', 'n', 'ne', 'sw'],
	se: ['se', 'e', 'ne', 's', 'n', 'nw', 'se'],
	'nw-alt': ['nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e'],
	'ne-alt': ['ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w'],
	'sw-alt': ['sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e'],
	'se-alt': ['se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w']
};

/**
 * Public API
 */
$.powerTip = {
	/**
	 * Attempts to show the tooltip for the specified element.
	 * @param {jQuery|Element} element The element to open the tooltip for.
	 * @param {jQuery.Event=} event jQuery event for hover intent and mouse
	 *     tracking (optional).
	 * @return {jQuery|Element} The original jQuery object or DOM Element.
	 */
	show: function apiShowTip(element, event) {
		// if we were supplied an event with a pageX property then it is a mouse
		// event with the information necessary to do hover intent testing
		if (event && typeof event.pageX === 'number') {
			trackMouse(event);
			session.previousX = event.pageX;
			session.previousY = event.pageY;
			$(element).data(DATA_DISPLAYCONTROLLER).show();
		} else {
			$(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true);
		}
		return element;
	},

	/**
	 * Repositions the tooltip on the element.
	 * @param {jQuery|Element} element The element the tooltip is shown for.
	 * @return {jQuery|Element} The original jQuery object or DOM Element.
	 */
	reposition: function apiResetPosition(element) {
		$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();
		return element;
	},

	/**
	 * Attempts to close any open tooltips.
	 * @param {(jQuery|Element)=} element The element with the tooltip that
	 *     should be closed (optional).
	 * @param {boolean=} immediate Disable close delay (optional).
	 * @return {jQuery|Element|undefined} The original jQuery object or DOM
	 *     Element, if one was specified.
	 */
	hide: function apiCloseTip(element, immediate) {
		if (element) {
			$(element).first().data(DATA_DISPLAYCONTROLLER).hide(immediate);
		} else {
			if (session.activeHover) {
				session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true);
			}
		}
		return element;
	},

	/**
	 * Toggles the tooltip for the specified element. This will open a closed
	 * tooltip, or close and open tooltip.
	 * @param {(jQuery|Element)} element The element with the tooltip that
	 *     should be toggled.
	 * @param {jQuery.Event=} event jQuery event for hover intent and mouse
	 *     tracking (optional).
	 */
	toggle: function apiToggle(element, event) {
		if (session.activeHover && element[0] === session.activeHover[0]) {
			// tooltip for element is active, so close it
			$.powerTip.hide(element, event);
		} else {
			// tooltip for element is not active, so open it
			$.powerTip.show(element, event);
		}
	},

	/**
	 * Destroy and roll back any powerTip() instance on the specified elements.
	 * If no elements are specified then all elements that the plugin is
	 * currently attached to will be rolled back.
	 * @param {(jQuery|Element)=} element The element with the powerTip instance.
	 * @return {jQuery|Element|undefined} The original jQuery object or DOM
	 *     Element, if one was specified.
	 */
	destroy: function apiDestroy(element) {
		var $element = element ? $(element) : session.elements;

		// if the plugin is not hooked to any elements then there is no point
		// trying to destroy anything, or dealing with the possible errors
		if (!session.elements || session.elements.length === 0) {
			return element;
		}

		// unhook events and destroy plugin changes to each element
		$element.off(EVENT_NAMESPACE).each(function destroy() {
			var $this = $(this),
				dataAttributes = [
					DATA_ORIGINALTITLE,
					DATA_DISPLAYCONTROLLER,
					DATA_HASACTIVEHOVER,
					DATA_FORCEDOPEN
				];

			// revert title attribute
			if ($this.data(DATA_ORIGINALTITLE)) {
				$this.attr('title', $this.data(DATA_ORIGINALTITLE));
				dataAttributes.push(DATA_POWERTIP);
			}

			// remove data attributes
			$this.removeData(dataAttributes);
		});

		// remove destroyed element from active elements collection
		session.elements = session.elements.not($element);

		// if there are no active elements left then we will unhook all of the
		// events that we've bound code to and remove the tooltip elements
		if (session.elements.length === 0) {
			$window.off(EVENT_NAMESPACE);
			$document.off(EVENT_NAMESPACE);
			session.mouseTrackingActive = false;
			session.tooltips.remove();
			session.tooltips = null;
		}

		return element;
	}
};

// API aliasing
$.powerTip.showTip = $.powerTip.show;
$.powerTip.closeTip = $.powerTip.hide;
<|endoftext|>


<commit_before>import pruneNonCriticalCss from './browser-sandbox/pruneNonCriticalCss'

async function blockJsRequests (page) {
  await page.setRequestInterceptionEnabled(true)
  page.on('request', interceptedRequest => {
    if (interceptedRequest.url.endsWith('.js')) {
      interceptedRequest.abort()
    } else {
      interceptedRequest.continue()
    }
  })
}

async function pruneNonCriticalCssLauncher ({
  browser,
  url,
  astRules,
  width,
  height,
  forceInclude,
  userAgent,
  timeout,
  renderWaitTime,
  blockJSRequests,
  customPageHeaders = {},
  debuglog
}) {
  let _hasExited = false

  return new Promise(async (resolve, reject) => {
    debuglog('Penthouse core start')
    let page
    let killTimeout
    async function cleanupAndExit ({error, returnValue}) {
      if (_hasExited) {
        return
      }
      _hasExited = true

      clearTimeout(killTimeout)
      // page.close will error if page/browser has already been closed;
      // try to avoid
      if (page && !(error && error.toString().indexOf('Target closed' > -1))) {
        // must await here, otherwise will receive errors if closing
        // browser before page is properly closed
        await page.close()
      }
      if (error) {
        reject(error)
        return
      }
      resolve(returnValue)
    }
    killTimeout = setTimeout(() => {
      cleanupAndExit({error: new Error('Penthouse timed out after ' + timeout / 1000 + 's. ')})
    }, timeout)

    try {
      page = await browser.newPage()
      debuglog('new page opened in browser')

      await page.setViewport({ width, height })
      debuglog('viewport set')

      if (blockJSRequests) {
        // crashes..
        // await page.setJavaScriptEnabled(false)
        await blockJsRequests(page)
        debuglog('blocking js requests')
      }
      page.on('console', msg => {
        // pass through log messages
        // - the ones sent by penthouse for debugging has 'debug: ' prefix.
        if (/^debug: /.test(msg)) {
          debuglog(msg.replace(/^debug: /, ''))
        }
      })

      // NOTE: have to set a timeout here,
      // even though we have our own timeout above,
      // just to override the default puppeteer timeout of 30s
      await page.goto(url, {timeout})
      debuglog('page loaded')

      if (!page) {
        // in case we timed out
        return
      }
      const criticalRules = await page.evaluate(pruneNonCriticalCss, {
        astRules,
        forceInclude,
        renderWaitTime
      })

      debuglog('GENERATION_DONE')
      cleanupAndExit({returnValue: criticalRules})
    } catch (e) {
      cleanupAndExit({error: e})
    }
  })
}

export default pruneNonCriticalCssLauncher
<commit_msg>core: Fix block all js requests<commit_after>import pruneNonCriticalCss from './browser-sandbox/pruneNonCriticalCss'

async function blockJsRequests (page) {
  await page.setRequestInterceptionEnabled(true)
  page.on('request', interceptedRequest => {
    if (/\.js(\?.*)?$/.test(interceptedRequest.url)) {
      interceptedRequest.abort()
    } else {
      interceptedRequest.continue()
    }
  })
}

async function pruneNonCriticalCssLauncher ({
  browser,
  url,
  astRules,
  width,
  height,
  forceInclude,
  userAgent,
  timeout,
  renderWaitTime,
  blockJSRequests,
  customPageHeaders = {},
  debuglog
}) {
  let _hasExited = false

  return new Promise(async (resolve, reject) => {
    debuglog('Penthouse core start')
    let page
    let killTimeout
    async function cleanupAndExit ({ error, returnValue }) {
      if (_hasExited) {
        return
      }
      _hasExited = true

      clearTimeout(killTimeout)
      // page.close will error if page/browser has already been closed;
      // try to avoid
      if (page && !(error && error.toString().indexOf('Target closed' > -1))) {
        // must await here, otherwise will receive errors if closing
        // browser before page is properly closed
        await page.close()
      }
      if (error) {
        reject(error)
        return
      }
      resolve(returnValue)
    }
    killTimeout = setTimeout(() => {
      cleanupAndExit({
        error: new Error('Penthouse timed out after ' + timeout / 1000 + 's. ')
      })
    }, timeout)

    try {
      page = await browser.newPage()
      debuglog('new page opened in browser')

      await page.setViewport({ width, height })
      debuglog('viewport set')

      if (blockJSRequests) {
        // crashes..
        // await page.setJavaScriptEnabled(false)
        await blockJsRequests(page)
        debuglog('blocking js requests')
      }
      page.on('console', msg => {
        // pass through log messages
        // - the ones sent by penthouse for debugging has 'debug: ' prefix.
        if (/^debug: /.test(msg)) {
          debuglog(msg.replace(/^debug: /, ''))
        }
      })

      // NOTE: have to set a timeout here,
      // even though we have our own timeout above,
      // just to override the default puppeteer timeout of 30s
      await page.goto(url, { timeout })
      debuglog('page loaded')

      if (!page) {
        // in case we timed out
        return
      }
      const criticalRules = await page.evaluate(pruneNonCriticalCss, {
        astRules,
        forceInclude,
        renderWaitTime
      })

      debuglog('GENERATION_DONE')
      cleanupAndExit({ returnValue: criticalRules })
    } catch (e) {
      cleanupAndExit({ error: e })
    }
  })
}

export default pruneNonCriticalCssLauncher
<|endoftext|>


<commit_before>/**
* @license GrapeFruit Game Engine
* Copyright (c) 2012-2014, Chad Engler
*
* GrapeFruit is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
* Known Limiting Features:
*   - Canvas
*       - IE 9+
*       - FF 2+
*       - Chrome 4+
*       - Safari 3.1+
*       - Opera 9+
*
*   - WebGL
*       - IE 11+
*       - FF 4+
*       - Chrome 8+
*       - Safari 6+
*       - Opera 12+
*
*   - Object.create
*       - IE 9+
*       - FF 4+
*       - Chrome 7+
*       - Safari 5+
*       - Opera 12+
*/

var gf = {
    //audio
    AudioManager:       require('./audio/AudioManager'),
    AudioPlayer:        require('./audio/AudioPlayer'),

    //camera
    Camera:             require('./camera/Camera'),

    //display
    BaseTexture:        require('./display/BaseTexture'),
    Container:          require('./display/Container'),
    Graphics:           require('./display/Graphics'),
    RenderTexture:      require('./display/RenderTexture'),
    Sprite:             require('./display/Sprite'),
    Texture:            require('./display/Texture'),
    TilingSprite:       require('./display/TilingSprite'),

    //fx
    fx: {
        camera: {
            Effect:     require('./fx/camera/Effect'),
            Close:      require('./fx/camera/Close'),
            Fade:       require('./fx/camera/Fade'),
            Flash:      require('./fx/camera/Flash'),
            Scanlines:  require('./fx/camera/Scanlines'),
            Shake:      require('./fx/camera/Shake')
        }
    },

    //game
    Game:               require('./game/Game'),
    State:              require('./game/State'),
    StateManager:       require('./game/StateManager'),
    World:              require('./game/World'),

    //geometry
    Circle:             require('./geom/Circle'),
    Ellipse:            require('./geom/Ellipse'),
    Polygon:            require('./geom/Polygon'),
    Rectangle:          require('./geom/Rectangle'),

    //gui
    GuiItem:            require('./gui/GuiItem'),

    //input
    Input:              require('./input/Input'),
    InputManager:       require('./input/InputManager'),
    Keyboard:           require('./input/Keyboard'),
    Gamepad:            require('./input/Gamepad'),
    GamepadButtons:     require('./input/gamepad/GamepadButtons'),
    GamepadSticks:      require('./input/gamepad/GamepadSticks'),
    Pointers:           require('./input/Pointers'),
    Pointer:            require('./input/pointer/Pointer'),

    //loader
    Loader:             require('./loader/Loader'),

    //math
    math:               require('./math/math'),
    Vector:             require('./math/Vector'),

    //particles
    ParticleEmitter:    require('./particles/ParticleEmitter'),
    ParticleSystem:     require('./particles/ParticleSystem'),

    //physics
    PhysicsSystem:      require('./physics/PhysicsSystem'),
    PhysicsTarget:      require('./physics/PhysicsTarget'),

    //text
    BitmapText:         require('./text/BitmapText'),
    Text:               require('./text/Text'),

    //tilemap
    Tile:               require('./tilemap/Tile'),
    Tilelayer:          require('./tilemap/Tilelayer'),
    Tilemap:            require('./tilemap/Tilemap'),
    Tileset:            require('./tilemap/Tileset'),
    ObjectGroup:        require('./tilemap/ObjectGroup'),

    //utils
    utils:              require('./utils/utils'),
    support:            require('./utils/support'),
    inherit:            require('./utils/inherit'),
    Cache:              require('./utils/Cache'),
    Clock:              require('./utils/Clock'),
    EventEmitter:       require('./utils/EventEmitter'),
    ObjectPool:         require('./utils/ObjectPool'),
    SpritePool:         require('./utils/SpritePool'),
    ObjectFactory:      require('./utils/ObjectFactory'),

    //plugin
    plugin:             require('./plugin'),

    //vendor files
    PIXI:               require('./vendor/pixi')
};

//replace the pixi point with a powerful vector class
gf.PIXI.Point = gf.Vector;

//copy over constants
var C = require('./constants');

for(var k in C) {
    gf[k] = C[k];
}

module.exports = gf;
<commit_msg>export controls<commit_after>/**
* @license GrapeFruit Game Engine
* Copyright (c) 2012-2014, Chad Engler
*
* GrapeFruit is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
* Known Limiting Features:
*   - Canvas
*       - IE 9+
*       - FF 2+
*       - Chrome 4+
*       - Safari 3.1+
*       - Opera 9+
*
*   - WebGL
*       - IE 11+
*       - FF 4+
*       - Chrome 8+
*       - Safari 6+
*       - Opera 12+
*
*   - Object.create
*       - IE 9+
*       - FF 4+
*       - Chrome 7+
*       - Safari 5+
*       - Opera 12+
*/

var gf = {
    //audio
    AudioManager:       require('./audio/AudioManager'),
    AudioPlayer:        require('./audio/AudioPlayer'),

    //camera
    Camera:             require('./camera/Camera'),

    //controls
    Controls:           require('./controls/Controls'),
    TopDownControls:    require('./controls/TopDownControls'),

    //display
    BaseTexture:        require('./display/BaseTexture'),
    Container:          require('./display/Container'),
    Graphics:           require('./display/Graphics'),
    RenderTexture:      require('./display/RenderTexture'),
    Sprite:             require('./display/Sprite'),
    Texture:            require('./display/Texture'),
    TilingSprite:       require('./display/TilingSprite'),

    //fx
    fx: {
        camera: {
            Effect:     require('./fx/camera/Effect'),
            Close:      require('./fx/camera/Close'),
            Fade:       require('./fx/camera/Fade'),
            Flash:      require('./fx/camera/Flash'),
            Scanlines:  require('./fx/camera/Scanlines'),
            Shake:      require('./fx/camera/Shake')
        }
    },

    //game
    Game:               require('./game/Game'),
    State:              require('./game/State'),
    StateManager:       require('./game/StateManager'),
    World:              require('./game/World'),

    //geometry
    Circle:             require('./geom/Circle'),
    Ellipse:            require('./geom/Ellipse'),
    Polygon:            require('./geom/Polygon'),
    Rectangle:          require('./geom/Rectangle'),

    //gui
    GuiItem:            require('./gui/GuiItem'),

    //input
    Input:              require('./input/Input'),
    InputManager:       require('./input/InputManager'),
    Keyboard:           require('./input/Keyboard'),
    Gamepad:            require('./input/Gamepad'),
    GamepadButtons:     require('./input/gamepad/GamepadButtons'),
    GamepadSticks:      require('./input/gamepad/GamepadSticks'),
    Pointers:           require('./input/Pointers'),
    Pointer:            require('./input/pointer/Pointer'),

    //loader
    Loader:             require('./loader/Loader'),

    //math
    math:               require('./math/math'),
    Vector:             require('./math/Vector'),

    //particles
    ParticleEmitter:    require('./particles/ParticleEmitter'),
    ParticleSystem:     require('./particles/ParticleSystem'),

    //physics
    PhysicsSystem:      require('./physics/PhysicsSystem'),
    PhysicsTarget:      require('./physics/PhysicsTarget'),

    //text
    BitmapText:         require('./text/BitmapText'),
    Text:               require('./text/Text'),

    //tilemap
    Tile:               require('./tilemap/Tile'),
    Tilelayer:          require('./tilemap/Tilelayer'),
    Tilemap:            require('./tilemap/Tilemap'),
    Tileset:            require('./tilemap/Tileset'),
    ObjectGroup:        require('./tilemap/ObjectGroup'),

    //utils
    utils:              require('./utils/utils'),
    support:            require('./utils/support'),
    inherit:            require('./utils/inherit'),
    Cache:              require('./utils/Cache'),
    Clock:              require('./utils/Clock'),
    EventEmitter:       require('./utils/EventEmitter'),
    ObjectPool:         require('./utils/ObjectPool'),
    SpritePool:         require('./utils/SpritePool'),
    ObjectFactory:      require('./utils/ObjectFactory'),

    //plugin
    plugin:             require('./plugin'),

    //vendor files
    PIXI:               require('./vendor/pixi')
};

//replace the pixi point with a powerful vector class
gf.PIXI.Point = gf.Vector;

//copy over constants
var C = require('./constants');

for(var k in C) {
    gf[k] = C[k];
}

module.exports = gf;
<|endoftext|>


<commit_before>'use strict';

/**
 * Creates a new Type editor and sets up the core
 * modules used for WYSIWYG editing. The core
 * class only holds methods for setting and retrieving
 * options as well getters and setters for instances
 * of core modules.
 *
 * @param {{}|Element} options - Either pass
 *     an associative array with options for this
 *     editor or the root element that should be
 *     used to modify its contents for WYSIWYG
 *     editing
 * @param {Element} options.el The root element
 *     that should be used to modify its contents
 *     for WYSIWYG editing
 * @constructor
 */
function Type(options) {

  // Allow passing an element as only parameter
  if (Type.DomUtilities.isNode(options)) {
    options = {el: options};
  }

  // If no element has been passed, interrupt
  if (!options.el) {
    throw new Error('You must provide an element as root node for the editor\'s contents.');
  }

  // Set settings for this editor
  this._root = null;
  this._options = null;
  this.options(options);

  // Enable editing mode on root element
  this._setElementEditable(this._root);

  // Trigger events
  Type.trigger('ready', this);

}

/**
 * Inherit event system
 */
Type.OOP.inherits(Type, Type.Events);

(function() {

  /**
   * Allows fast detection if an object is a Type Editor
   * instance (or class)
   *
   * @type {boolean}
   */
  this.typeEditor = true;

  /**
   * Holds the default options for every editor. These options
   * will be extended by the options passed to each instance
   * on instantiation.
   *
   * @type {{el: null, undoSteps: number}}
   * @private
   */
  this._defaultOptions = {
    el: null,
    undoSteps: 20,
  };

  /**
   * Sets or gets the options to be used by this Type instance.
   * Parameters can be passed as you know it from jQuery:
   *
   * Pass a single string to get an option:
   * this.options('el')
   * returns your editor's TypeContents baseelement
   *
   * Pass a name value combination to set a specific option
   * this.options('el', myElement)
   * sets the base element
   *
   * Pass an object to set multiple options
   * this.options({el: myElement, foo:bar})
   * sets both parameters
   *
   * @param {(string|{el: Element}|{}|*)} options - Either a plain object
   *     with keys and values to be set or a string that will
   *     be used as a name for a option. If you pass a string,
   *     pass a second parameter to set that option or no
   *     second parameter to retrieve that option.
   * @param {*} [value] - If the first parameter is a string,
   *     this value will be set to the key of the given first
   *     parameter. Any arbitrary value can be set.
   * @returns {Type|*} Returns the type instance if you set an
   *     option or the according value if you get an option
   */
  this.options = function(options, value) {

    var opts;

    // Load default options if there are no instance options yet
    this._options = this._options || Type.Utilities.extend({}, this._defaultOptions);

    // Pass a single option name to fetch it
    if (typeof options === 'string' && arguments.length === 1) {
      return this._options[options];
    }

    // Pass an option name and a value to set it
    if (typeof options === 'string' && arguments.length === 2) {
      opts = {};
      opts[options] = value;
      options = opts;
    }

    // Pass an object of key-values to set them
    if (typeof options === 'object') {
      Type.Utilities.extend(this._options, options);
    }

    // If the el option has been passed copy it for quick access
    if (options.el) {
      this._root = options.el;
    }

    // Chaining
    return arguments.length ? this : this._options;

  };

  /**
   * Creates a {Type.DomWalker} that ist constrained to this
   * instance's root element unless you explicitly pass a
   * constrainingNode as argument. All other DomWalker options
   * can also be passed to this as usual.
   *
   * @param {Node} node - Any DOM {Node} to be set as starting
   *     node for the DomWalker
   * @param {Node|string|Function|{constrainingNode: Node, filter: string|Function}} [options]
   *     See {Type.DomWalker} for a description of possible arguments
   * @returns {Type.DomWalker}
   */
  this.createDomWalker = function(node, options) {
    options = Type.DomWalker.loadOptions(options || {});
    options.constrainingNode = options.constrainingNode || this._root;
    return new Type.DomWalker(node, options);
  };

  /**
   * Getter for this instance's root element, i.e. the
   * element that contains this editor's text.
   * @returns {Element}
   */
  this.getRoot = function() {
    return this._root;
  };

  /**
   * Sets the editing mode of an element. The second parameter
   * determines if the editing mode should be enabled or disabled.
   * If no second parameter is give this defaults to true.
   *
   * @param {Element} el - The element to set the editing mode for
   * @param {boolean|string} val - Set to true to enable editing mode
   *     or false to disable it
   * @returns {Type}
   * @private
   */
  this._setElementEditable = function(el, val) {
    val = !val ? 'false' : 'true';
    el.setAttribute('contenteditable', val);
    return this;
  };

}).call(Type.prototype);

/**
 * Exposes Type's prototype as jQuery-style shorthand variable
 * @type {Object}
 */
Type.fn = Type.prototype;

/**
 * The namespace for Type actions
 * @type {{}}
 */
Type.Actions = {};

/**
 * Module Exports for CommonJs
 * @type {Type}
 */
module.exports = Type;
<commit_msg>Started reworking type js<commit_after>'use strict';

/**
 * Creates a new Type editor and sets up the core
 * modules used for WYSIWYG editing. The core
 * class only holds methods for setting and retrieving
 * options as well getters and setters for instances
 * of core modules.
 *
 * @param {{}|Element} options - Either pass
 *     an associative array with options for this
 *     editor or the root element that should be
 *     used to modify its contents for WYSIWYG
 *     editing
 * @param {Element} options.el The root element
 *     that should be used to modify its contents
 *     for WYSIWYG editing
 * @constructor
 */
function Type(options) {

  // Allow passing an element as only parameter
  if (Type.DomUtilities.isNode(options)) {
    options = {el: options};
  }

  // If no element has been passed, interrupt
  if (!options.el) {
    throw new Error('You must provide an element as root node for the editor\'s contents.');
  }

  // Set settings for this editor
  this._root = null;
  this._options = null;
  this.options(options);

  // Enable editing mode on root element
  this._setElementEditable(this._root);

  // Trigger events
  Type.trigger('ready', this);

}

/**
 * Inherit event system
 */
Type.OOP.inherits(Type, Type.Events);

(function() {

  /**
   * Allows fast detection if an object is a Type Editor
   * instance (or class)
   *
   * @type {boolean}
   */
  this.typeEditor = true;

  /**
   * Holds the default options for every editor. These options
   * will be extended by the options passed to each instance
   * on instantiation.
   *
   * @type {{el: null, undoSteps: number}}
   * @private
   */
  this._defaultOptions = {
    el: null,
    undoSteps: 20,
  };

  /**
   * Sets or gets the options to be used by this Type instance.
   * Parameters can be passed as you know it from jQuery:
   *
   * Pass a single string to get an option:
   * this.options('el')
   * returns your editor's TypeContents baseelement
   *
   * Pass a name value combination to set a specific option
   * this.options('el', myElement)
   * sets the base element
   *
   * Pass an object to set multiple options
   * this.options({el: myElement, foo:bar})
   * sets both parameters
   *
   * @param {(string|{el: Element}|{}|*)} options - Either a plain object
   *     with keys and values to be set or a string that will
   *     be used as a name for a option. If you pass a string,
   *     pass a second parameter to set that option or no
   *     second parameter to retrieve that option.
   * @param {*} [value] - If the first parameter is a string,
   *     this value will be set to the key of the given first
   *     parameter. Any arbitrary value can be set.
   * @returns {Type|*} Returns the type instance if you set an
   *     option or the according value if you get an option
   */
  this.options = function(options, value) {

    var opts;

    // Load default options if there are no instance options yet
    this._options = this._options || Type.Utilities.extend({}, this._defaultOptions);

    // Pass a single option name to fetch it
    if (typeof options === 'string' && arguments.length === 1) {
      return this._options[options];
    }

    // Pass an option name and a value to set it
    if (typeof options === 'string' && arguments.length === 2) {
      opts = {};
      opts[options] = value;
      options = opts;
    }

    // Pass an object of key-values to set them
    if (typeof options === 'object') {
      Type.Utilities.extend(this._options, options);
    }

    // If the el option has been passed copy it for quick access
    if (options.el) {
      this._root = options.el;
    }

    // Chaining
    return arguments.length ? this : this._options;

  };

  /**
   * Creates a {Type.DomWalker} that ist constrained to this
   * instance's root element unless you explicitly pass a
   * constrainingNode as argument. All other DomWalker options
   * can also be passed to this as usual.
   *
   * @param {Node} node - Any DOM {Node} to be set as starting
   *     node for the DomWalker
   * @param {Node|string|Function|{constrainingNode: Node, filter: string|Function}} [options]
   *     See {Type.DomWalker} for a description of possible arguments
   * @returns {Type.DomWalker}
   */
  this.createDomWalker = function(node, options) {
    options = Type.DomWalker.loadOptions(options || {});
    options.constrainingNode = options.constrainingNode || this._root;
    return new Type.DomWalker(node, options);
  };

  /**
   * Getter for this instance's root element, i.e. the
   * element that contains this editor's text.
   * @returns {Element}
   */
  this.getRoot = function() {
    return this._root;
  };

  /**
   * Sets the editing mode of an element. The second parameter
   * determines if the editing mode should be enabled or disabled.
   * If no second parameter is give this defaults to true.
   *
   * @param {Element} el - The element to set the editing mode for
   * @param {boolean|string} [val] - Set to true to enable editing mode
   *     or false to disable it. Optional, defaults to true.
   * @returns {Type}
   * @private
   */
  this._setElementEditable = function(el, val) {
    val = !val ? 'false' : 'true';
    el.setAttribute('contenteditable', val);
    return this;
  };

}).call(Type.prototype);

/**
 * Exposes Type's prototype as jQuery-style shorthand variable
 * @type {Object}
 */
Type.fn = Type.prototype;

/**
 * The namespace for Type actions
 * @type {{}}
 */
Type.Actions = {};

/**
 * Module Exports for CommonJs
 * @type {Type}
 */
module.exports = Type;
<|endoftext|>


<commit_before>//==================================================
// 数据缓存模块
//==================================================
$.define("data", "lang", function(){
    //$.log("已加载data模块");
    var remitter = /object|function/;
    $.mix( $, {
        _db: {},
        // 读写数据
        data : function( target, name, data, pvt ) {
            if(target && remitter.test(typeof target)){//只处理HTML节点与普通对象
                var id = $.getUid(target), isEl = target.nodeType === 1
                if(name === "@uuid"){
                    return id;
                }
                var getByName = typeof name === "string",
                database = isEl ? $._db: target,
                table = database[ "@data_"+id ] || (database[ "@data_"+id ] = {
                    data:{}
                });
                var inner = table
                if(isEl && !table.parsedAttrs){
                    var attrs = target.attributes;
                    //将HTML5单一的字符串数据转化为mass多元化的数据，并储存起来
                    for ( var i = 0, attr; attr = attrs[i++];) {
                        var key = attr.name;
                        if ( key.indexOf( "data-" ) === 0 ) {
                            $.parseData(target, key, id, table.data);
                        }
                    }
                    table.parsedAttrs = true;
                }
                if ( !pvt ) {
                    table = table.data;
                }
                if ( name && typeof name == "object" ) {
                    $.mix(table, name);
                }else if(getByName && data !== void 0){
                    table[ name ] = data;
                }
                if(getByName){
                    return isEl && !pvt && name.indexOf("data-") === 0 ? $.parseData( target, name, id, inner ) : table[ name ];
                }else{
                    return table
                }
            }
        },//仅内部调用
        _data:function(target,name,data){
            return $.data(target, name, data, true)
        },
        parseData: function(target, name, id, table){
            if( table && (name + id) in table){//如果已经转换过
                return table[ name + id ];
            }else{
                var data = target.getAttribute( name );
                if ( typeof data === "string") {//转换
                    try {
                        data = eval("0,"+ data );
                    } catch( e ) {
                        $.log("$.parseData error : "+ e)
                    }
                    if(table){
                        table[ name + id ] = data
                    }
                }else{
                    data = void 0;
                }
                return data;
            }
        },
        //移除数据
        removeData : function(target, name, pvt){
            if(target && remitter.test(typeof target)){
                var id =  $.getUid(target);
                if (  !id ) {
                    return;
                }
                var  clear = 1, ret = typeof name == "string",
                database = target.nodeType === 1  ? $._db : target,
                table = database["@data_"+id] ;
                if ( table && ret ) {
                    if(!pvt){
                        table = table.data
                    }
                    if(table){
                        ret = table[ name ];
                        delete table[ name ];
                    }
                    var cache = database["@data_"+id];
                        loop:
                        for(var key in cache){
                            if(key == "data"){
                                for(var i in cache.data){
                                    clear = 0;
                                    break loop;
                                }
                            }else{
                                clear = 0;
                                break loop;
                            }
                        }
                }
                if(clear){
                    delete database["@data_"+id];
                }
                return ret;
            }
        },
        //合并数据
        mergeData:function(neo, src){
            var srcData = $._data(src), neoData = $._data(neo), events = srcData.events;
            if(srcData && neoData){
                $.Object.merge( neoData, srcData );
                if(events){
                    delete neoData.callback;
                    neoData.events = {};
                    for ( var type in events ) {
                        for (var i = 0, obj ; obj =  events[ type ][i++]; ) {
                            $.event.bind.call( neo, obj );
                        }
                    }
                }
            }
        }
    });
});

/**
2011.9.27 uniqueID改为uniqueNumber 简化data与removeData
2011.9.28 添加$._data处理内部数据
2011.10.21 强化mergeData，可以拷贝事件
2012.1.31 简化$.Object.merge的调用
2012.4.5 修正mergeData BUG, 让$.data能获取HTML5 data-*
*/
<commit_msg> $._db -> $["@data]<commit_after>//==================================================
// 数据缓存模块
//==================================================
$.define("data", "lang", function(){
    //$.log("已加载data模块");
    var remitter = /object|function/;
    $.mix( $, {
        "@data": {},
        // 读写数据
        data : function( target, name, data, pvt ) {
            if(target && remitter.test(typeof target)){//只处理HTML节点与普通对象
                var id = $.getUid(target), isEl = target.nodeType === 1
                if(name === "@uuid"){
                    return id;
                }
                var getByName = typeof name === "string",
                database = isEl ? $["@data"]: target,
                table = database[ "@data_"+id ] || (database[ "@data_"+id ] = {
                    data:{}
                });
                var inner = table
                if(isEl && !table.parsedAttrs){
                    var attrs = target.attributes;
                    //将HTML5单一的字符串数据转化为mass多元化的数据，并储存起来
                    for ( var i = 0, attr; attr = attrs[i++];) {
                        var key = attr.name;
                        if ( key.indexOf( "data-" ) === 0 ) {
                            $.parseData(target, key, id, table.data);
                        }
                    }
                    table.parsedAttrs = true;
                }
                if ( !pvt ) {
                    table = table.data;
                }
                if ( name && typeof name == "object" ) {
                    $.mix(table, name);
                }else if(getByName && data !== void 0){
                    table[ name ] = data;
                }
                if(getByName){
                    return isEl && !pvt && name.indexOf("data-") === 0 ? $.parseData( target, name, id, inner ) : table[ name ];
                }else{
                    return table
                }
            }
        },//仅内部调用
        _data:function(target,name,data){
            return $.data(target, name, data, true)
        },
        parseData: function(target, name, id, table){
            if( table && (name + id) in table){//如果已经转换过
                return table[ name + id ];
            }else{
                var data = target.getAttribute( name );
                if ( typeof data === "string") {//转换
                    try {
                        data = eval("0,"+ data );
                    } catch( e ) {
                        $.log("$.parseData error : "+ e)
                    }
                    if(table){
                        table[ name + id ] = data
                    }
                }else{
                    data = void 0;
                }
                return data;
            }
        },
        //移除数据
        removeData : function(target, name, pvt){
            if(target && remitter.test(typeof target)){
                var id =  $.getUid(target);
                if (  !id ) {
                    return;
                }
                var  clear = 1, ret = typeof name == "string",
                database = target.nodeType === 1  ? $["@data"] : target,
                table = database["@data_"+id] ;
                if ( table && ret ) {
                    if(!pvt){
                        table = table.data
                    }
                    if(table){
                        ret = table[ name ];
                        delete table[ name ];
                    }
                    var cache = database["@data_"+id];
                        loop:
                        for(var key in cache){
                            if(key == "data"){
                                for(var i in cache.data){
                                    clear = 0;
                                    break loop;
                                }
                            }else{
                                clear = 0;
                                break loop;
                            }
                        }
                }
                if(clear){
                    delete database["@data_"+id];
                }
                return ret;
            }
        },
        //合并数据
        mergeData:function(neo, src){
            var srcData = $._data(src), neoData = $._data(neo), events = srcData.events;
            if(srcData && neoData){
                $.Object.merge( neoData, srcData );
                if(events){
                    delete neoData.callback;
                    neoData.events = {};
                    for ( var type in events ) {
                        for (var i = 0, obj ; obj =  events[ type ][i++]; ) {
                            $.event.bind.call( neo, obj );
                        }
                    }
                }
            }
        }
    });
});

/**
2011.9.27 uniqueID改为uniqueNumber 简化data与removeData
2011.9.28 添加$._data处理内部数据
2011.10.21 强化mergeData，可以拷贝事件
2012.1.31 简化$.Object.merge的调用
2012.4.5 修正mergeData BUG, 让$.data能获取HTML5 data-*
2012.5.2 $._db -> $["@data]
*/
<|endoftext|>


<commit_before>let Entity = require('azure-entities');

module.exports = {};

/**
 * Entity for tracking which task-groups are associated
 * with which org/repo/sha, etc.
 *
 */
module.exports.Build = Entity.configure({
  version: 1,
  partitionKey: Entity.keys.StringKey('taskGroupId'),
  rowKey: Entity.keys.ConstantKey('taskGroupId'),
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
  },
}).configure({
  version: 2,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    // GitHub installation ID that comes from the webhook
    // Needed for authentication in statusHandler
    installationId: Entity.types.Number,
  },
  migrate: function(item) {
    item.installationId = 0;
    return item;
  },
}).configure({
  version: 3,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    installationId: Entity.types.Number,
    eventType: Entity.types.String,
  },
  migrate: function(item) {
    item.eventType = 'Unknown Event';
    return item;
  },
}).configure({
  version: 4,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    installationId: Entity.types.Number,
    eventType: Entity.types.String,
    eventId: Entity.types.String,
  },
  migrate: function(item) {
    item.Id = 'Unknown';
    return item;
  },
});
<commit_msg>Fix a bad migration<commit_after>let Entity = require('azure-entities');

module.exports = {};

/**
 * Entity for tracking which task-groups are associated
 * with which org/repo/sha, etc.
 *
 */
module.exports.Build = Entity.configure({
  version: 1,
  partitionKey: Entity.keys.StringKey('taskGroupId'),
  rowKey: Entity.keys.ConstantKey('taskGroupId'),
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
  },
}).configure({
  version: 2,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    // GitHub installation ID that comes from the webhook
    // Needed for authentication in statusHandler
    installationId: Entity.types.Number,
  },
  migrate: function(item) {
    item.installationId = 0;
    return item;
  },
}).configure({
  version: 3,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    installationId: Entity.types.Number,
    eventType: Entity.types.String,
  },
  migrate: function(item) {
    item.eventType = 'Unknown Event';
    return item;
  },
}).configure({
  version: 4,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    installationId: Entity.types.Number,
    eventType: Entity.types.String,
    eventId: Entity.types.String,
  },
  migrate: function(item) {
    item.Id = 'Unknown';
    return item;
  },
}).configure({
  version: 5,
  properties: {
    organization: Entity.types.String,
    repository: Entity.types.String,
    sha: Entity.types.String,
    taskGroupId: Entity.types.String,
    state: Entity.types.String,
    created: Entity.types.Date,
    updated: Entity.types.Date,
    installationId: Entity.types.Number,
    eventType: Entity.types.String,
    eventId: Entity.types.String,
  },
  migrate: function(item) {
    // Delete Id because it was mistakenly set in the last migration
    delete item.Id; // Just in case the migrations are chained
    item.eventId = item.eventId || 'Unknown';
    return item;
  },
});
<|endoftext|>


<commit_before>// // const Ned = require('nedb');

// // const work = new Ned({
// //     filename: `assets/data/time.manager.work.db`,
// //     timestampData: true,
// //     autoLoad: true
// // });

// // const menu = new Ned({
// //     filename: `assets/data/time.manager.menu.db`,
// //     autoLoad: true
// // })

// // db = {
// //     work: work,
// //     menu: menu
// // }

// // module.exports = db;

// // class Database {
// //     constructor(name, collections) {
// //         this.collections = [];
// //         collections.forEach(col => {
// //            this.collections.push(new Ned({filename: `assets/data/${name}.${col}.db`,
// //                                     autoLoad)
// //         });
// //     }
// // }

// class Collection {
//     constructor(filename) {
//         // this.store = new Ned({filename: filename, autoLoad: true})
//         this.strings = []
//         filename.forEach(test => {
//             for (var k in test) {
//                 if (typeof test[k] == 'function') {
//                     test[k] = this._serialize(test[k], test)
//                     console.log(test[k])
//                     test[k] = this._deserialize(test[k])
//                     console.log(test[k])
//                 }
//             }

//         })
//     }

//     add(obj) {
//         for (var k in obj) {
//             if (typeof obj[k] == 'function') {
//                 this.obj[k] = JSON.stringify(obj[k])
//             }
//         }
//     }

//     _serialize(func, owner) {
//         var signature
//         var body

//         return JSON.stringify({ signature: func.toString(), owner: owner})
//     }

//     _deserialize(str) {
//         var parsed = JSON.parse(str);
//         return this._createFunction(parsed.func, parsed.owner);
//     }

//     _createFunction(func, owner) {
//         return (new Function(this._createFunctionBody(func, owner))(owner));
//     }

//     _createFunctionBody(func, owner) {
//         return Object.keys(owner).reduceRight(this._addVar, 'return ' + func + ';');
//     }

//     _addVar(s, k) {
//         return 'var ' + k + '= argument[0].' + k + ';\n' + s
//     }

// }

// const testArrat = [{
//         label: 'File',
//         accelerator: 'CmdOrCtrl+R',
//         click (item, focusedWindow) {
//         focusedWindow.loadUrl(__dirname + '/index.html');
//         }
//     },{
//         label: 'Close Window',
//         accelerator: 'CmdOrCtrl+W',
//         click(item, focusedWindow) {
//             focusedWindow.close();
//         }
//         },{
//         label: 'Quit',
//         accelerator: 'CmdOrCtrl+Q',
//         click(item, focusedWindow) {
//             app.quit();
//         }
//     }]

// function t() {
//     var c = new Collection(testArrat)
// }
// t()<commit_msg>uncomment nedb logic<commit_after>const Ned = require('nedb');

const work = new Ned({
    filename: `assets/data/time.manager.work.db`,
    timestampData: true,
    autoLoad: true
});

const menu = new Ned({
    filename: `assets/data/time.manager.menu.db`,
    autoLoad: true
})

db = {
    work: work,
    menu: menu
}

module.exports = db;

class Database {
    constructor(name, collections) {
        this.collections = [];
        collections.forEach(col => {
           this.collections.push(new Ned({filename: `assets/data/${name}.${col}.db`,
                                    autoLoad)
        });
    }
}

class Collection {
    constructor(filename) {
        // this.store = new Ned({filename: filename, autoLoad: true})
        this.strings = []
        filename.forEach(test => {
            for (var k in test) {
                if (typeof test[k] == 'function') {
                    test[k] = this._serialize(test[k], test)
                    console.log(test[k])
                    test[k] = this._deserialize(test[k])
                    console.log(test[k])
                }
            }

        })
    }

    add(obj) {
        for (var k in obj) {
            if (typeof obj[k] == 'function') {
                this.obj[k] = JSON.stringify(obj[k])
            }
        }
    }

    _serialize(func, owner) {
        var signature
        var body

        return JSON.stringify({ signature: func.toString(), owner: owner})
    }

    _deserialize(str) {
        var parsed = JSON.parse(str);
        return this._createFunction(parsed.func, parsed.owner);
    }

    _createFunction(func, owner) {
        return (new Function(this._createFunctionBody(func, owner))(owner));
    }

    _createFunctionBody(func, owner) {
        return Object.keys(owner).reduceRight(this._addVar, 'return ' + func + ';');
    }

    _addVar(s, k) {
        return 'var ' + k + '= argument[0].' + k + ';\n' + s
    }

}

const testArrat = [{
        label: 'File',
        accelerator: 'CmdOrCtrl+R',
        click (item, focusedWindow) {
        focusedWindow.loadUrl(__dirname + '/index.html');
        }
    },{
        label: 'Close Window',
        accelerator: 'CmdOrCtrl+W',
        click(item, focusedWindow) {
            focusedWindow.close();
        }
        },{
        label: 'Quit',
        accelerator: 'CmdOrCtrl+Q',
        click(item, focusedWindow) {
            app.quit();
        }
    }]

function t() {
    var c = new Collection(testArrat)
}
t()<|endoftext|>


<commit_before>const demo = () => 'what the hell? how do I test my component???';

export default demo;
<commit_msg>Remove unused demo.js file<commit_after><|endoftext|>