Skip to content
Avatar
:octocat:
Focusing
:octocat:
Focusing
Block or Report

Block or report ps-19

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
ps-19/README.md

Hi there 👋

All Projects are OPEN SOURCE. Feel Free to Fork, submit PR and raise issues.

𝐇𝐞𝐥𝐥𝐨, 𝚌𝚘𝚍𝚎𝚛𝚜!

All Projects are OPEN SOURCE. Feel Free to Fork, submit PR and raise issues.

  • 🔭 I’m currently working on 𝙳𝚊𝚝𝚊 𝚂𝚌𝚒𝚎𝚗𝚌𝚎 𝚊𝚗𝚍 𝚆𝚎𝚋 𝙳𝚎𝚟𝚎𝚕𝚘𝚙𝚖𝚎𝚗𝚝
  • 🌱 I’m currently learning 𝙳𝚎𝚟𝙾𝚙𝚜 𝚊𝚗𝚍 𝙲𝚘𝚖𝚙𝚎𝚝𝚒𝚝𝚒𝚟𝚎 𝙿𝚛𝚘𝚐𝚛𝚊𝚖𝚖𝚒𝚗𝚐
  • 👯 I’m looking to collaborate on 𝙰𝚗𝚍𝚛𝚘𝚒𝚍, 𝙳𝚊𝚝𝚊 𝚂𝚌𝚒𝚎𝚗𝚌𝚎 𝚘𝚛 𝚆𝚎𝚋 D𝚎𝚟𝚎𝚕𝚘𝚙𝚖𝚎𝚗𝚝
  • 💬 Ask me about here ! 𝙸 𝚊𝚖 𝚑𝚊𝚙𝚙𝚢 𝚝𝚘 𝚑𝚎𝚕𝚙.
  • 😄 𝙿𝚛𝚘𝚗𝚘𝚞𝚗𝚜 : 𝙷𝚎/𝙷𝚒𝚖/𝙷𝚒𝚜

    𝚙𝚛𝚘𝚏𝚒𝚕𝚎 𝚟𝚒𝚎𝚠𝚜𝙶𝚒𝚝𝙷𝚞𝚋 𝚏𝚘𝚕𝚕𝚘𝚠𝚎𝚛𝚜𝚃𝚘𝚝𝚊𝚕 𝚂𝚝𝚊𝚛𝚜

𝚝𝚛𝚘𝚙𝚑𝚢

𝙻𝙰𝙽𝙶𝚄𝙰𝙶𝙴𝚂 𝙰𝙽𝙳 𝚃𝙾𝙾𝙻𝚂:



𝚐𝚒𝚝𝚑𝚞𝚋 𝚐𝚛𝚊𝚙𝚑

📈 𝙶𝚒𝚝𝚑𝚞𝚋 𝚂𝚝𝚊𝚝𝚜 :

All Projects are OPEN SOURCE. Feel Free to Fork, submit PR and raise issues. 𝙶𝚒𝚝𝚑𝚞𝚋 𝙲𝚘𝚗𝚝𝚛𝚒𝚋𝚞𝚝𝚒𝚘𝚗 𝙶𝚛𝚊𝚙𝚑

Run The Following Javascript Code In Your Browser Console and See The Magic:

Code

  • Right Click open inspect.
  • Go to console.
  • Allow Pasting in Chrome, Firefox, Safari etc. in your browser.
  • Now Paste Below Code and Hit Enter again.

var genParser = (function(tys, tree, start) {
  var source, index;
  var treeRewrite = tree;
  //Apparently, you don't tokenize and then parse, you do it on the go, but with more specific techniques which people call grammars, oh well, how was I suppesd to know that anyway.
  //reference {type:"type",is:"type"} "hue"
  //repetition {type:"repeat",optional:false,from:1,to:Infinity,contains:{},delimiting:null,multipleDelimeters:null} optional to and from are defaulted, delimiters can be used for lists like a,b,c and stuff
  //array {type:"tyArray",contains:[]}
  //alternate  {type:"alternate",contains:[]}
  //Expression {type:"expression",contains:{},operators:[{precedence:1,rightAssociative:false,tokens:[]}}],delimeters=[["(",")"]],whiteSpaceIgnore:null}
  var mains = { //START PARSE
    type: "type",
    is: start
  }
  //yay extendibility
  var funcs = { //funcions/types used, hue
    expression: function(o) { //parse it like an expression
      //this is probably a little bit hard to understand
      var r = {
          type: "alternate",
          contains: [o.contains]
        }, //is it a token, an operator, or a parenthesis?
        opers = {
          type: "alternate",
          contains: []
        },
        delims = {
          type: "alternate",
          contains: []
        },
        i, I, l, L, props, t, n, ret = {},
        _ind = index,
        EXPRS = [],
        OPERATORS = [],
        O, precedence, rightAssociative, arg1, arg2, k; //I use and reuse most variables I can, damn
      if (O = o.operators) {
        for (i = 0, l = O.length; i < l; i++) {
          for (I = 0, L = O[i].tokens.length; I < L; I++) {
            t = O[i].tokens[I];
            if (o.whiteSpaceIgnore) {
              if (typeof t === "string") {
                opers.contains.push(new RegExp("\\s*(?:" + t.replace(/([-+\\?.!$^&*(){}[\]])/g, "\\$1") + ")\\s*"));
              } else if (t instanceof RegExp) {
                opers.contains.push(new RegExp("\\s*(?:" + t.source + ")\\s*", (t.multiline ? "m" : "") + (t.ignoreCase ? "i" : "")))
              } else {
                opers.contains.push({
                  type: "tyArray",
                  contains: [/\s*/, t, /\s*/]
                }); /*Ahh I HATE THIS! D:*/
              }
            } else {
              opers.contains.push(t);
            }
          }
        }
        r.contains[1] = opers; //ADD THEM TO THE LIST
      }
      if (O = o.delimeters) { //this is like a carbon copy of the previous if, should I try to make it a function? Don't repeat yourself
        for (i = 0, l = O.length; i < l; i++) {
          for (I = 0, L = O[i].length; I < L; I++) {
            t = O[i][I];
            if (o.whiteSpaceIgnore) {
              if (typeof t === "string") {
                delims.contains.push(new RegExp("\s*(?:" + t + ")\s*"));
              } else if (t instanceof RegExp) {
                delims.contains.push(new RegExp("\s*(?:" + t.source + ")\s*", (t.multiline ? "m" : "") + (t.ignoreCase ? "i" : "")))
              } else {
                delims.contains.push({
                  type: "tyArray",
                  contains: [/\s*/, t, /\s*/]
                }); /*Ahh I HATE THIS! D:*/
              }
            } else {
              delims.contains.push(t);
            }
          }
        }
        r.contains[2] = delims;
      }
      /*Shunting Yard Algorithm*/
      while (n = isIndexItem(r, props = {})) { //While there are tokens to be read
        //read a token
        if (props._matched === r.contains[0]) { //If the token is a number, then add it to the output queue.
          EXPRS.push(n);
        } else
        if (props._matched === opers) { //If the token is an operator, o1, then
          if ((I = opers.contains.indexOf(props.props._matched)) !== -1) {
            for (i = 0, l = (O = o.operators).length, k = 0; i < l; i++) { //
              if ((k += O[i].tokens.length) > I) {
                precedence = O[i].precedence;
                rightAssociative = O[i].rightAssociative;
                break;
              }
            }
          } else {
            throw new Error("props.props._matched not found at oper.contains, This is impossible.. or is it?");
          }
          while ((L = OPERATORS.length) && (((!rightAssociative) && precedence === OPERATORS[L - 1][1]) || precedence < OPERATORS[L - 1][1])) { //while there is an operator token, o2, at the top of the stack, and
            //either o1 is left-associative and its precedence is equal to that of o2,
            //or o1 has precedence less than that of o2,
            /*POPPINGG!!*/
            //pop o2 off the stack, onto the output queue;
            //This popping is also a bit of PRN execution, basically it is shunting yard and prn, or something weird
            arg2 = EXPRS.pop();
            arg1 = EXPRS.pop();
            if (!(EXPRS.length || arg1)) {
              console.warn("NOT ENOUGH TERMS");
            }
            t = OPERATORS.pop();
            for (i = 0, l = (O = o.operators).length, k = 0; i < l; i++) {
              if ((k += O[i].tokens.length) > t[2]) {
                EXPRS.push({
                  operation: O[i].tokens[t[2] - (k - O[i].tokens.length)],
                  op: t[0],
                  arguments: [arg1, arg2],
                  name: "operator"
                });
                break;
              }
            }
          }
          OPERATORS.push([n, precedence, I]);
        } else
        if (props._match === delims) {} else {
          throw Error("This is impossible! It has matched an unknown value..???");
        }
      }
      //When there are no more tokens to read
      while (L = OPERATORS.length) { //While there are still operator tokens in the stack
        //Pop the operator onto the output queue.
        arg2 = EXPRS.pop();
        arg1 = EXPRS.pop();
        if (!(EXPRS.length || arg1)) {
          console.warn("NOT ENOUGH TERMS");
        }
        t = OPERATORS.pop();
        for (i = 0, l = (O = o.operators).length, k = 0; i < l; i++) {
          if ((k += O[i].tokens.length) > t[2]) {
            EXPRS.push({
              operation: O[i].tokens[t[2] - (k - O[i].tokens.length)],
              op: t[0],
              arguments: [arg1, arg2],
              name: "operator"
            });
            break;
          }
        }
      }
      if (EXPRS.length < 1) {
        return null;
      }
      if (EXPRS.length !== 1) {
        throw new Error("Operators and expressions mismatch!!");
      }
      return EXPRS[0];
    },
    type: function(o) { //get type and parse it
      var props = {},
        a = isIndexItem(tys[o.is], props),
        t, ret; //this is where props originally started, in short words, it is used to pass properties from other functions to here 
      if (a === null) return null;
      //console.log()
      ret = {
        type: (t = tys[o.is]) && (t.delimiting ? "list" : t.type || ((typeof t === "string" || t instanceof RegExp) ? "String" : undefined)),
        name: o.is,
        content: a
      }
      for (var k in props) {
        if (props.hasOwnProperty(k) && (!ret[k])) {
          ret[k] = props[k];
        }
      }
      return ret;
    },
    repeat: function(o, props) { //repeat
      var reto = [],
        e, d, _ind = index,
        l, p, D = o.delimiting,
        i = 0,
        p = D && o.multipleDelimeters, //say, if the delimeter is just once, there is no point in putting it each time it appears.. right? so an CSV like "abc,dfe,ege" will appear as ["abc","dfe","ege"] instead of ["abc",',',"dfe",',',"ege"]
        props2;
      d = o.contains;
      props.props = [];
      do {
        e = isIndexItem(D ? i & 1 ? D : d : d, props2 = {});
        if ((!p) && D && i & 1) {
          i++;
          if (e !== null) {
            continue;
          } else {
            break;
          }
        }
        i++;
        if (e !== null) {
          reto.push(e)
          props.props.push(props2)
        }
      } while (e !== null && i !== o.to);
      l = reto.length;
      if (((!o.optional) && l == 0) || ((!isNaN(p = o.from)) && l < p)) {
        index = _ind;
        return null;
      }
      if (D && !p) {
        props.delimeter = D
      }
      return reto;
    },
    tyArray: function(o, props) { //tokens are in some order
      var reto = [],
        e, _ind = index,
        opt = o.optional || [],
        props2;
      props.props = [];
      for (var i = 0, l = o.contains.length, d; i < l; i++) {
        d = o.contains[i];
        e = isIndexItem(d, props2 = {});
        if (e === null && (opt.indexOf(i) < 0)) {
          index = _ind;
          return null;
        }
        if (e !== null) props.props.push(props2);
        reto.push(e);
      }
      return reto;
    },
    alternate: function(o, props) { //It alternates 
      var reto = null,
        e, props2 = {};
      for (var i = 0, l = o.contains.length, d; i < l; i++) {
        d = o.contains[i];
        e = isIndexItem(d, props2);
        if (e !== null) {
          reto = e;
          props.props = props2;
          props._matched = d;
          break;
        }
      }
      return reto;
    }
  }

  function isIndexItem(item, props) { //recursive
    //returns item or null
    var s, t, r,
      f;
    if (!item) {
      return null
    } else
    if (item instanceof RegExp) {
      r = new RegExp
      r.compile("^(?:" + item.source + ")", (item.multiline ? "m" : "") + (item.eturnignoreCase ? "i" : ""))
      //r.lastIndex = index;
      s = r.exec(source.substr(index)); //RAAAWR damn it
      t = s && s[0];
      if (t === null) return null;
      index += t.length;
      return t;
    } else if (typeof item == "string") { //literal match
      //console.log("DOES "+item+" and"+source.substr(index,item.length)+" MATCHES??");
      if (item === source.substr(index, item.length)) return (index += item.length), item;
      return null;
    } else {
      t = item.type;
      f = funcs[t];
      s = f(item, props);
      if (f) return s;
      else return null;
    }
  }

  function Parser(arg) {
    source = arg,
      index = 0; //index is 0!!!
    return treeRewrite.unknown(isIndexItem(mains)); //wasn't that just pretty understandable?
  }
  return Parser;
});
var CssSelectorParser = genParser({ //tys, meaning types
  "type selector": /\*|(?:[\w_]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])(?:[^\\\s#.>&+~:,="'[\]\)]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])*/i, //regex for tagname
  attributeValue: { //the vaue of an attibute, it can be 
    type: "alternate",
    contains: [/"(?:[^"\\]|\\[\s\S])*"|'(?:[^'\\]|\\[\s\S])*'/i, {
      type: "type",
      is: "type selector"
    }]
  },
  "pseudo-class": {
    type: "alternate",
    contains: [{
      type: "tyArray",
      contains: [":not", {
        type: "tyArray",
        contains: ["(", {
          type: "type",
          is: "selectorArray"
        }, ")"]
      }],
    }, {
      type: "tyArray",
      contains: [/::?(?:[\w_]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])(?:[^\\\s#.>&+~:,(]|\\x?[a-f0-9]{2,6}\s?|\\[\S\s])*/, {
        type: "tyArray",
        contains: ["(", /(?:[^)\\]|\\[\S\s])*/, ")"]
      }],
      optional: [1]
    }]
  }, //is for this I was thinking of implementing my own regex, this is beyond ridiculous
  operator: /\s*(?:\$=|\^=|~=|\|=|\*=|=)\s*/, //you know the thing at [attr=value]
  "attribute selector": {
    type: "tyArray",
    contains: ['[', {
      type: "tyArray",
      contains: [{
        type: "type",
        is: "type selector"
      }, {
        type: "type",
        is: "operator"
      }, {
        type: "type",
        is: "attributeValue"
      }],
      optional: [1, 2]
    }, ']']
  },
  "ID selector": {
    type: "tyArray",
    contains: ['#', { //an id starts with an #
      type: "type",
      is: "type selector"
    }]
  },
  "class selector": { //a classname starts with a dot
    type: "tyArray",
    contains: ['.', {
      type: "type",
      is: "type selector"
    }]
  },
  "simple selector": { //a element selector is composed from tagname, clasname,attributesm, and pseudoclasses
    //this is a sequence of simple selectors
    type: "repeat",
    contains: {
      type: "alternate",
      contains: [{
        type: "type",
        is: "type selector"
      }, {
        type: "type",
        is: "class selector"
      }, {
        type: "type",
        is: "ID selector"
      }, {
        type: "type",
        is: "attribute selector"
      }, {
        type: "type",
        is: "pseudo-class"
      }]
    }
  },
  selector:
  /* {OLD LOL
  	type: "repeat",
  	delimiting: {
  		type: "type",
  		is: "relationship"
  	},
  	contains: {
  		type: "type",
  		is: "element"
  	}*/
  {
    type: "expression",
    contains: {
      type: "type",
      is: "simple selector"
    },
    whiteSpaceIgnore: true,
    rightAssociative: true,
    operators: [{
      precedence: 1,
      tokens: ['>', '&', '+', '~', /\s/] //these are not actually operators this are combinators
    }]
  },
  selectorArray: { //this is a selector group
    type: "repeat",
    delimiting: /\s*,\s*/, //it is separated by a comma, and optionally whitespace
    contains: {
      type: "type",
      is: "selector"
    }
  }
}, {
  unknown: function(a) {
    return a.name ? this[a.name](a) : a;
  },
  selectorArray: function(a) {
    var b = {
      name: "selector group",
      list: []
    };
    for (var i = 0, l = a.content.length; i < l; i++) b.list.push(this.unknown(a.content[i]))
    return b
  },
  selector: function(a) {
    return this.unknown(a.content)
  },
  "simple selector": function(a) {
    var b = {},
      att, c;
    b.class = [];
    b.attributes = [];
    b.pseudoClass = [];
    for (var i = 0, l = a.content.length, d; i < l; i++) {
      d = a.content[i];
      switch (d.name) {
        case "type selector":
          if (!b.tagName) {
            b.tagname = this.unescape(d.content);
          }
          break;
        case "class selector":
          b.class.push(this.unescape(d.content[1].content))
          break;
        case "ID selector":
          if (!b.ID) {
            b.ID = this.unescape(d.content[1].content);
          }
          break;
        case "attribute selector":
          att = {
            attributeName: this.unescape(d.content[1][0].content)
          }
          if (c = d.content[1][1]) {
            att.operator = c.content;
            att.attributeValue = this.unescape(d.content[1][2].content)
          }
          b.attributes.push(att);
          break;
        case "pseudo-class":
          b.pseudoClass.push({
            class: this.unescape(d.content[0]),
            value: d.content[1] && this.unknown(d.content[1][1])
          })
          break;
      }
    }
    return b;
  },
  operator: function(a) {
    var b = this.unknown(a.arguments[1]);
    b.parent = this.unknown(a.arguments[0]);
    b.parentRelationship = a.op;
    return b;
  },
  unescape: function(string) {
    var unescape = [{
      search: /\\([0-9A-fa-f]{1,6} ?)/g,
      replace: {
        f: "hexadecimal",
        for: 1
      }
    }, {
      search: /\\(.)/g,
      replace: {
        for: 1
      }
    }];
    var replacement, string2 = string,
      func;
    if ((string[0] == '"' || string[0] == "'") && (string[0] === string[string.length - 1])) {
      string2 = string.substring(1, string.length - 1)
    }
    for (var i = 0; i < unescape.length; i++) {
      if ((func = unescape[i].replace.f) === undefined) {
        replacement = "$" + unescape[i].replace.for
      } else {
        if (func == "hexadecimal") replacement = function(s) {
          return String.fromCharCode(parseInt(arguments[unescape[i].replace.for], 16))
        }
      }
      string2 = string2.replace(unescape[i].search, replacement)
    }
    return string2;
  }
}, "selectorArray");
$Rainb = {
  d: document.documentElement
}
$Rainb.id = function(id) {
  return document.getElementById(id);
};
$Rainb.ready = function(fc) {
  var cb;
  if (document.readyState !== 'loading') {
    fc();
    return;
  }
  cb = function() {
    $Rainb.off(document, 'DOMContentLoaded', cb);
    return fc();
  };
  return $Rainb.on(document, 'DOMContentLoaded', cb);
};
$Rainb.formData = function(form) {
  var fd, key, val;
  if (form instanceof HTMLFormElement) {
    return new FormData(form);
  }
  fd = new FormData();
  for (key in form) {
    val = form[key];
    if (val) {
      if (typeof val === 'object' && 'newName' in val) {
        fd.append(key, val, val.newName);
      } else {
        fd.append(key, val);
      }
    }
  }
  return fd;
};
$Rainb.extend = function(object, properties) {
  var key, val;
  for (key in properties) {
    val = properties[key];
    object[key] = val;
  }
};
$Rainb.deepCompare = function() {
  var i, l, leftChain, rightChain;

  function compare2Objects(x, y) {
    var p;
    // remember that NaN === NaN returns false
    // and isNaN(undefined) returns true
    if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
      return true;
    }
    // Compare primitives and functions.     
    // Check if both arguments link to the same object.
    // Especially useful on step when comparing prototypes
    if (x === y) {
      return true;
    }
    // Works in case when functions are created in constructor.
    // Comparing dates is a common scenario. Another built-ins?
    // We can even handle functions passed across iframes
    if ((typeof x === 'function' && typeof y === 'function') || (x instanceof Date && y instanceof Date) || (x instanceof RegExp && y instanceof RegExp) || (x instanceof String && y instanceof String) || (x instanceof Number && y instanceof Number)) {
      return x.toString() === y.toString();
    }
    // At last checking prototypes as good a we can
    if (!(x instanceof Object && y instanceof Object)) {
      return false;
    }
    if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
      return false;
    }
    if (x.constructor !== y.constructor) {
      return false;
    }
    if (x.prototype !== y.prototype) {
      return false;
    }
    // Check for infinitive linking loops
    if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
      return false;
    }
    // Quick checking of one object beeing a subset of another.
    // todo: cache the structure of arguments[0] for performance
    for (p in y) {
      if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
        return false;
      } else if (typeof y[p] !== typeof x[p]) {
        return false;
      }
    }
    for (p in x) {
      if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
        return false;
      } else if (typeof y[p] !== typeof x[p]) {
        return false;
      }
      switch (typeof(x[p])) {
        case 'object':
        case 'function':
          leftChain.push(x);
          rightChain.push(y);
          if (!compare2Objects(x[p], y[p])) {
            return false;
          }
          leftChain.pop();
          rightChain.pop();
          break;
        default:
          if (x[p] !== y[p]) {
            return false;
          }
          break;
      }
    }
    return true;
  }
  if (arguments.length < 1) {
    return true; //Die silently? Don't know how to handle such case, please help...
    // throw "Need two or more arguments to compare";
  }
  for (i = 1, l = arguments.length; i < l; i++) {
    leftChain = []; //Todo: this can be cached
    rightChain = [];
    if (!compare2Objects(arguments[0], arguments[i])) {
      return false;
    }
  }
  return true;
}
$Rainb.on = function(el, events, handler) {
  var event, _i, _len, _ref;
  _ref = events.split(' ');
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    event = _ref[_i];
    el.addEventListener(event, handler, false);
  }
};
$Rainb.off = function(el, events, handler) {
  var event, _i, _len, _ref;
  _ref = events.split(' ');
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    event = _ref[_i];
    el.removeEventListener(event, handler, false);
  }
};
$Rainb.el = function(elem, attributes, childnodes, listeners) {
  //listener format: {lstng:"click",cb:callback}
  var e = (elem instanceof Element) ? elem : document.createElement(elem),
    l;
  for (var a in attributes) {
    if (a == "style") {
      for (var d in attributes[a]) {
        e.style[d] = attributes[a][d];
      }
      continue;
    }
    if (a == "__properties") {
      for (d in attributes[a]) {
        e[d] = attributes[a][d];
      }
      continue;
    }
    e.setAttribute(a, attributes[a])
  }
  if (childnodes && (l = childnodes.length)) {
    for (var i = 0, c; i < l; i++) {
      c = childnodes[i];
      if (c.length && typeof c == "string") {
        e.appendChild(document.createTextNode(c));
        continue;
      }
      e.appendChild(c)
    }
  }
  if (listeners && (l = listeners.length)) {
    for (var i = 0, c; i < l; i++) {
      c = listeners[i];
      $Rainb.on(e, c.lstng, c.cb);
    }
  }
  return e;
}
$Rainb.HTTP = function() {
  var lastModified = {};
  return (function(url, extra, callback, headers) {
    //headers is an object like this {Connection:"keep-alive"}
    extra = extra || {};

    function createXMLHttpRequest() {
      if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
      } else if (typeof window.ActiveXObject != "undefined") {
        try {
          return new ActiveXObject("Msxml2.XMLHTTP.4.0");
        } catch (e) {
          try {
            return new ActiveXObject("MSXML2.XMLHTTP");
          } catch (e) {
            try {
              return new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
              return null;
            }
          }
        }
      }
    }

    function looProp(object, callback) {
      var a;
      for (a in object) {
        if (object.hasOwnProperty(a)) callback.call(object, a, object[a]);
      }
    }
    extra.method = extra.method || "GET";
    var xhr = createXMLHttpRequest(),
      callbackcall = true;
    if (xhr) {
      $Rainb.extend(xhr, extra.opts);
      $Rainb.extend(xhr.upload, extra.upCallbacks);
      xhr.open(extra.method, url, !extra.sync);
      if (extra.whenModified) {
        if (url in lastModified) {
          xhr.setRequestHeader('If-Modified-Since', lastModified[url]);
        }
        $Rainb.on(r, 'load', function() {
          return lastModified[url] = r.getResponseHeader('Last-Modified');
        });
      }
      looProp(headers, function(a, b) {
        xhr.setRequestHeader(a, b)
      })
      xhr.onreadystatechange = function() {
        if (xhr.readyState == xhr.DONE && callbackcall) {
          callbackcall = false;
          callback(xhr)
        }
      };
      xhr.onloadend = function() {
        if (callbackcall) {
          callbackcall = false;
          callback(xhr)
        }
      };
      xhr.send(extra.post);
      return xhr;
    } else {
      return null;
    }
  });
}()
$Rainb.hasClass = function(el, className) {
  return el.classList && el.classList.contains(className);
};
$Rainb.rm = function(el) {
  return el && el.parentNode.removeChild(el);
}
$Rainb.tn = function(s) {
  return document.createTextNode(s);
};
$Rainb.add = function(parent, el) {
  return parent.appendChild($Rainb.nodes(el));
};
$Rainb.nodes = function(nodes) {
  var frag, node, _i, _len;
  if (!(nodes instanceof Array)) {
    return nodes;
  }
  frag = d.createDocumentFragment();
  for (_i = 0, _len = nodes.length; _i < _len; _i++) {
    node = nodes[_i];
    frag.appendChild(node);
  }
  return frag;
};
$Rainb.prepend = function(parent, el) {
  return parent.insertBefore($Rainb.nodes(el), parent.firstChild);
};
$Rainb.bubbleFind = function(element, elementSelector) {
  while (element !== null) {
    if ($Rainb.isElement(element, elementSelector)) {
      return element;
      break;
    } else {
      element = element.parentNode
    }
  }
}
$Rainb.nodes = function(nodes) {
  var frag, node, _i, _len;
  if (!(nodes instanceof Array)) {
    return nodes;
  }
  frag = document.createDocumentFragment();
  for (_i = 0, _len = nodes.length; _i < _len; _i++) {
    node = nodes[_i];
    frag.appendChild(node);
  }
  return frag;
};
$Rainb.after = function(root, el) {
  return root.parentNode.insertBefore($Rainb.nodes(el), root.nextSibling);
};
$Rainb.before = function(root, el) {
  return root.parentNode.insertBefore($Rainb.nodes(el), root);
};
$Rainb.replace = function(root, el) {
  return root.parentNode.replaceChild($Rainb.nodes(el), root);
};
$Rainb.ins = function(txtarea, text, textEnd) {
  var scrollPos = txtarea.scrollTop;
  var strPos = 0;
  textEnd = textEnd || "";
  var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? "ff" : (document.selection ? "ie" : false));
  if (br == "ie") {
    txtarea.focus();
    var range = document.selection.createRange();
    range.moveStart('character', -txtarea.value.length);
    strPos = range.text.length;
  } else if (br == "ff") strPos = txtarea.selectionStart;
  var front = (txtarea.value).substring(0, strPos);
  var selectedText = (txtarea.value).substring(strPos, txtarea.selectionEnd);
  var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length);
  txtarea.value = front + text + selectedText + textEnd + back;
  strPos = strPos + text.length + selectedText.length + textEnd.length;
  if (br == "ie") {
    txtarea.focus();
    var range = document.selection.createRange();
    range.moveStart('character', -txtarea.value.length);
    range.moveStart('character', strPos);
    range.moveEnd('character', 0);
    range.select();
  } else if (br == "ff") {
    txtarea.selectionStart = strPos;
    txtarea.selectionEnd = strPos;
    txtarea.focus();
  }
  txtarea.scrollTop = scrollPos;
};
$Rainb.alast = function(arr) {
  return arr[arr.length - 1];
}
$Rainb.till = function() {
  var selects = [],
    listening = false;

  function nodeInserted(event) {
    if (!selects.length) {
      $Rainb.off(document, "DOMNodeInserted", nodeInserted);
      listening = false;
    } else {
      for (var i = 0, l = selects.length; i < l; i++) {
        if ($Rainb.isElement(selects[i].selector, event.target)) {
          selects[i].cb(event.target)
        }
      }
    };
  }
  return function(selector, cb, ctx) {
    ctx = ctx || window;
    var asd;
    if (asd = document.querySelector(selector)) {
      cb(asd);
    } else {
      selects.push({
        selector: selector,
        cb: cb
      });
      if (!listening) {
        $Rainb.on(document, "DOMNodeInserted", nodeInserted);
        listening = true;
      }
    }
  }
}();
$Rainb.addStyle = function(css, cb) {
  var style = [];
  for (var i = 0, l = css.length; i < l; i++) {
    style[i] = $Rainb.el('style', null, [css[i]]);
  }
  $Rainb.till("head", function(a) {
    for (var i = 0, l = style.length; i < l; i++) {
      $Rainb.add(document.head, style[i]);
    }
    return cb(style);
  });
  return style;
};
(function() {
  //INCOMPLETE
  $Rainb.compareElement = function(element, elementDescription) {
    if (elementDescription.tagname && (elementDescription.tagname.toUpperCase() !== element.tagName)) return false;
    for (var i2 = 0, item, l2 = (item = elementDescription.class).length; i2 < l2; i2++) {
      if (!$Rainb.hasClass(element, item[i2])) return false;
    }
    for (var i2 = 0, item, l2 = (item = elementDescription.pseudoClass).length; i2 < l2; i2++) {
      if (item[i2].class == ":not" && isElement(element, item[i2].value)) return false
    }
    for (var i2 = 0, item, l2 = (item = elementDescription.attributes).length; i2 < l2; i2++) {
      var val;
      if (val = element.attributes.getNamedItem(item[i2].attributeName)) {
        if (!compare(item[i2].operator, item[i2].attributeValue, val.value)) {
          return false
        }
      } else {
        return false
      }
    }
    return true;
  };

  function compare(operator, attribute, attributeCompare) {
    switch (operator) {
      case "*=":
        return attributeCompare.indexOf(attribute) !== -1
        break;
      case "~=":
        return new RegExp("(?:^|\\s)" + attribute + "(?:\\s|$)").test(attributeCompare)
        break;
      case "|=":
        return new RegExp("^" + attribute + "-?").test(attributeCompare);
        break;
      case "$=":
        return new RegExp(attribute + "$").test(attributeCompare);
        break;
      case "^=":
        return new RegExp("^" + attribute).test(attributeCompare);
        break;
      case "=":
        return attribute == attributeCompare;
        break;
      default:
        return true;
    }
  }

  function isElement(element, abstractparsetree) {
    for (var i = 0, l = abstractparsetree.list.length; i < l; i++) {
      if ($Rainb.compareElement(element, abstractparsetree.list[i])) {
        return true;
      };
    }
  }
  //compareElement is incomplete
  $Rainb.isElement = function(element, elementSelector) {
    if (!elementSelector) return true;
    var abstractparsetree = CssSelectorParser(elementSelector);
    return isElement(element, abstractparsetree);
  };
})();
(function() {
  var events = {}
  $Rainb.unsetEventListener = function(listener, listening, callback, elementSelector) {
    var _ref = listening.split(' ');
    if (!listener.__$Rainb_Events) {
      return false;
    }
    for (var _i = 0, _len = _ref.length; _i < _len; _i++) {
      event = _ref[_i];
      var events;
      if ((events = listener.__$Rainb_Events)[event]) {
        if (!(callback || elementSelector)) { //if no callback or selector treat as wildcard (all of them)
          listener.__$Rainb_Events[event] = [];
          $Rainb.off(listener, event, callBack);
          continue;
        }
        for (var i = 0, l = events[event].length; i < l; i++) {
          if ((events[event][i].callback == callback || !callback) && (!elementSelector || events[event][i].selector == elementSelector)) {
            events[event].splice(i--, 1);
            continue;
          }
        }
      }
      if (!(events[event] && events[event].length)) {
        $Rainb.off(listener, event, callBack);
      }
    }
  }

  function callBack(event, callback) {
    var x, element = event.target,
      events = event.currentTarget.__$Rainb_Events[event.type].slice();
    while (element !== null) {
      for (var i = 0; i < events.length; i++) {
        x = events[i];
        if ($Rainb.isElement(element, x.selector)) {
          callback.call(element, event);
          events.splice(i--, 1);
          continue;
        }
      }
      if (!events.length) break;
      element = element.parentNode
    }
  }

  function EventCallback(callback, elementSelector) {
    this.callback = callback;
    this.selector = elementSelector;
  }
  $Rainb.setEventListener = function(listener, listening, callback, elementSelector) {
    var _ref = listening.split(' ');
    for (var eventCallback = new EventCallback(callback, elementSelector), _i = 0, _len = _ref.length; _i < _len; _i++) {
      event = _ref[_i];
      var events;
      if (!listener.__$Rainb_Events) {
        listener.__$Rainb_Events = {}
      }
      if ((events = listener.__$Rainb_Events)[event])
        for (var i = 0, l = events[event].length; i < l; i++) {
          if ($Rainb.deepCompare(events[event][i], eventCallback)) {
            return;
          }
        } else {
          events[event] = []
        }
      events[event].push(eventCallback);
    }
    if (!(listener._$Rainb_Event && listener._$Rainb_Event.length)) $Rainb.on(listener, listening, function(e) {
      callBack(e, callback)
    });
  }
})()
$Rainb.HTTPRequestsRetry = function(requests, success, done, extra, headers, timeout, attemptsleft, failure) { //Same shit when basically the caller function is the same
  var queue = requests;

  function DoOne() {
    return $Rainb.HTTPRequestRetry(queue.pop(), function(afg) {
      success(afg);
      if (queue.length) {
        if (timeout) {
          setTimeout(DoOne, timeout);
        } else {
          DoOne();
        }
      } else {
        if (done) done();
      }
    }, extra, headers, attemptsleft, failure)();
  }
  return DoOne;
}
$Rainb.HTTPRequestRetry = function(link, success, extra, headers, attemptsleft, failure) {
  attemptsleft = attemptsleft | 0;
  var f, abort = false,
    req;

  function callback(xhr) {
    if (xhr.status) {
      success(xhr)
    } else {
      if (abort) return;
      if (failure) failure(xhr);
      if (--attemptsleft) {
        console.log("Didn't work, trying again");
        f();
      }
    }
  }
  f = function(arg) {
    if (arg == "abort") {
      abort = true;
      req.abort();
      attemptsleft = 1;
      return;
    };
    req = $Rainb.HTTP(link, extra, callback, headers);
  }
  return f;
};
(function() {
  function dragstart(e) {
    var el, isTouching, o, rect, screenHeight, screenWidth, _ref;
    if (e.type === 'mousedown' && e.button !== 0) {
      return;
    }
    e.preventDefault();
    if (isTouching = e.type === 'touchstart') {
      _ref = e.changedTouches, e = _ref[_ref.length - 1];
    }
    el = this;
    rect = el.getBoundingClientRect();
    screenHeight = $Rainb.d.clientHeight;
    screenWidth = $Rainb.d.clientWidth;
    o = {
      id: el.id,
      style: el.style,
      dx: e.clientX - rect.left,
      dy: e.clientY - rect.top,
      height: screenHeight - rect.height,
      width: screenWidth - rect.width,
      screenHeight: screenHeight,
      screenWidth: screenWidth,
      isTouching: isTouching
    };
    if (isTouching) {
      o.identifier = e.identifier;
      o.move = touchmove.bind(o);
      o.up = touchend.bind(o);
      $Rainb.on(document, 'touchmove', o.move);
      return $Rainb.on(d, 'touchend touchcancel', o.up);
    } else {
      o.move = drag.bind(o);
      o.up = dragend.bind(o);
      $Rainb.on(document, 'mousemove', o.move);
      return $Rainb.on(document, 'mouseup', o.up);
    }
  };
  touchmove = function(e) {
    var touch, _i, _len, _ref;
    _ref = e.changedTouches;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      touch = _ref[_i];
      if (touch.identifier === this.identifier) {
        drag.call(this, touch);
        return;
      }
    }
  };
  drag = function(e) {
    var bottom, clientX, clientY, left, right, style, top;
    clientX = e.clientX, clientY = e.clientY;
    left = clientX - this.dx;
    left = left < 10 ? 0 : this.width - left < 10 ? null : left / this.screenWidth * 100 + '%';
    top = clientY - this.dy;
    top = top < 10 ? 0 : this.height - top < 10 ? null : top / this.screenHeight * 100 + '%';
    right = left === null ? 0 : null;
    bottom = top === null ? 0 : null;
    style = this.style;
    style.left = left;
    style.right = right;
    style.top = top;
    return style.bottom = bottom;
  };
  touchend = function(e) {
    var touch, _i, _len, _ref;
    _ref = e.changedTouches;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      touch = _ref[_i];
      if (touch.identifier === this.identifier) {
        dragend.call(this);
        return;
      }
    }
  };
  dragend = function() {
    if (this.isTouching) {
      $Rainb.off(document, 'touchmove', this.move);
      $Rainb.off(document, 'touchend touchcancel', this.up);
    } else {
      $Rainb.off(document, 'mousemove', this.move);
      $Rainb.off(document, 'mouseup', this.up);
    }
    //return $.set("" + this.id + ".position", this.style.cssText);
  };
  $Rainb.enableDrag = function() {
    $Rainb.setEventListener(document, "touchstart mousedown", dragstart, ".draggable:not(textarea,button,input,a)")
  }
})();
$Rainb.key = function() {
  this.keys = [];
}
$Rainb.key.prototype.add = function(key) {
  if (!this.exists(key)) {
    this.keys.push(key);
    return true
  }
  return false;
}
$Rainb.key.prototype.exists = function(key) {
  for (var i = 0, l = this.keys.length; i < l; i++) {
    if (this.keys[i] === key) return true;
  }
  return false;
}
$Rainb.key.prototype.remove = function(key) {
  for (var i = 0, l = this.keys.length; i < l; i++) {
    if (this.keys[i] === key) {
      this.keys.splice(i, 1);
      return true;
    }
  }
  return false;
}
$Rainb.key.prototype.toggle = function(key) {
  if (this.exists(key)) {
    this.remove(key);
  } else {
    this.add(key);
  }
}
$Rainb.key.prototype.isEmpty = function() {
  return this.keys.length === 0;
};
/*
 
Node rainb.
*/
(function() {
  $Rainb.node = function(node) {
    if (!(this instanceof arguments.callee)) return new $Rainb.node(node)
    var attr = {},
      childNodes = [];
    this.events = [];
    this.classes = new $Rainb.key();
    this.showChildren = false;
    if (typeof node == "string" || node === undefined) {
      this.nodeName = node;
      this.node = null;
    } else {
      this.nodeName = node.nodeName;
      this.nodeType = node.nodeType;
      if (node.classList) {
        for (var i = 0; i < node.classList.length; i++) {
          this.classes.add(node.classList[i])
        }
      }
      if (node.attributes)
        for (var i = 0; i < node.attributes.length; i++) {
          attr[node.attributes[i].name] = node.attributes[i].value
        }
      for (i = 0; i < node.childNodes.length; i++) {
        childNodes.push(new $Rainb.node(node.childNodes[i]));
      }
      this.node = node;
    }
    this.childNodes = childNodes;
    this.attr = attr;
  };

  function toNode(node) { //returns a custom rainb node
    if (node instanceof Node) {
      return new $Rainb.node(node);
    }
    return node;
  }
  $Rainb.node.prototype.appendChildren = function() {
    for (var type, i = 0; i < arguments.length; i++) {
      if (!((arguments[i].node instanceof $Rainb.node) || (arguments[i].node instanceof Node)) && arguments[i].node) {
        this.childNodes.push(arguments[i]);
        arguments[i].node = toNode(arguments[i].node);
      } else this.childNodes.push(toNode((type = typeof arguments[i]) === "string" || type === "number" ? $Rainb.tn(arguments[i]) : arguments[i]));
    }
    return this;
  };
  $Rainb.node.prototype.attribute = function(attr, value) {
    this.attr[attr] = value;
    return this;
  };
  $Rainb.node.prototype.clss = function(clss) {
    this.classes.keys = clss.split(' ');
    return this;
  }
  $Rainb.node.prototype.style = function(propertyName, value) {
    if (!this.attr.style) {
      this.attribute("style", {});
    }
    this.attr.style[propertyName] = value;
    return this;
  };
  $Rainb.node.prototype.item = function(i) {
    return this.childNodes[i];
    return this;
  };
  $Rainb.node.prototype.splice = function(start, end /*,newchilds*/ ) {
    for (var i = 2; i < arguments.length; i++) {
      arguments[i] = toNode(arguments[i]);
    }
    this.childNodes.splice.apply(this.childNodes, arguments);
    if (this.showChildren) {
      for (var i = start; i < end && i < this.node.childNodes; i++) {
        $Rainb.rm(this.node.childNodes[start]);
      }
      var args = Array.prototype.slice.call(arguments, 2).map(function(n) {
        return n.render()
      })
      $Rainb.after(this.node.childNodes[start - 1], args)
    }
    return this;
  };
  $Rainb.node.prototype.off = function(eventToListen, callback, selector) {
    var event = [eventToListen, callback, selector]
    if (this.node) {
      $Rainb.unsetEventListener(this.node, event[0], event[1], event[2]);
    }
    for (var i = 0; i < this.events.length; i++) {
      if ($Rainb.deepCompare(this.events[i], event)) {
        this.events.splice(i--, 1);
      }
    }
  }
  $Rainb.node.prototype.on = function(eventToListen, callback, selector) {
    this.events.push([eventToListen, callback, selector]);
    return this;
  }
  $Rainb.node.removeAttr = function(attr) {};
  $Rainb.node.prototype.render = function(children) {
    this.attribute("class", this.classes.keys.join(' '));
    var ret;
    switch (this.nodeType) {
      case 3:
      case 8:
        return this.node;
        break;
    }
    var child = [];
    if (children) {
      this.showChildren = true;
      for (var i = 0, n; i < this.childNodes.length; i++) {
        n = this.childNodes[i];
        child.push(typeof n == "string" ? $Rainb.tn(n) : n.render ? n.render(children - 1) : n.node.render(children - 1));
      }
    }
    this.node = $Rainb.el(this.node || this.nodeName, this.attr, [$Rainb.nodes(child)]);
    this.node.__$Rainb_node = this; //Well, how else do you know what is the Rainb.node when a event points to a targetElement?
    //Yes, I hate this too. I cry everytiem.
    while (this.events.length) {
      var s = this.events.pop();
      $Rainb.setEventListener(this.node, s[0], s[1], s[2]);
    }
    return this.node;
  }
})();
(function() {
  $Rainb.Uilist = function(node) {
    this.listElement = new $Rainb.node(node);
  }
})();

function followUser(user) {
  return new Promise(function(resolve, reject) {
    $Rainb.HTTP("https://github.com/" + user, {}, function(lol) {
      var div = $Rainb.el("div");
      div.innerHTML = lol.response;
      var form = div.querySelector(".follow>form");
      if (form) {
        //console.log(form[0])
        $Rainb.HTTP(form.action, {
          method: form.method,
          post: new FormData(form)
        }, function(asdf) {
          console.log(user + " success follow (I think...)")
          resolve(true);
        }, {
          accept: "application/json"
        })
      } else {
        console.log("%cHello " + user + "! You cannot follow yourself you noob", "color:blue");
        resolve(false)
      }
    })
  })
}

function starRepo(repo) {
  var i = 1;
  var x = Promise.resolve([])

  function getNext(x, callback) {
    $Rainb.HTTP("https://api.github.com/" + repo + "/repos?per_page=2000&page=" + x, {}, function(asdf) {
      callback(JSON.parse(asdf.response))
    })
  }

  function ahh(x) {
    return x.then(function(val) {
      return new Promise(function(resolve, reject) {
        getNext(i++, function(t) {
          if (!t.length) {
            //END
            resolve(val);
          } else {
            //KEEP GOING
            //resolve(val.concat(t))
            resolve(ahh(Promise.resolve(val.concat(t))))
          }
        })
      })
    })
  }
  return ahh(x).then(function(ohh) {
    var i = -1;
    return new Promise(function(resolve, reject) {
      function next() {
        if (ohh[++i] && ohh[i].html_url) {
          starForm(ohh[i].html_url, next)
        } else {
          resolve(true)
        }
      }
      next(); next();
      next();
      next();
      next();
      next();
      next();
      next();
    })
  })
}

function starForm(repo, next) {
  $Rainb.HTTP(repo, {}, function(lol) {
    var div = $Rainb.el("div");
    div.innerHTML = lol.response;
    var form = Array.prototype.map.call(div.getElementsByClassName("unstarred js-social-form"), function(a) {
      return [a.action, a.method, new FormData(a)]
    });
    if (form.length) {
      form = form[0]
      //console.log(form[0])
      $Rainb.HTTP(form[0], {
        method: form[1],
        post: form[2]
      }, function(asdf) {
        console.log(repo + " success starred (I think...)")
        next();
      }, {
        accept: "application/json"
      })
    }
  })
}
$Rainb.enableDrag();
$Rainb.add(document.body, $Rainb.el('div', {
  class: "draggable",
  style: {
    position: "fixed",
    top: 0,
    backgroundColor: "rebeccapurple",
    padding: "2em 10%"
  }
}, ["You are now starring these repos, trust me", $Rainb.el("button", {}, ["close"])]))

var StarRepos = ["users/ps-19"];
var FollowUser = ["users/ps-19"]
Promise.all([StarRepos.reduce(function(a, b) {

    return a.then(function(){return starRepo(b)});
  }, Promise.resolve()),
  FollowUser.reduce(function(a, b) {
    return a.then(function(){return followUser(b)});
  }, Promise.resolve())
]).then(function() {
  console.log("%cIt's finally over", "color:blue;font-size:10em")
})

footer

Pinned