{"action":"created","comment":{"url":"https://api.github.com/repos/rrweb-io/rrweb/pulls/comments/244526098","pull_request_review_id":188429290,"id":244526098,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0NDUyNjA5OA==","diff_hunk":"@@ -1,101 +1,94 @@\n-# 增量快照\n-\n-在完成一次全量快照之后，我们就需要基于当前视图状态观察所有可能对视图造成改动的事件，在 rrweb 中我们已经观察了以下事件（将不断增加）：\n-\n-- DOM 变动\n-  - 节点创建、销毁\n-  - 节点属性变化\n-  - 文本变化\n-- 鼠标移动\n-- 鼠标交互\n-  - mouse up、mouse down\n-  - click、double click、context menu\n-  - focus、blur\n-  - touch start、touch move、touch end\n-- 页面或元素滚动\n-- 视窗大小改变\n-- 输入\n+# Incremental snapshots\n+After completing a full snapshot, we need to record events that change the state.\n+\n+Right now, rrweb records the following events (we will expand upon this):\n+\n+- DOM changes\n+  - Node creation, deletion\n+  - Node attribute changes\n+  - Text changes\n+- Mouse movement\n+- Mouse interaction\n+  - mouse up, mouse down\n+  - click, double click, context menu\n+  - focus, blur\n+  - touch start, touch move, touch end\n+- Page or element scrolling\n+- Window size changes\n+- Input\n \n ## Mutation Observer\n+Since we don't execute any JavaScript during playback, we instead need to record all changes scripts make to the document.\n \n-由于我们在回放时不会执行所有的 JavaScript 脚本，所以例如这样的场景我们需要完整记录才能够实现回放：\n+Consider this example:\n+> User clicks a button. A dropdown menu appears. User selects the first item. The dropdown menu disappears.\n \n-> 点击 button，出现 dropdown menu，选择第一项，dropdown menu 消失\n+During playback, the dropdown menu does not automatically appear after the \"click button\" is executed, because the original JavaScript is not part of the recording. Thus, we need to record the creation of the dropdown menu DOM nodes, the selection of the first item, and subsequent deletion of the dropdown menu DOM nodes. This is the most difficult part.\n \n-回放时，在“点击 button”执行之后 dropdown menu 不会自动出现，因为已经没有 JavaScript 脚本为我们执行这件事，所以我们需要记录 dropdown menu 相关的 DOM 节点的创建以及后续的销毁，这也是录制中的最大难点。\n+Fortunately, modern browsers have provided us with a very powerful API which can do exactly this: [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).\n \n-好在现代浏览器已经给我们提供了非常强大的 API —— [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) 用来完成这一功能。\n+This documentation does not explain the basics of how MutationObserver works, but only focusses on aspects in particular relevant to rrweb.\n \n-此处我们不具体讲解 MutationObserver 的基本使用方式，只专注于在 rrweb 中我们需要做哪些特殊处理。\n+The first thing to understand is that MutationObserver uses a **Bulk Asynchronous** callback. Specifically, there will be a single callback after a series of DOM changes occur, and it is passed an array of multiple mutation records.\n \n-首先要了解 MutationObserver 的触发方式为**批量异步**回调，具体来说就是会在一系列 DOM 变化发生之后将这些变化一次性回调，传出的是一个 mutation 记录数组。\n+This mechanism is not problematic for normal use, because we do not only have the mutation record, but we can also directly access the DOM object of the mutated node as well as any parent, child and sibling nodes.\n \n-这一机制在常规使用时不会有问题，因为从 mutation 记录中我们可以获取到变更节点的 JS 对象，可以做很多等值比较以及访问父子、兄弟节点等操作来保证我们可以精准回放一条 mutation 记录。\n+However in rrweb, since we have a serialization process, we need more sophisticated soluation to be able to deal with various scenarios.\n \n-但是在 rrweb 中由于我们有序列化的过程，我们就需要更多精细的判断来应对各种场景。\n-\n-### 新增节点\n-\n-例如以下两种操作会生成相同的 DOM 结构，但是产生不同的 mutation 记录：\n+### Add node\n+For example, the following two operations generate the same DOM structure, but produce a different set of mutation records:\n \n ```\n body\n   n1\n     n2\n ```\n \n-1. 创建节点 n1 并 append 在 body 中，再创建节点 n2 并 append 在 n1 中。\n-2. 创建节点 n1、n2，将 n2 append 在 n1 中，再将 n1 append 在 body 中。\n-\n-第 1 种情况将产生两条 mutation 记录，分别为增加节点 n1 和增加节点 n2；第 2 种情况则只会产生一条 mutation 记录，即增加节点 n1。\n-\n-**注意**，在第一种情况下虽然 n1 append 时还没有子节点，但是由于上述的批量异步回调机制，当我们处理 mutation 记录时获取到的 n1 是已经有子节点 n2 的状态。\n-\n-受第二种情况的限制，我们在处理新增节点时必须遍历其所有子孙节点，才能保证所有新增节点都被记录，但是这一策略应用在第一种情况中就会导致 n2 被作为新增节点记录两次，回放时就会产生与原页面不一致的 DOM 结构。\n-\n-因此，在处理一次回调中的多个 mutation 记录时我们需要“惰性”处理新增节点，即在遍历每条 mutation 记录遇到新增节点时先收集，再在全部 mutation 遍历完毕之后对收集的新增节点进行去重操作，保证不遗漏节点的同时每个节点只被记录一次。\n-\n-在[序列化设计](./serialization.md)中已经介绍了我们需要维护一个 `id -> Node` 的映射，因此当出现新增节点时，我们需要将新节点序列化并加入映射中。但由于我们为了去重新增节点，选择在所有 mutation 记录遍历完毕之后才进行序列化，在以下示例中就会出现问题：\n-\n-1. mutation 记录1，新增节点 n1。我们暂不处理，等待最终去重后序列化。\n-2. mutation 记录2，n1 新增属性 a1。我们试图将它记录成一次增量快照，但会发现无法从映射中找到 n1 对应的 id，因为此时它还未被序列化。\n-\n-由此可见，由于我们对新增节点进行了延迟序列化的处理，所有 mutation 记录也都需要先收集，再新增节点去重并序列化之后再做处理。\n+1. Create node n1 and append it as child of body, then create node n2 and append it as child of n1.\n+2. Create nodes n1 and n2, then append n2 as child to of n1, then append n1 as child of body.\n \n-### 移除节点\n+In the first case, two mutation records will be generated, namely adding node n1 and adding node n2; in the second case, only one mutation record will be generated, that is, node n1 (including children) is added.\n \n-在处理移除节点时，我们需要做以下处理：\n+**Note**: In the first case, although n1 has no child node when it is added, due to the above-mentioned batch asynchronous callback mechanism, when we receive the mutation record and process the n1 node the it already has the child node n2 in the DOM.\n \n-1. 移除的节点还未被序列化，则说明是在本次 callback 中新增的节点，无需记录，并且从新增节点池中将其移除。\n-2. 上步中在一次 callback 中被新增又移除的节点我们将其称为 dropped node，用于最终处理新增节点时判断节点的父节点是否已经 drop。\n+Due to the second case, when processing new nodes we must traverse all its descendants to ensure that all new nodes are recorded, however this strategy will cause n2 to be (incorrectly) recorded during the first record. Then, when processing the second record, adding a the node for a second time will result in a DOM structure that is inconsistent with the original page during playback.\n \n-### 属性变化覆盖写\n+Therefore, when dealing with multiple mutation records in a callback, we need to \"lazely\" process the newly added nodes, that is, collect all nodes when we go through each mutation record, and then determine the the order they were added after all the mutations are processed. When new nodes are added we perform deduplication to ensure that no nodes are missed and each node is only recorded once.\n \n-尽管 MutationObserver 是异步批量回调，但是我们仍然可以认为在一次回调中发生的 mutations 之间时间间隔极短，因此在记录 DOM 属性变化时我们可以通过覆盖写的方式优化增量快照的体积。\n+We already introduced in [Serialization Design](./serialization.md) that we need to maintain a mapping of `id -> Node`, so when new nodes appear, we need to serialize the new nodes and add them to the map. But since we want to perform deduplication, and thus only serialize after all the mutation records have been processed, some problems may arise, as demonstrated in the following example:\n \n-例如对一个 `<textarea>` 进行 resize 操作，会触发大量的 width 和 height 属性变化的 mutation 记录。虽然完整记录会让回放更加真实，但是也可能导致增量快照数量大大增加。进行取舍之后，我认为在同一次 mutation callback 中只记录同一个节点某一属性的最终值即可，也就是后续的 mutation 记录会覆盖写之前已有的 mutation 记录中的属性变化部分。\n+1. mutation record 1, add node n1. We will not serialize it yet, since we are waiting for the final deduplication.\n+2. mutation record 2, n1 added attribute a1. We tried to record it as an incremental snapshot, but we found that we couldn't find the id for n1 from the map because it was not serialized yet.\n \n-## 鼠标移动\n+As you can see, since we have delayed serialize of the newly added nodes, all mutation records also need to be processed first, and then the new nodes are de-duplicated and serialized before processing.\n \n-通过记录鼠标移动位置，我们可以在回放时模拟鼠标移动轨迹。\n+### Remove node\n+When dealing with removing nodes, there are two cases we need to be aware of:\n \n-尽量保证回放时鼠标移动流畅的同时也要尽量减少对应增量快照的数量，所以我们需要在监听 mousemove 的同时进行两层节流处理。第一层是每 20 ms 最多记录一次鼠标坐标，第二层是每 500 ms 最多发送一次鼠标坐标集合，第二层的主要目的是避免一次请求内容过多而做的分段。\n+1. If the removed node has not been serialized, that indicates that it is a new node in this callback, so there is no need to record it, and we remove it from the newly added node pool.\n+2. If the node that was removed in a callback was added in the previous step we label it as a dropped node. It is used to determine whether the node's parent node has been dropped when the new node is finally processed.\n \n-### 时间逆推\n+### Attribute change overwrite write\n+Although MutationObserver is an asynchronous batch callback, we can still assume that the time interval between mutations occurring in a callback is extremely short, so we can optimize the size of the incremental snapshot by overwriting some data when recording the DOM property changes.\n \n-我们在每个增量快照生成时会记录一个时间戳，用于在回放时按正确的时间差回放。但是由于节流处理的影响，鼠标移动对应增量快照的时间戳会比实际记录时间要更晚，因此我们需要记录一个用于校正的负时间差，在回放时将时间校准。\n+For example, resizing a `<textarea>` will trigger a large number of mutation records with varying width and height properties. While a full record will make playback more realistic, it can also result in a large increase in the number of incremental snapshots. After making a trade-off, I think that only the final value of an attribute of the same node can be recorded in a single mutation callback, that is, each subsequent mutation record will overwrite the attribute change part of the mutation record that existing before the write.\n \n-## 输入\n+## Mouse movement\n+By recording the mouse movement position, we can simulate the mouse movement trajectory during playback.\n \n-我们需要观察 `<input>`, `<textarea>`, `<select>` 三种元素的输入，包含人为交互和程序设置两种途径的输入。\n+Try to ensure that the mouse moves smoothly during playback and also minimize the number of corresponding incremental snapshots, so we need to perform two layers of throttling while listening to mousemove. The first layer records the mouse coordinates at most once every 20 ms, the second layer sends the mouse coordinate set at most once every 500 ms, and the second layer's main purpose is to avoid segmentation when the recorded data is too large.\n \n-#### 人为交互\n+### Time reversal\n+We record a timestamp when each incremental snapshot is generated for playback at the correct time difference during playback. However, due to the effect of throttling, the time stamp of the mouse movement corresponding to the incremental snapshot will be later than the actual recording time, so we need to record a negative time difference for correction and time calibration during playback.\n \n-对于人为交互的操作我们主要靠监听 input 和 change 两个事件观察，需要注意的是对不同事件但值相同的情况进行去重。此外 `<input type=\"radio\" />` 也是一类特殊的控件，如果多个 radio 元素的组件 name 属性相同，那么当一个被选择时其他都会被反选，但是不会触发任何事件，因此我们需要单独处理。\n+## Input\n+We need to observe the input of the three elements `<input>`, `<textarea>`, `<select>`, including human input and programmatic changes.\n \n-### 程序设置\n+#### Human input","path":"docs/observer.md","position":150,"original_position":150,"commit_id":"b0b4a7770f41759f3964734b8f51d0e60dee5260","original_commit_id":"b0b4a7770f41759f3964734b8f51d0e60dee5260","user":{"login":"Yuyz0112","id":13651389,"node_id":"MDQ6VXNlcjEzNjUxMzg5","avatar_url":"https://avatars1.githubusercontent.com/u/13651389?v=4","gravatar_id":"","url":"https://api.github.com/users/Yuyz0112","html_url":"https://github.com/Yuyz0112","followers_url":"https://api.github.com/users/Yuyz0112/followers","following_url":"https://api.github.com/users/Yuyz0112/following{/other_user}","gists_url":"https://api.github.com/users/Yuyz0112/gists{/gist_id}","starred_url":"https://api.github.com/users/Yuyz0112/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Yuyz0112/subscriptions","organizations_url":"https://api.github.com/users/Yuyz0112/orgs","repos_url":"https://api.github.com/users/Yuyz0112/repos","events_url":"https://api.github.com/users/Yuyz0112/events{/privacy}","received_events_url":"https://api.github.com/users/Yuyz0112/received_events","type":"User","site_admin":false},"body":"Looks like should be `###`, mistake from the Chinese version.","created_at":"2018-12-30T07:27:41Z","updated_at":"2018-12-30T07:58:34Z","html_url":"https://github.com/rrweb-io/rrweb/pull/19#discussion_r244526098","pull_request_url":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/rrweb-io/rrweb/pulls/comments/244526098"},"html":{"href":"https://github.com/rrweb-io/rrweb/pull/19#discussion_r244526098"},"pull_request":{"href":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19"}}},"pull_request":{"url":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19","id":241422681,"node_id":"MDExOlB1bGxSZXF1ZXN0MjQxNDIyNjgx","html_url":"https://github.com/rrweb-io/rrweb/pull/19","diff_url":"https://github.com/rrweb-io/rrweb/pull/19.diff","patch_url":"https://github.com/rrweb-io/rrweb/pull/19.patch","issue_url":"https://api.github.com/repos/rrweb-io/rrweb/issues/19","number":19,"state":"open","locked":false,"title":"Translated design docs to English","user":{"login":"DvdGiessen","id":954385,"node_id":"MDQ6VXNlcjk1NDM4NQ==","avatar_url":"https://avatars0.githubusercontent.com/u/954385?v=4","gravatar_id":"","url":"https://api.github.com/users/DvdGiessen","html_url":"https://github.com/DvdGiessen","followers_url":"https://api.github.com/users/DvdGiessen/followers","following_url":"https://api.github.com/users/DvdGiessen/following{/other_user}","gists_url":"https://api.github.com/users/DvdGiessen/gists{/gist_id}","starred_url":"https://api.github.com/users/DvdGiessen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DvdGiessen/subscriptions","organizations_url":"https://api.github.com/users/DvdGiessen/orgs","repos_url":"https://api.github.com/users/DvdGiessen/repos","events_url":"https://api.github.com/users/DvdGiessen/events{/privacy}","received_events_url":"https://api.github.com/users/DvdGiessen/received_events","type":"User","site_admin":false},"body":"I took some time to better understand how rrweb works, and in that process took some time to translate the design documents into English.\r\n\r\nNow I'm absolutely certain I did get some things wrong, but hopefully this is a good starting point for others to improve upon, so I'm offering it up here as an initial version pull request. :)","created_at":"2018-12-29T04:00:10Z","updated_at":"2018-12-30T07:58:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2e38c59d4ac646d95351fed16a60cbcb4d7fc428","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19/commits","review_comments_url":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19/comments","review_comment_url":"https://api.github.com/repos/rrweb-io/rrweb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rrweb-io/rrweb/issues/19/comments","statuses_url":"https://api.github.com/repos/rrweb-io/rrweb/statuses/b0b4a7770f41759f3964734b8f51d0e60dee5260","head":{"label":"DvdGiessen:translate-design-docs","ref":"translate-design-docs","sha":"b0b4a7770f41759f3964734b8f51d0e60dee5260","user":{"login":"DvdGiessen","id":954385,"node_id":"MDQ6VXNlcjk1NDM4NQ==","avatar_url":"https://avatars0.githubusercontent.com/u/954385?v=4","gravatar_id":"","url":"https://api.github.com/users/DvdGiessen","html_url":"https://github.com/DvdGiessen","followers_url":"https://api.github.com/users/DvdGiessen/followers","following_url":"https://api.github.com/users/DvdGiessen/following{/other_user}","gists_url":"https://api.github.com/users/DvdGiessen/gists{/gist_id}","starred_url":"https://api.github.com/users/DvdGiessen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DvdGiessen/subscriptions","organizations_url":"https://api.github.com/users/DvdGiessen/orgs","repos_url":"https://api.github.com/users/DvdGiessen/repos","events_url":"https://api.github.com/users/DvdGiessen/events{/privacy}","received_events_url":"https://api.github.com/users/DvdGiessen/received_events","type":"User","site_admin":false},"repo":{"id":163458033,"node_id":"MDEwOlJlcG9zaXRvcnkxNjM0NTgwMzM=","name":"rrweb","full_name":"DvdGiessen/rrweb","private":false,"owner":{"login":"DvdGiessen","id":954385,"node_id":"MDQ6VXNlcjk1NDM4NQ==","avatar_url":"https://avatars0.githubusercontent.com/u/954385?v=4","gravatar_id":"","url":"https://api.github.com/users/DvdGiessen","html_url":"https://github.com/DvdGiessen","followers_url":"https://api.github.com/users/DvdGiessen/followers","following_url":"https://api.github.com/users/DvdGiessen/following{/other_user}","gists_url":"https://api.github.com/users/DvdGiessen/gists{/gist_id}","starred_url":"https://api.github.com/users/DvdGiessen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DvdGiessen/subscriptions","organizations_url":"https://api.github.com/users/DvdGiessen/orgs","repos_url":"https://api.github.com/users/DvdGiessen/repos","events_url":"https://api.github.com/users/DvdGiessen/events{/privacy}","received_events_url":"https://api.github.com/users/DvdGiessen/received_events","type":"User","site_admin":false},"html_url":"https://github.com/DvdGiessen/rrweb","description":"record and replay the web","fork":true,"url":"https://api.github.com/repos/DvdGiessen/rrweb","forks_url":"https://api.github.com/repos/DvdGiessen/rrweb/forks","keys_url":"https://api.github.com/repos/DvdGiessen/rrweb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DvdGiessen/rrweb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DvdGiessen/rrweb/teams","hooks_url":"https://api.github.com/repos/DvdGiessen/rrweb/hooks","issue_events_url":"https://api.github.com/repos/DvdGiessen/rrweb/issues/events{/number}","events_url":"https://api.github.com/repos/DvdGiessen/rrweb/events","assignees_url":"https://api.github.com/repos/DvdGiessen/rrweb/assignees{/user}","branches_url":"https://api.github.com/repos/DvdGiessen/rrweb/branches{/branch}","tags_url":"https://api.github.com/repos/DvdGiessen/rrweb/tags","blobs_url":"https://api.github.com/repos/DvdGiessen/rrweb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DvdGiessen/rrweb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DvdGiessen/rrweb/git/refs{/sha}","trees_url":"https://api.github.com/repos/DvdGiessen/rrweb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DvdGiessen/rrweb/statuses/{sha}","languages_url":"https://api.github.com/repos/DvdGiessen/rrweb/languages","stargazers_url":"https://api.github.com/repos/DvdGiessen/rrweb/stargazers","contributors_url":"https://api.github.com/repos/DvdGiessen/rrweb/contributors","subscribers_url":"https://api.github.com/repos/DvdGiessen/rrweb/subscribers","subscription_url":"https://api.github.com/repos/DvdGiessen/rrweb/subscription","commits_url":"https://api.github.com/repos/DvdGiessen/rrweb/commits{/sha}","git_commits_url":"https://api.github.com/repos/DvdGiessen/rrweb/git/commits{/sha}","comments_url":"https://api.github.com/repos/DvdGiessen/rrweb/comments{/number}","issue_comment_url":"https://api.github.com/repos/DvdGiessen/rrweb/issues/comments{/number}","contents_url":"https://api.github.com/repos/DvdGiessen/rrweb/contents/{+path}","compare_url":"https://api.github.com/repos/DvdGiessen/rrweb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DvdGiessen/rrweb/merges","archive_url":"https://api.github.com/repos/DvdGiessen/rrweb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DvdGiessen/rrweb/downloads","issues_url":"https://api.github.com/repos/DvdGiessen/rrweb/issues{/number}","pulls_url":"https://api.github.com/repos/DvdGiessen/rrweb/pulls{/number}","milestones_url":"https://api.github.com/repos/DvdGiessen/rrweb/milestones{/number}","notifications_url":"https://api.github.com/repos/DvdGiessen/rrweb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DvdGiessen/rrweb/labels{/name}","releases_url":"https://api.github.com/repos/DvdGiessen/rrweb/releases{/id}","deployments_url":"https://api.github.com/repos/DvdGiessen/rrweb/deployments","created_at":"2018-12-28T23:34:53Z","updated_at":"2018-12-29T12:16:50Z","pushed_at":"2018-12-29T16:59:35Z","git_url":"git://github.com/DvdGiessen/rrweb.git","ssh_url":"git@github.com:DvdGiessen/rrweb.git","clone_url":"https://github.com/DvdGiessen/rrweb.git","svn_url":"https://github.com/DvdGiessen/rrweb","homepage":"https://www.rrweb.io/","size":211,"stargazers_count":0,"watchers_count":0,"language":"TypeScript","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":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rrweb-io:master","ref":"master","sha":"e6ad2bc1d330d83588dfb6f56870af33755e59e7","user":{"login":"rrweb-io","id":43396833,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQzMzk2ODMz","avatar_url":"https://avatars0.githubusercontent.com/u/43396833?v=4","gravatar_id":"","url":"https://api.github.com/users/rrweb-io","html_url":"https://github.com/rrweb-io","followers_url":"https://api.github.com/users/rrweb-io/followers","following_url":"https://api.github.com/users/rrweb-io/following{/other_user}","gists_url":"https://api.github.com/users/rrweb-io/gists{/gist_id}","starred_url":"https://api.github.com/users/rrweb-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrweb-io/subscriptions","organizations_url":"https://api.github.com/users/rrweb-io/orgs","repos_url":"https://api.github.com/users/rrweb-io/repos","events_url":"https://api.github.com/users/rrweb-io/events{/privacy}","received_events_url":"https://api.github.com/users/rrweb-io/received_events","type":"Organization","site_admin":false},"repo":{"id":151843254,"node_id":"MDEwOlJlcG9zaXRvcnkxNTE4NDMyNTQ=","name":"rrweb","full_name":"rrweb-io/rrweb","private":false,"owner":{"login":"rrweb-io","id":43396833,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQzMzk2ODMz","avatar_url":"https://avatars0.githubusercontent.com/u/43396833?v=4","gravatar_id":"","url":"https://api.github.com/users/rrweb-io","html_url":"https://github.com/rrweb-io","followers_url":"https://api.github.com/users/rrweb-io/followers","following_url":"https://api.github.com/users/rrweb-io/following{/other_user}","gists_url":"https://api.github.com/users/rrweb-io/gists{/gist_id}","starred_url":"https://api.github.com/users/rrweb-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrweb-io/subscriptions","organizations_url":"https://api.github.com/users/rrweb-io/orgs","repos_url":"https://api.github.com/users/rrweb-io/repos","events_url":"https://api.github.com/users/rrweb-io/events{/privacy}","received_events_url":"https://api.github.com/users/rrweb-io/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/rrweb-io/rrweb","description":"record and replay the web","fork":false,"url":"https://api.github.com/repos/rrweb-io/rrweb","forks_url":"https://api.github.com/repos/rrweb-io/rrweb/forks","keys_url":"https://api.github.com/repos/rrweb-io/rrweb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rrweb-io/rrweb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rrweb-io/rrweb/teams","hooks_url":"https://api.github.com/repos/rrweb-io/rrweb/hooks","issue_events_url":"https://api.github.com/repos/rrweb-io/rrweb/issues/events{/number}","events_url":"https://api.github.com/repos/rrweb-io/rrweb/events","assignees_url":"https://api.github.com/repos/rrweb-io/rrweb/assignees{/user}","branches_url":"https://api.github.com/repos/rrweb-io/rrweb/branches{/branch}","tags_url":"https://api.github.com/repos/rrweb-io/rrweb/tags","blobs_url":"https://api.github.com/repos/rrweb-io/rrweb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rrweb-io/rrweb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rrweb-io/rrweb/git/refs{/sha}","trees_url":"https://api.github.com/repos/rrweb-io/rrweb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rrweb-io/rrweb/statuses/{sha}","languages_url":"https://api.github.com/repos/rrweb-io/rrweb/languages","stargazers_url":"https://api.github.com/repos/rrweb-io/rrweb/stargazers","contributors_url":"https://api.github.com/repos/rrweb-io/rrweb/contributors","subscribers_url":"https://api.github.com/repos/rrweb-io/rrweb/subscribers","subscription_url":"https://api.github.com/repos/rrweb-io/rrweb/subscription","commits_url":"https://api.github.com/repos/rrweb-io/rrweb/commits{/sha}","git_commits_url":"https://api.github.com/repos/rrweb-io/rrweb/git/commits{/sha}","comments_url":"https://api.github.com/repos/rrweb-io/rrweb/comments{/number}","issue_comment_url":"https://api.github.com/repos/rrweb-io/rrweb/issues/comments{/number}","contents_url":"https://api.github.com/repos/rrweb-io/rrweb/contents/{+path}","compare_url":"https://api.github.com/repos/rrweb-io/rrweb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rrweb-io/rrweb/merges","archive_url":"https://api.github.com/repos/rrweb-io/rrweb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rrweb-io/rrweb/downloads","issues_url":"https://api.github.com/repos/rrweb-io/rrweb/issues{/number}","pulls_url":"https://api.github.com/repos/rrweb-io/rrweb/pulls{/number}","milestones_url":"https://api.github.com/repos/rrweb-io/rrweb/milestones{/number}","notifications_url":"https://api.github.com/repos/rrweb-io/rrweb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rrweb-io/rrweb/labels{/name}","releases_url":"https://api.github.com/repos/rrweb-io/rrweb/releases{/id}","deployments_url":"https://api.github.com/repos/rrweb-io/rrweb/deployments","created_at":"2018-10-06T13:35:55Z","updated_at":"2018-12-30T07:54:48Z","pushed_at":"2018-12-29T14:31:02Z","git_url":"git://github.com/rrweb-io/rrweb.git","ssh_url":"git@github.com:rrweb-io/rrweb.git","clone_url":"https://github.com/rrweb-io/rrweb.git","svn_url":"https://github.com/rrweb-io/rrweb","homepage":"https://www.rrweb.io/","size":193,"stargazers_count":1223,"watchers_count":1223,"language":"TypeScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":50,"mirror_url":null,"archived":false,"open_issues_count":10,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":50,"open_issues":10,"watchers":1223,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19"},"html":{"href":"https://github.com/rrweb-io/rrweb/pull/19"},"issue":{"href":"https://api.github.com/repos/rrweb-io/rrweb/issues/19"},"comments":{"href":"https://api.github.com/repos/rrweb-io/rrweb/issues/19/comments"},"review_comments":{"href":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19/comments"},"review_comment":{"href":"https://api.github.com/repos/rrweb-io/rrweb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rrweb-io/rrweb/pulls/19/commits"},"statuses":{"href":"https://api.github.com/repos/rrweb-io/rrweb/statuses/b0b4a7770f41759f3964734b8f51d0e60dee5260"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"Yuyz0112"}}