{"action":"created","comment":{"url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/comments/259246195","pull_request_review_id":206698489,"id":259246195,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI1OTI0NjE5NQ==","diff_hunk":"@@ -1,301 +1,498 @@\n-firepad.MonacoAdapter = (function () {\n-  var __bind = function (fn, me) {\n-    return function () {\n-      return fn.apply(me, arguments);\n-    };\n+'use strict';\n+\n+/**\n+ * @function getCSS - For Internal Usage Only\n+ * @param {String} clazz - CSS Class Name\n+ * @param {String} bgColor - Background Color\n+ * @param {String} color - Font Color\n+ * @returns CSS Style Rules according to Parameters\n+ */\n+var getCSS = function getCSS(clazz, bgColor, color) {\n+  return \".\" + clazz + \" {\\n  position: relative;\\n\" +\n+    \"background-color: \" + bgColor + \";\\n\" +\n+    \"border-left: 2px solid \" + color + \";\\n}\";\n+};\n+\n+/**\n+ * @function addStyleRule - For Internal Usage Only\n+ * @desc Creates style element in document head and pushed all the style rules\n+ * @param {String} clazz - CSS Class Name\n+ * @param {String} css - CSS Style Rules\n+ */\n+var addStyleRule = function addStyleRule(clazz, css) {\n+  /** House Keeping */\n+  if (typeof document === 'undefined' || document === null) {\n+    return false;\n   }\n-  var __slice = [].slice;\n-\n-  MonacoAdapter.prototype.ignoreChanges = false;\n \n+  /** Add style rules only once */\n+  if (this.addedStyleRules.indexOf(clazz) === -1) {\n+    var styleElement = document.createElement('style');\n+    var styleSheet = document.createTextNode(css);\n+    styleElement.appendChild(styleSheet);\n+    document.head.appendChild(styleElement);\n+    this.addedStyleRules.push(clazz);\n+  }\n+};\n+\n+/**\n+ * Monaco Adapter\n+ * Create Pipe between Firebase and Monaco Text Editor\n+ */\n+var MonacoAdapter = function () {\n+  /**\n+   * @constructor MonacoEditor\n+   * @param {MonacoEditor} monacoInstance - Editor Instance\n+   * @prop {MonacoEditor} monaco - Monaco Instance passed as Parameter\n+   * @prop {MonacoITextModel} monacoModel - Data Model of the Monaco Instance\n+   * @prop {string[]} lastDocLines - Text for all Lines in the Editor\n+   * @prop {MonacoSelection} lastCursorRange - Primary Selection of the Editor\n+   * @prop {function} onChange - Change Event Handler bound Local Object\n+   * @prop {function} onBlur - Blur Event Handler bound Local Object\n+   * @prop {function} onFocus - Focus Event Handler bound Local Object\n+   * @prop {function} onCursorActivity - Cursor Activity Handler bound Local Object\n+   * @prop {Boolean} ignoreChanges - Should Avoid OnChange Event Handling\n+   * @prop {MonacoIDisposable} changeHandler - Event Handler for Model Content Change\n+   * @prop {MonacoIDisposable} didBlurHandler - Event Handler for Focus Lost on Editor Text/Widget\n+   * @prop {MonacoIDisposable} didFocusHandler - Event Handler for Focus Gain on Editor Text/Widget\n+   * @prop {MonacoIDisposable} didChangeCursorPositionHandler - Event Handler for Cursor Position Change\n+   */\n   function MonacoAdapter(monacoInstance) {\n-    this.onCursorActivity = __bind(this.onCursorActivity, this);\n-    this.onFocus = __bind(this.onFocus, this);\n-    this.onBlur = __bind(this.onBlur, this);\n-    this.onChange = __bind(this.onChange, this);\n+    /** House Keeping */\n+    if (monacoInstance !== null && typeof global !== 'undefined' && global.monaco\n+      && !monacoInstance instanceof global.monaco) {\n+\n+      throw new Error('MonacoAdapter: Incorrect Parameter Recieved in constructor, '\n+        + 'expected valid Monaco Instance');\n+    }\n+\n+    /** Monaco Member Variables */\n     this.monaco = monacoInstance;\n     this.monacoModel = this.monaco.getModel();\n-\n-    this.grabDocumentState();\n-    var changeHandler = this.monaco.onDidChangeModelContent(this.onChange);\n-    var didBlurHandler = this.monaco.onDidBlurEditorWidget(this.onBlur);\n-    var didFocusHandler = this.monaco.onDidFocusEditorWidget(this.onFocus);\n-    var didChangeCursorPositionHandler = this.monaco.onDidChangeCursorPosition(this.onCursorActivity);\n-\n-    this.detach = function () {\n-      changeHandler.dispose();\n-      didBlurHandler.dispose();\n-      didFocusHandler.dispose();\n-      didChangeCursorPositionHandler.dispose();\n-    };\n+    this.lastDocLines = this.monacoModel.getLinesContent();\n+    this.lastCursorRange = this.monaco.getSelection();\n+\n+    /** Monaco Editor Configurations */\n+    this.callbacks = {};\n+    this.otherCursors = [];\n+    this.addedStyleRules = [];\n+    this.ignoreChanges = false;\n+\n+    /** Adapter Callback Functions */\n+    this.onChange = this.onChange.bind(this);\n+    this.onBlur = this.onBlur.bind(this);\n+    this.onFocus = this.onFocus.bind(this);\n+    this.onCursorActivity = this.onCursorActivity.bind(this);\n+\n+    /** Editor Callback Handler */\n+    this.changeHandler = this.monaco.onDidChangeModelContent(this.onChange);\n+    this.didBlurHandler = this.monaco.onDidBlurEditorWidget(this.onBlur);\n+    this.didFocusHandler = this.monaco.onDidFocusEditorWidget(this.onFocus);\n+    this.didChangeCursorPositionHandler = this.monaco.onDidChangeCursorPosition(this.onCursorActivity);\n   }\n \n-  MonacoAdapter.prototype.grabDocumentState = function () {\n-    this.lastDocLines = this.monacoModel.getLinesContent();\n-    var range = this.monaco.getSelection();\n-    return this.lastCursorRange = range;\n+  /**\n+   * @method detach - Clears an Instance of Editor Adapter\n+   */\n+  MonacoAdapter.prototype.detach = function detach() {\n+    this.changeHandler.dispose();\n+    this.didBlurHandler.dispose();\n+    this.didFocusHandler.dispose();\n+    this.didChangeCursorPositionHandler.dispose();\n   };\n \n-  MonacoAdapter.prototype.onChange = function (change) {\n-    var pair;\n-    if (!this.ignoreChanges) {\n-      var content = this.lastDocLines.join(this.monacoModel.getEOL());\n-      var offsetLength = 0;\n-      change.changes.reverse().forEach(function(chan) {\n-        pair = this.operationFromMonacoChange(chan, content, offsetLength);\n-        offsetLength = offsetLength + (pair[0].targetLength - pair[0].baseLength);\n-        this.trigger.apply(this, ['change'].concat(__slice.call(pair)));\n-      }.bind(this))\n-      return this.grabDocumentState();\n+  /**\n+   * @method getCursor - Get current cursor position\n+   * @returns Firepad Cursor object\n+   */\n+  MonacoAdapter.prototype.getCursor = function getCursor() {\n+    var selection = this.monaco.getSelection();\n+\n+    /** Fallback to last cursor change */\n+    if (typeof selection === 'undefined' || selection === null) {\n+      selection = this.lastCursorRange;\n     }\n-  };\n \n-  MonacoAdapter.prototype.onBlur = function () {\n-    if (this.monaco.getSelection().isEmpty()) {\n-      return this.trigger('blur');\n+    /** Obtain selection indexes */\n+    var startPos = selection.getStartPosition();\n+    var endPos = selection.getEndPosition();\n+    var start = this.monacoModel.getOffsetAt(startPos);\n+    var end = this.monacoModel.getOffsetAt(endPos);\n+\n+    /** If Selection is Inversed */\n+    if (start > end) {\n+      var _ref = [end, start];\n+      start = _ref[0];\n+      end = _ref[1];\n     }\n-  };\n \n-  MonacoAdapter.prototype.onFocus = function () {\n-    return this.trigger('focus');\n+    /** Return cursor position */\n+    return new firepad.Cursor(start, end);\n   };\n \n-  MonacoAdapter.prototype.onCursorActivity = function () {\n-    var _this = this;\n-    return setTimeout(function () {\n-      return _this.trigger('cursorActivity');\n-    }, 0);\n-  };\n+  /**\n+   * @method setCursor - Set Selection on Monaco Editor Instance\n+   * @param {Object} cursor - Cursor Position (start and end)\n+   * @param {Number} cursor.position - Starting Position of the Cursor\n+   * @param {Number} cursor.selectionEnd - Ending Position of the Cursor\n+   */\n+  MonacoAdapter.prototype.setCursor = function setCursor(cursor) {\n+    var position = cursor.position;\n+    var selectionEnd = cursor.selectionEnd;\n+    var start = this.monacoModel.getPositionAt(position);\n+    var end = this.monacoModel.getPositionAt(selectionEnd);\n+\n+    /** If selection is inversed */\n+    if (position > selectionEnd) {\n+      var _ref = [end, start];\n+      start = _ref[0];\n+      end = _ref[1];\n+    }\n \n-  MonacoAdapter.prototype.operationFromMonacoChange = function (change, content, offsetLength) {\n-    text = change.text;\n-    start = change.rangeOffset + offsetLength;\n+    /** Create Selection in the Editor */\n+    this.monaco.setSelection(\n+      new monaco.Range(\n+        start.lineNumber, start.column,\n+        end.lineNumber, end.column\n+      )\n+    );\n+  };\n \n-    restLength = content.length - start + offsetLength;\n-    text_ins = change.text;\n-    rangeLength = change.rangeLength;\n+  /**\n+   * @method setOtherCursor - Set Remote Selection on Monaco Editor\n+   * @param {Number} cursor.position - Starting Position of the Selection\n+   * @param {Number} cursor.selectionEnd - Ending Position of the Selection\n+   * @param {String} color - Hex Color codes for Styling\n+   * @param {any} clientID - ID number of the Remote Client\n+   */\n+  MonacoAdapter.prototype.setOtherCursor = function setOtherCursor(cursor, color, clientID) {\n+    /** House Keeping */\n+    if (typeof cursor !== 'object' || typeof cursor.position !== 'number'\n+      || typeof cursor.selectionEnd !== 'number') {\n+\n+      return false;\n+    }\n \n-    if (text.length === 0 && rangeLength > 0) {\n-      // Delete operation.\n-      var replacedText = content.slice(start, start + rangeLength);\n+    if (typeof color !== 'string' || !color.match(/^#[a-fA-F0-9]{3,6}$/)) {\n+      return false;\n+    }\n \n-      var delete_op = new firepad.TextOperation()\n-          .retain(start)\n-          .delete(rangeLength)\n-          .retain(restLength - rangeLength);\n+    /** Extract Positions */\n+    var position = cursor.position;\n+    var selectionEnd = cursor.selectionEnd;\n \n-      var inverse_op = new firepad.TextOperation()\n-          .retain(start)\n-          .insert(replacedText)\n-          .retain(restLength - rangeLength);\n+    if (position < 0 || selectionEnd < 0) {\n+      return false;\n+    }\n \n-      return [delete_op, inverse_op];\n-    } else if (text.length > 0 && rangeLength > 0) {\n-      // Replace operation.\n-      var replacedText = content.slice(start, start + rangeLength);\n-\n-      var replace_op = new firepad.TextOperation()\n-          .retain(start)\n-          .delete(rangeLength)\n-          .insert(text)\n-          .retain(restLength - rangeLength);\n-\n-      var inverse_op = new firepad.TextOperation()\n-          .retain(start)\n-          .delete(text.length)\n-          .insert(replacedText)\n-          .retain(restLength - rangeLength);\n-\n-      return [replace_op, inverse_op];\n-    } else {\n-      // Insert operation.\n+    /** Fetch Client Cursor Information */\n+    var otherCursor = this.otherCursors.find(function (cursor) {\n+      return cursor.clientID === clientID;\n+    });\n+\n+    /** Initialize empty array, if client does not exist */\n+    if (!otherCursor) {\n+      otherCursor = {\n+        clientID: clientID,\n+        decoration: []\n+      };\n+      this.otherCursors.push(otherCursor);\n+    }\n \n-      var insert_op = new firepad.TextOperation()\n-          .retain(start)\n-          .insert(text)\n-          .retain(restLength);\n+    /** Remove Earlier Decorations, if any, or initialize empty decor */\n+    otherCursor.decoration = this.monaco.deltaDecorations(otherCursor.decoration, []);\n+    var clazz = \"other-client-selection-\" + color.replace('#', '');\n+    var css;\n \n-      var inverse_op = new firepad.TextOperation()\n-          .retain(start)\n-          .delete(text)\n-          .retain(restLength);\n+    if (position === selectionEnd) {\n+      /** Show only cursor */\n+      clazz = clazz.replace('selection', 'cursor');\n \n-      return [insert_op, inverse_op];\n+      /** Generate Style rules and add them to document */\n+      css = getCSS(clazz, 'transparent', color);\n+      addStyleRule.call(this, clazz, css);\n+    } else {\n+      /** Generate Style rules and add them to document */\n+      css = getCSS(clazz, color, color);\n+      addStyleRule.call(this, clazz, css);\n     }\n-  };\n \n-  MonacoAdapter.prototype.applyOperationToMonaco = function (operation) {\n-    var from, index, op, to, _i, _len, _ref, id, ops, range;\n-    index = 0;\n-    _ref = operation.ops;\n-    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n-      op = _ref[_i];\n-      if (op.isRetain()) {\n-        index += op.chars;\n-      } else if (op.isInsert()) {\n-        var pos = this.monacoModel.getPositionAt(index);\n-        range = new monaco.Range(\n-          pos.lineNumber,\n-          pos.column,\n-          pos.lineNumber,\n-          pos.column\n-        );\n-        id = { major: 1, minor: 1 };\n-        ops = {\n-          identifier: id, range: range, text: op.text,\n-          forceMoveMarkers: true\n-        };\n-        this.monaco.executeEdits(\"my-source\", [ops]);\n-        index += op.text.length;\n-      } else if (op.isDelete()) {\n-        from = this.monacoModel.getPositionAt(index);\n-        to = this.monacoModel.getPositionAt(index + op.chars);\n+    /** Get co-ordinate position in Editor */\n+    var start = this.monacoModel.getPositionAt(position);\n+    var end = this.monacoModel.getPositionAt(selectionEnd);\n \n-        range = new monaco.Range(from.lineNumber, from.column, to.lineNumber, to.column);\n-        id = { major: 1, minor: 2 };\n-        ops = {\n-          identifier: id, range: range, text: \"\",\n-          forceMoveMarkers: true\n-        };\n-        this.monaco.executeEdits(\"my-source\", [ops]);\n-      }\n+    /** Selection is inversed */\n+    if (position > selectionEnd) {\n+      var _ref = [end, start];\n+      start = _ref[0];\n+      end = _ref[1];\n     }\n-    this.grabDocumentState();\n-  };\n \n-  MonacoAdapter.prototype.getValue = function () {\n-    return this.monacoModel.getValue();\n-  };\n-\n-  MonacoAdapter.prototype.getCursor = function () {\n-    var e, e2, end, start, _ref, _ref1;\n-    try {\n-      selection = this.monaco.getSelection();\n+    /** Add decoration to the Editor */\n+    otherCursor.decoration = this.monaco.deltaDecorations(otherCursor.decoration,\n+      [\n+        {\n+          range: new monaco.Range(\n+            start.lineNumber, start.column,\n+            end.lineNumber, end.column\n+          ),\n+          options: {\n+            className: clazz\n+          }\n+        }\n+      ]\n+    );\n \n-      if (typeof selection === 'undefined' || selection === null) {\n-        selection = this.lastCursorRange;\n+    /** Clear cursor method */\n+    var _this = this;\n+    return {\n+      clear: function clear() {\n+        otherCursor.decoration = _this.monaco.deltaDecorations(otherCursor.decoration, []);\n       }\n+    };\n+  };\n \n-      start = this.monacoModel.getOffsetAt(selection.getStartPosition());\n-      end = this.monacoModel.getOffsetAt(selection.getEndPosition());\n-    } catch (_error) {\n-      e2 = _error;","path":"lib/monaco-adapter.js","position":404,"original_position":404,"commit_id":"f6c350072c3808a9640346b41d748863dd45c025","original_commit_id":"f6c350072c3808a9640346b41d748863dd45c025","user":{"login":"Progyan1997","id":14367736,"node_id":"MDQ6VXNlcjE0MzY3NzM2","avatar_url":"https://avatars1.githubusercontent.com/u/14367736?v=4","gravatar_id":"","url":"https://api.github.com/users/Progyan1997","html_url":"https://github.com/Progyan1997","followers_url":"https://api.github.com/users/Progyan1997/followers","following_url":"https://api.github.com/users/Progyan1997/following{/other_user}","gists_url":"https://api.github.com/users/Progyan1997/gists{/gist_id}","starred_url":"https://api.github.com/users/Progyan1997/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Progyan1997/subscriptions","organizations_url":"https://api.github.com/users/Progyan1997/orgs","repos_url":"https://api.github.com/users/Progyan1997/repos","events_url":"https://api.github.com/users/Progyan1997/events{/privacy}","received_events_url":"https://api.github.com/users/Progyan1997/received_events","type":"User","site_admin":false},"body":"I didn't find any situation where statements above will throw any error.","created_at":"2019-02-22T08:16:09Z","updated_at":"2019-02-22T08:16:09Z","html_url":"https://github.com/FirebaseExtended/firepad/pull/325#discussion_r259246195","pull_request_url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/comments/259246195"},"html":{"href":"https://github.com/FirebaseExtended/firepad/pull/325#discussion_r259246195"},"pull_request":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325"}},"in_reply_to_id":259167804},"pull_request":{"url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325","id":244389119,"node_id":"MDExOlB1bGxSZXF1ZXN0MjQ0Mzg5MTE5","html_url":"https://github.com/FirebaseExtended/firepad/pull/325","diff_url":"https://github.com/FirebaseExtended/firepad/pull/325.diff","patch_url":"https://github.com/FirebaseExtended/firepad/pull/325.patch","issue_url":"https://api.github.com/repos/FirebaseExtended/firepad/issues/325","number":325,"state":"open","locked":false,"title":"Monaco Adapter: Rewrite from scratch in ES6+","user":{"login":"Progyan1997","id":14367736,"node_id":"MDQ6VXNlcjE0MzY3NzM2","avatar_url":"https://avatars1.githubusercontent.com/u/14367736?v=4","gravatar_id":"","url":"https://api.github.com/users/Progyan1997","html_url":"https://github.com/Progyan1997","followers_url":"https://api.github.com/users/Progyan1997/followers","following_url":"https://api.github.com/users/Progyan1997/following{/other_user}","gists_url":"https://api.github.com/users/Progyan1997/gists{/gist_id}","starred_url":"https://api.github.com/users/Progyan1997/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Progyan1997/subscriptions","organizations_url":"https://api.github.com/users/Progyan1997/orgs","repos_url":"https://api.github.com/users/Progyan1997/repos","events_url":"https://api.github.com/users/Progyan1997/events{/privacy}","received_events_url":"https://api.github.com/users/Progyan1997/received_events","type":"User","site_admin":false},"body":"Created only those APIs that are been called either by\r\nFirepad or EditorClient.\r\n\r\nSyncing between editors and cursors.\r\n\r\nUpdated package-lock, found 7 vulnerability with breaking\r\nchange update\r\n\r\nRemoved depenencies and function prototypes created while\r\ntranspiling from Coffescript code for Ace. Rewritten specific to\r\nMonaco Editor and it's API standards.\r\n\r\nAdd Build task to convert ES6+ codes into ES5 using Babel.\r\n\r\nAdd Testcases to verify changes from Monaco editor onChange\r\nevent handler to OT.js Text Operations.\r\n\r\nRef: #324 \r\nCloses: #313 \r\n\r\nSigned-off-by: Progyan Bhattacharya <Progyan@hackerrank.com>","created_at":"2019-01-14T10:05:24Z","updated_at":"2019-02-22T08:16:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3ec42b86368ad4a956d0b804f4108a63adcc2cbe","assignee":{"login":"samtstern","id":8466666,"node_id":"MDQ6VXNlcjg0NjY2NjY=","avatar_url":"https://avatars2.githubusercontent.com/u/8466666?v=4","gravatar_id":"","url":"https://api.github.com/users/samtstern","html_url":"https://github.com/samtstern","followers_url":"https://api.github.com/users/samtstern/followers","following_url":"https://api.github.com/users/samtstern/following{/other_user}","gists_url":"https://api.github.com/users/samtstern/gists{/gist_id}","starred_url":"https://api.github.com/users/samtstern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samtstern/subscriptions","organizations_url":"https://api.github.com/users/samtstern/orgs","repos_url":"https://api.github.com/users/samtstern/repos","events_url":"https://api.github.com/users/samtstern/events{/privacy}","received_events_url":"https://api.github.com/users/samtstern/received_events","type":"User","site_admin":false},"assignees":[{"login":"samtstern","id":8466666,"node_id":"MDQ6VXNlcjg0NjY2NjY=","avatar_url":"https://avatars2.githubusercontent.com/u/8466666?v=4","gravatar_id":"","url":"https://api.github.com/users/samtstern","html_url":"https://github.com/samtstern","followers_url":"https://api.github.com/users/samtstern/followers","following_url":"https://api.github.com/users/samtstern/following{/other_user}","gists_url":"https://api.github.com/users/samtstern/gists{/gist_id}","starred_url":"https://api.github.com/users/samtstern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samtstern/subscriptions","organizations_url":"https://api.github.com/users/samtstern/orgs","repos_url":"https://api.github.com/users/samtstern/repos","events_url":"https://api.github.com/users/samtstern/events{/privacy}","received_events_url":"https://api.github.com/users/samtstern/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325/commits","review_comments_url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325/comments","review_comment_url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/comments{/number}","comments_url":"https://api.github.com/repos/FirebaseExtended/firepad/issues/325/comments","statuses_url":"https://api.github.com/repos/FirebaseExtended/firepad/statuses/f6c350072c3808a9640346b41d748863dd45c025","head":{"label":"Progyan1997:develop","ref":"develop","sha":"f6c350072c3808a9640346b41d748863dd45c025","user":{"login":"Progyan1997","id":14367736,"node_id":"MDQ6VXNlcjE0MzY3NzM2","avatar_url":"https://avatars1.githubusercontent.com/u/14367736?v=4","gravatar_id":"","url":"https://api.github.com/users/Progyan1997","html_url":"https://github.com/Progyan1997","followers_url":"https://api.github.com/users/Progyan1997/followers","following_url":"https://api.github.com/users/Progyan1997/following{/other_user}","gists_url":"https://api.github.com/users/Progyan1997/gists{/gist_id}","starred_url":"https://api.github.com/users/Progyan1997/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Progyan1997/subscriptions","organizations_url":"https://api.github.com/users/Progyan1997/orgs","repos_url":"https://api.github.com/users/Progyan1997/repos","events_url":"https://api.github.com/users/Progyan1997/events{/privacy}","received_events_url":"https://api.github.com/users/Progyan1997/received_events","type":"User","site_admin":false},"repo":{"id":164127319,"node_id":"MDEwOlJlcG9zaXRvcnkxNjQxMjczMTk=","name":"firepad","full_name":"Progyan1997/firepad","private":false,"owner":{"login":"Progyan1997","id":14367736,"node_id":"MDQ6VXNlcjE0MzY3NzM2","avatar_url":"https://avatars1.githubusercontent.com/u/14367736?v=4","gravatar_id":"","url":"https://api.github.com/users/Progyan1997","html_url":"https://github.com/Progyan1997","followers_url":"https://api.github.com/users/Progyan1997/followers","following_url":"https://api.github.com/users/Progyan1997/following{/other_user}","gists_url":"https://api.github.com/users/Progyan1997/gists{/gist_id}","starred_url":"https://api.github.com/users/Progyan1997/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Progyan1997/subscriptions","organizations_url":"https://api.github.com/users/Progyan1997/orgs","repos_url":"https://api.github.com/users/Progyan1997/repos","events_url":"https://api.github.com/users/Progyan1997/events{/privacy}","received_events_url":"https://api.github.com/users/Progyan1997/received_events","type":"User","site_admin":false},"html_url":"https://github.com/Progyan1997/firepad","description":"Collaborative Text Editor Powered by Firebase","fork":true,"url":"https://api.github.com/repos/Progyan1997/firepad","forks_url":"https://api.github.com/repos/Progyan1997/firepad/forks","keys_url":"https://api.github.com/repos/Progyan1997/firepad/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Progyan1997/firepad/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Progyan1997/firepad/teams","hooks_url":"https://api.github.com/repos/Progyan1997/firepad/hooks","issue_events_url":"https://api.github.com/repos/Progyan1997/firepad/issues/events{/number}","events_url":"https://api.github.com/repos/Progyan1997/firepad/events","assignees_url":"https://api.github.com/repos/Progyan1997/firepad/assignees{/user}","branches_url":"https://api.github.com/repos/Progyan1997/firepad/branches{/branch}","tags_url":"https://api.github.com/repos/Progyan1997/firepad/tags","blobs_url":"https://api.github.com/repos/Progyan1997/firepad/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Progyan1997/firepad/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Progyan1997/firepad/git/refs{/sha}","trees_url":"https://api.github.com/repos/Progyan1997/firepad/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Progyan1997/firepad/statuses/{sha}","languages_url":"https://api.github.com/repos/Progyan1997/firepad/languages","stargazers_url":"https://api.github.com/repos/Progyan1997/firepad/stargazers","contributors_url":"https://api.github.com/repos/Progyan1997/firepad/contributors","subscribers_url":"https://api.github.com/repos/Progyan1997/firepad/subscribers","subscription_url":"https://api.github.com/repos/Progyan1997/firepad/subscription","commits_url":"https://api.github.com/repos/Progyan1997/firepad/commits{/sha}","git_commits_url":"https://api.github.com/repos/Progyan1997/firepad/git/commits{/sha}","comments_url":"https://api.github.com/repos/Progyan1997/firepad/comments{/number}","issue_comment_url":"https://api.github.com/repos/Progyan1997/firepad/issues/comments{/number}","contents_url":"https://api.github.com/repos/Progyan1997/firepad/contents/{+path}","compare_url":"https://api.github.com/repos/Progyan1997/firepad/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Progyan1997/firepad/merges","archive_url":"https://api.github.com/repos/Progyan1997/firepad/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Progyan1997/firepad/downloads","issues_url":"https://api.github.com/repos/Progyan1997/firepad/issues{/number}","pulls_url":"https://api.github.com/repos/Progyan1997/firepad/pulls{/number}","milestones_url":"https://api.github.com/repos/Progyan1997/firepad/milestones{/number}","notifications_url":"https://api.github.com/repos/Progyan1997/firepad/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Progyan1997/firepad/labels{/name}","releases_url":"https://api.github.com/repos/Progyan1997/firepad/releases{/id}","deployments_url":"https://api.github.com/repos/Progyan1997/firepad/deployments","created_at":"2019-01-04T16:02:18Z","updated_at":"2019-02-14T16:56:29Z","pushed_at":"2019-02-14T18:57:30Z","git_url":"git://github.com/Progyan1997/firepad.git","ssh_url":"git@github.com:Progyan1997/firepad.git","clone_url":"https://github.com/Progyan1997/firepad.git","svn_url":"https://github.com/Progyan1997/firepad","homepage":null,"size":40037,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"FirebaseExtended:master","ref":"master","sha":"25ce6f5f63e40f277899794198ecd573007f1128","user":{"login":"FirebaseExtended","id":42357678,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQyMzU3Njc4","avatar_url":"https://avatars0.githubusercontent.com/u/42357678?v=4","gravatar_id":"","url":"https://api.github.com/users/FirebaseExtended","html_url":"https://github.com/FirebaseExtended","followers_url":"https://api.github.com/users/FirebaseExtended/followers","following_url":"https://api.github.com/users/FirebaseExtended/following{/other_user}","gists_url":"https://api.github.com/users/FirebaseExtended/gists{/gist_id}","starred_url":"https://api.github.com/users/FirebaseExtended/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FirebaseExtended/subscriptions","organizations_url":"https://api.github.com/users/FirebaseExtended/orgs","repos_url":"https://api.github.com/users/FirebaseExtended/repos","events_url":"https://api.github.com/users/FirebaseExtended/events{/privacy}","received_events_url":"https://api.github.com/users/FirebaseExtended/received_events","type":"Organization","site_admin":false},"repo":{"id":9037027,"node_id":"MDEwOlJlcG9zaXRvcnk5MDM3MDI3","name":"firepad","full_name":"FirebaseExtended/firepad","private":false,"owner":{"login":"FirebaseExtended","id":42357678,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQyMzU3Njc4","avatar_url":"https://avatars0.githubusercontent.com/u/42357678?v=4","gravatar_id":"","url":"https://api.github.com/users/FirebaseExtended","html_url":"https://github.com/FirebaseExtended","followers_url":"https://api.github.com/users/FirebaseExtended/followers","following_url":"https://api.github.com/users/FirebaseExtended/following{/other_user}","gists_url":"https://api.github.com/users/FirebaseExtended/gists{/gist_id}","starred_url":"https://api.github.com/users/FirebaseExtended/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FirebaseExtended/subscriptions","organizations_url":"https://api.github.com/users/FirebaseExtended/orgs","repos_url":"https://api.github.com/users/FirebaseExtended/repos","events_url":"https://api.github.com/users/FirebaseExtended/events{/privacy}","received_events_url":"https://api.github.com/users/FirebaseExtended/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/FirebaseExtended/firepad","description":"Collaborative Text Editor Powered by Firebase","fork":false,"url":"https://api.github.com/repos/FirebaseExtended/firepad","forks_url":"https://api.github.com/repos/FirebaseExtended/firepad/forks","keys_url":"https://api.github.com/repos/FirebaseExtended/firepad/keys{/key_id}","collaborators_url":"https://api.github.com/repos/FirebaseExtended/firepad/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/FirebaseExtended/firepad/teams","hooks_url":"https://api.github.com/repos/FirebaseExtended/firepad/hooks","issue_events_url":"https://api.github.com/repos/FirebaseExtended/firepad/issues/events{/number}","events_url":"https://api.github.com/repos/FirebaseExtended/firepad/events","assignees_url":"https://api.github.com/repos/FirebaseExtended/firepad/assignees{/user}","branches_url":"https://api.github.com/repos/FirebaseExtended/firepad/branches{/branch}","tags_url":"https://api.github.com/repos/FirebaseExtended/firepad/tags","blobs_url":"https://api.github.com/repos/FirebaseExtended/firepad/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/FirebaseExtended/firepad/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/FirebaseExtended/firepad/git/refs{/sha}","trees_url":"https://api.github.com/repos/FirebaseExtended/firepad/git/trees{/sha}","statuses_url":"https://api.github.com/repos/FirebaseExtended/firepad/statuses/{sha}","languages_url":"https://api.github.com/repos/FirebaseExtended/firepad/languages","stargazers_url":"https://api.github.com/repos/FirebaseExtended/firepad/stargazers","contributors_url":"https://api.github.com/repos/FirebaseExtended/firepad/contributors","subscribers_url":"https://api.github.com/repos/FirebaseExtended/firepad/subscribers","subscription_url":"https://api.github.com/repos/FirebaseExtended/firepad/subscription","commits_url":"https://api.github.com/repos/FirebaseExtended/firepad/commits{/sha}","git_commits_url":"https://api.github.com/repos/FirebaseExtended/firepad/git/commits{/sha}","comments_url":"https://api.github.com/repos/FirebaseExtended/firepad/comments{/number}","issue_comment_url":"https://api.github.com/repos/FirebaseExtended/firepad/issues/comments{/number}","contents_url":"https://api.github.com/repos/FirebaseExtended/firepad/contents/{+path}","compare_url":"https://api.github.com/repos/FirebaseExtended/firepad/compare/{base}...{head}","merges_url":"https://api.github.com/repos/FirebaseExtended/firepad/merges","archive_url":"https://api.github.com/repos/FirebaseExtended/firepad/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/FirebaseExtended/firepad/downloads","issues_url":"https://api.github.com/repos/FirebaseExtended/firepad/issues{/number}","pulls_url":"https://api.github.com/repos/FirebaseExtended/firepad/pulls{/number}","milestones_url":"https://api.github.com/repos/FirebaseExtended/firepad/milestones{/number}","notifications_url":"https://api.github.com/repos/FirebaseExtended/firepad/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/FirebaseExtended/firepad/labels{/name}","releases_url":"https://api.github.com/repos/FirebaseExtended/firepad/releases{/id}","deployments_url":"https://api.github.com/repos/FirebaseExtended/firepad/deployments","created_at":"2013-03-26T18:16:29Z","updated_at":"2019-02-21T08:15:59Z","pushed_at":"2019-02-14T18:57:31Z","git_url":"git://github.com/FirebaseExtended/firepad.git","ssh_url":"git@github.com:FirebaseExtended/firepad.git","clone_url":"https://github.com/FirebaseExtended/firepad.git","svn_url":"https://github.com/FirebaseExtended/firepad","homepage":null,"size":40122,"stargazers_count":3142,"watchers_count":3142,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":721,"mirror_url":null,"archived":false,"open_issues_count":83,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":721,"open_issues":83,"watchers":3142,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325"},"html":{"href":"https://github.com/FirebaseExtended/firepad/pull/325"},"issue":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/issues/325"},"comments":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/issues/325/comments"},"review_comments":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325/comments"},"review_comment":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/pulls/325/commits"},"statuses":{"href":"https://api.github.com/repos/FirebaseExtended/firepad/statuses/f6c350072c3808a9640346b41d748863dd45c025"}},"author_association":"NONE"}}
{"actor":{"display_login":"Progyan1997"}}