{"action":"created","comment":{"url":"https://api.github.com/repos/emberjs/rfcs/pulls/comments/213375985","pull_request_review_id":150184090,"id":213375985,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMzM3NTk4NQ==","diff_hunk":"@@ -0,0 +1,323 @@\n+- Start Date: (fill me in with today's date, YYYY-MM-DD)\n+- RFC PR: (leave this empty)\n+- Ember Issue: (leave this empty)\n+\n+# Element Modifiers\n+\n+## Summary\n+\n+This RFC introduces the concept of user defined element modifiers. Unlike a component, there is no template/layout for an element modifier. Unlike a helper, an element modifier does not return a value.\n+\n+Below is an example of the element modifier syntax:\n+\n+```hbs\n+<button {{add-event-listener 'click' (action 'save')}}>Save</button>\n+```\n+\n+This RFC supercedes the [original element modifiers RFC](https://github.com/emberjs/rfcs/pull/112) and is intended to replace the [`this.bounds` RFC](https://github.com/emberjs/rfcs/pull/351).\n+\n+## Motivation\n+\n+Classic component instances have a `this.element` property which provides you a single DOM node as defined by `tagName`. The children of this node will be the DOM representation of what you wrote in your template. Templates are typically referred to having `innerHTML` semantics in classic components since there is a single wrapping element that is the parent of the template. These semantics allow for components to encapsulate some 3rd party JavaScript library or do some fine grain DOM manipulation.\n+\n+Glimmer components have `outerHTML` semantics, meaning what you see in the template is what you get in the DOM, there is no `tagName` that wraps the template. While this drastically simplifies the API for creating new components it makes reliable access to the a component's DOM structure very difficult to do. As [pointed out](https://github.com/emberjs/rfcs/pull/351#issuecomment-412123046) in the [Bounds RFC](https://github.com/emberjs/rfcs/pull/351) the stability of the nodes in the `Bounds` object creates way too many footguns. So a formalized way for accessing DOM in the Glimmer component world is still needed.\n+\n+Element modifiers allow for stable access of the DOM node they are installed on. This allows for programatic access to DOM in Glimmer templates and also offers a more targeted construct for cases where classic components were being used. The introduction of this API will likely result in the proliferation of one or several popular addons for managing element event listeners, style and animation.\n+\n+## Detailed design\n+\n+### Invocation\n+\n+An element modifier is invoked in \"element space\". This is the space between `<` and `>` opening an HTML tag. For example:\n+\n+```hbs\n+<button {{flummux}}></button>\n+<span {{whipperwill 'carrot'}}><i>Some DOM</i></span>\n+<b {{crum bing='whoop'}} zip=\"bango\">Hm...</b>\n+```\n+\n+Element modifiers may be invoked with params or hash arguments.\n+\n+### Definition and lookup\n+\n+A basic element modifier is defined with the type of `modifier`. For example these paths would be global element modifiers in an application:\n+\n+```\n+Classic paths:\n+\n+  app/modifiers/flummux.js\n+  app/modifiers/whipperwill.js\n+\n+MU paths:\n+\n+  src/ui/components/flummux/modifier.js\n+  src/ui/routes/posts/-components/whipperwill/modifier.js\n+```\n+\n+In Module Unification, modifiers live within the generalized collection type \"components\" [as specified](https://github.com/dgeb/rfcs/blob/module-unification/text/0000-module-unification.md#components). Modifiers, like component and helpers, are eligible for local lookup. For example:\n+\n+```\n+MU paths:\n+\n+  src/ui/routes/posts/-components/post-editor/flummux/modifier.js\n+```\n+\n+The element modifier class is a default export from these files. For example:\n+\n+```js\n+import Modifier from '@ember/modifier';\n+\n+export default class extends Modifier {}\n+```\n+\n+### Lifecycle Hooks\n+\n+During rendering and teardown of a target element, any attached element modifiers will execute a series of hooks. These hooks are:\n+\n+* `didInsertElement`\n+* `didUpdate`\n+* `willDestroyElement`\n+\n+It is important to note that in server-side rendering environments none of the lifecycle events are called.\n+\n+#### `didInsertElement` semantics\n+\n+`didInsertElement` is called when the element is in the DOM and it's children are attached. The element is available on `this.element` of the modifier instance. Unlike classic components, the `didInsertElement` hook receives the positional and named params as arguments in the same way helpers do. This hook is only called once.\n+\n+This hook has the following timing semantics:\n+\n+**Always**\n+- called **after** all children modifiers `didInsertElement` hook are called\n+- called **after** DOM insertion\n+\n+ **May or May Not**\n+- be called in the same tick as DOM insertion\n+- have the sibling nodes fully initialized in DOM\n+\n+Below is an example of how this hook could be used:\n+\n+```js\n+import Modifier from '@ember/modifier';\n+\n+export default class extends Modifier {\n+  this.listenerOptions = undefined;\n+  didInsertElement([ eventType, callback ], eventOptions) {\n+    this.listenerOptions = [\n+      eventType,\n+      callBack,\n+      eventOptions\n+    ];\n+    this.element.addEventListener(eventType, callback, eventOptions);\n+  }\n+}\n+```\n+\n+#### `didUpdate` semantics\n+\n+`didUpdate` is called whenever any of the parameters used by the modifier are updated. `didUpdate` has the same signature as `didInsertElement`.\n+\n+This hook has the following timing semantics:\n+\n+**Always**\n+- called **after** the arguments to the modifier have changed\n+\n+**Never**\n+- called if the arguments to the modifier are constants\n+\n+Below is an example of how this hook could be used:\n+\n+```js\n+import Modifier from '@ember/modifier';\n+\n+export default class extends Modifier {\n+  this.listenerOptions = undefined;\n+  didInsertElement([ eventType, callback ], eventOptions) {\n+    this.listenerOptions = [\n+      eventType,\n+      callBack,\n+      eventOptions\n+    ];\n+    this.element.addEventListener(eventType, callback, eventOptions);\n+  },\n+\n+  didUpdate([ eventType, callback ], eventOptions) {\n+    this.element.removeEventListener(...this.listenerOptions);\n+    this.element.addEventListener(eventType, callback, eventOptions);\n+    this.listenerOptions = [eventType, callback, eventOptions];\n+  }\n+}\n+```\n+\n+#### `willDestroyElement` semantics\n+\n+`willDestroyElement` is called during the destruction of a template. It receives no arguments.\n+\n+Below is an example of how this hook could be used:\n+\n+```js\n+import Modifier from '@ember/modifier';\n+\n+export default class extends Modifier {\n+  this.listenerOptions = undefined;\n+  didInsertElement([ eventType, callback ], eventOptions) {\n+    this.listenerOptions = [\n+      eventType,\n+      callBack,\n+      eventOptions\n+    ];\n+    this.element.addEventListener(eventType, callback, eventOptions);\n+  },\n+\n+  didUpdate([ eventType, callback ], eventOptions) {\n+    this.element.removeEventListener(...this.listenerOptions);\n+    this.element.addEventListener(eventType, callback, eventOptions);\n+    this.listenerOptions = [eventType, callback, eventOptions];\n+  }\n+\n+  willDestroyElement() {\n+    this.element.removeEventListener(...this.listenerOptions);\n+  }\n+}\n+```\n+\n+This hook has the following timing semantics:\n+\n+**Always**\n+- called **after** all children modifier's `willDestroyElement` hook is called\n+\n+ **May or May Not**\n+- be called in the same tick as DOM removal\n+\n+## Examples\n+\n+Below are some examples of what you could do with a modifier:\n+\n+### Performance Marking\n+```hbs\n+<section id=\"about-us\" {{performance 'mark' 'about-page'}}>\n+  <h1>About Us</h1>\n+  {{!-- snip --}}\n+</section>\n+```\n+\n+```js\n+import Modifier from '@ember/modifier';\n+\n+export Modifier.extend({\n+  didInsertElement([ type, marker ]) {\n+    performance[type](marker);\n+  }\n+});\n+```\n+\n+### jQuery Widget\n+```hbs\n+<input type=\"date\" {{datepicker changeMonth=true changeYear=true}} />\n+```\n+\n+```js\n+import Modifier from '@ember/modifier';\n+import $ from 'jquery';\n+\n+export Modifier.extend({\n+  didInsertElement(_params, hash) {\n+    $(this.element).datepicker(this._normalizeOptions(hash));\n+  },\n+\n+  _normalizeOptions(options) {\n+    return Object.assign(options, { minDate: 20, maxDate: '+1M +10D' });\n+  },\n+\n+  willDestroyElement() {\n+    $(this.element).datepicker('destroy');\n+  }\n+});\n+```\n+\n+### Page View Tracking\n+```hbs\n+<section {{track-impression eventCategory=\"Post\"}}>\n+  <header>Chad liked a post</header>\n+  <img src=\"cat.jpg\">\n+  {{!-- Snip --}}\n+<section>\n+```\n+\n+```js\n+import Modifier from '@ember/modifier';\n+import { inject as service } from '@ember/service';\n+\n+export Modifier.extend({\n+  ga: service('google-analytics'),\n+  init() {\n+    this._super(...arguments);\n+    this.eventCategory = undefined;\n+    this.interSectionObserver = new IntersectionObserver(entries => {\n+      entries.forEach(entry => {\n+        this.ga.send('event', 'impression', this.eventCategory);\n+      });\n+    });\n+  },\n+  didInsertElement(_params, { eventCategory }) {\n+    this.eventCategory = eventCategory;\n+    this.interSectionObserver.observe(this.element);\n+  },\n+\n+  willDestroyElement() {\n+    this.interSectionObserver.unobserve(this.element);\n+  }\n+});\n+```\n+\n+## How we teach this\n+\n+While user defined element modifiers are a new concept, Ember has had the [`{{action}}` modifier](https://www.emberjs.com/api/ember/release/classes/Ember.Templates.helpers/methods/action?anchor=action) since 1.0.0. We would need to update the existing documentation around `{{action}}` to refer to it as a modifier. In terms of documenting the modifier base class, I think we can largely repurpose existing documentation around [component's `didInsertElement`](https://guides.emberjs.com/release/components/the-component-lifecycle/#toc_integrating-with-third-party-libraries-with-didinsertelement) hook.\n+\n+In terms of guides, I believe we should add a section to the \"Templates\" section to outline how to write modifiers. This would be similar to the [\"Writing Helpers\"](https://guides.emberjs.com/release/templates/writing-helpers/) guide.\n+\n+## Drawbacks\n+\n+The drawbacks of adding element modifiers largely deal with explaining when to use a classic component for encapsulating some DOM manipulation versus when to use an element modifier. That being said it is likely that the recommendation would be to use element modifiers if you are just manually modifying the DOM.\n+\n+This API also doesn't attempt to create a corollary of `this.element` for Glimmer Components and instead offers a different API for altering DOM nodes directly. This expands the surface area of Ember's API.\n+\n+## Alternatives\n+\n+The alternative to this is to create a \"ref\"-like API that is available in [other client side frameworks](https://reactjs.org/docs/refs-and-the-dom.html). This may look like the following:","path":"text/0000-modifiers.md","position":286,"original_position":286,"commit_id":"929499ca334bd02aa9c08b1ed484b2267135b37b","original_commit_id":"929499ca334bd02aa9c08b1ed484b2267135b37b","user":{"login":"rwjblue","id":12637,"node_id":"MDQ6VXNlcjEyNjM3","avatar_url":"https://avatars0.githubusercontent.com/u/12637?v=4","gravatar_id":"","url":"https://api.github.com/users/rwjblue","html_url":"https://github.com/rwjblue","followers_url":"https://api.github.com/users/rwjblue/followers","following_url":"https://api.github.com/users/rwjblue/following{/other_user}","gists_url":"https://api.github.com/users/rwjblue/gists{/gist_id}","starred_url":"https://api.github.com/users/rwjblue/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rwjblue/subscriptions","organizations_url":"https://api.github.com/users/rwjblue/orgs","repos_url":"https://api.github.com/users/rwjblue/repos","events_url":"https://api.github.com/users/rwjblue/events{/privacy}","received_events_url":"https://api.github.com/users/rwjblue/received_events","type":"User","site_admin":false},"body":"I think that modifiers (as proposed here) allows a \"ref-like api\" to be implemented. Slightly modified example:\r\n\r\n```hbs\r\n<section>\r\n  <h1 {{ref this \"heading\"}}>Hello!</h1>\r\n  <p>How are you?</p>\r\n</section>\r\n```\r\n\r\nCould easily be implemented as a modifier:\r\n\r\n```js\r\nexport default class RefModifier extends Modifier {\r\n  didInsertElement([component, name]) {\r\n    component[name](this.element);\r\n  }\r\n\r\n  willDestroyElement([component, name]) {\r\n    component[name](null);\r\n  }\r\n}\r\n```\r\n\r\nIn other words, I don't think \"refs\" is an alternative to modifiers but instead is a valid use case of them...","created_at":"2018-08-28T16:04:38Z","updated_at":"2018-08-28T16:06:35Z","html_url":"https://github.com/emberjs/rfcs/pull/353#discussion_r213375985","pull_request_url":"https://api.github.com/repos/emberjs/rfcs/pulls/353","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/comments/213375985"},"html":{"href":"https://github.com/emberjs/rfcs/pull/353#discussion_r213375985"},"pull_request":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/353"}}},"pull_request":{"url":"https://api.github.com/repos/emberjs/rfcs/pulls/353","id":209013427,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA5MDEzNDI3","html_url":"https://github.com/emberjs/rfcs/pull/353","diff_url":"https://github.com/emberjs/rfcs/pull/353.diff","patch_url":"https://github.com/emberjs/rfcs/pull/353.patch","issue_url":"https://api.github.com/repos/emberjs/rfcs/issues/353","number":353,"state":"open","locked":false,"title":"Modifiers","user":{"login":"chadhietala","id":183799,"node_id":"MDQ6VXNlcjE4Mzc5OQ==","avatar_url":"https://avatars1.githubusercontent.com/u/183799?v=4","gravatar_id":"","url":"https://api.github.com/users/chadhietala","html_url":"https://github.com/chadhietala","followers_url":"https://api.github.com/users/chadhietala/followers","following_url":"https://api.github.com/users/chadhietala/following{/other_user}","gists_url":"https://api.github.com/users/chadhietala/gists{/gist_id}","starred_url":"https://api.github.com/users/chadhietala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chadhietala/subscriptions","organizations_url":"https://api.github.com/users/chadhietala/orgs","repos_url":"https://api.github.com/users/chadhietala/repos","events_url":"https://api.github.com/users/chadhietala/events{/privacy}","received_events_url":"https://api.github.com/users/chadhietala/received_events","type":"User","site_admin":false},"body":"[Rendered](https://github.com/emberjs/rfcs/blob/new-modifiers/text/0000-modifiers.md)","created_at":"2018-08-16T23:50:17Z","updated_at":"2018-08-28T16:06:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"07b1bd074a2ed53e8b1c98ad0ea5ee028b33ec6c","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/emberjs/rfcs/pulls/353/commits","review_comments_url":"https://api.github.com/repos/emberjs/rfcs/pulls/353/comments","review_comment_url":"https://api.github.com/repos/emberjs/rfcs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/emberjs/rfcs/issues/353/comments","statuses_url":"https://api.github.com/repos/emberjs/rfcs/statuses/929499ca334bd02aa9c08b1ed484b2267135b37b","head":{"label":"emberjs:new-modifiers","ref":"new-modifiers","sha":"929499ca334bd02aa9c08b1ed484b2267135b37b","user":{"login":"emberjs","id":1253363,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNTMzNjM=","avatar_url":"https://avatars2.githubusercontent.com/u/1253363?v=4","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"repo":{"id":22664562,"node_id":"MDEwOlJlcG9zaXRvcnkyMjY2NDU2Mg==","name":"rfcs","full_name":"emberjs/rfcs","owner":{"login":"emberjs","id":1253363,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNTMzNjM=","avatar_url":"https://avatars2.githubusercontent.com/u/1253363?v=4","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emberjs/rfcs","description":"RFCs for changes to Ember","fork":false,"url":"https://api.github.com/repos/emberjs/rfcs","forks_url":"https://api.github.com/repos/emberjs/rfcs/forks","keys_url":"https://api.github.com/repos/emberjs/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emberjs/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emberjs/rfcs/teams","hooks_url":"https://api.github.com/repos/emberjs/rfcs/hooks","issue_events_url":"https://api.github.com/repos/emberjs/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/emberjs/rfcs/events","assignees_url":"https://api.github.com/repos/emberjs/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/emberjs/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/emberjs/rfcs/tags","blobs_url":"https://api.github.com/repos/emberjs/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emberjs/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emberjs/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/emberjs/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emberjs/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/emberjs/rfcs/languages","stargazers_url":"https://api.github.com/repos/emberjs/rfcs/stargazers","contributors_url":"https://api.github.com/repos/emberjs/rfcs/contributors","subscribers_url":"https://api.github.com/repos/emberjs/rfcs/subscribers","subscription_url":"https://api.github.com/repos/emberjs/rfcs/subscription","commits_url":"https://api.github.com/repos/emberjs/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/emberjs/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/emberjs/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/emberjs/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/emberjs/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/emberjs/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emberjs/rfcs/merges","archive_url":"https://api.github.com/repos/emberjs/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emberjs/rfcs/downloads","issues_url":"https://api.github.com/repos/emberjs/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/emberjs/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/emberjs/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/emberjs/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emberjs/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/emberjs/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/emberjs/rfcs/deployments","created_at":"2014-08-06T00:49:22Z","updated_at":"2018-08-27T15:44:52Z","pushed_at":"2018-08-28T14:18:12Z","git_url":"git://github.com/emberjs/rfcs.git","ssh_url":"git@github.com:emberjs/rfcs.git","clone_url":"https://github.com/emberjs/rfcs.git","svn_url":"https://github.com/emberjs/rfcs","homepage":"https://emberjs.github.io/rfcs/","size":1619,"stargazers_count":615,"watchers_count":615,"language":"Shell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":271,"mirror_url":null,"archived":false,"open_issues_count":143,"license":null,"forks":271,"open_issues":143,"watchers":615,"default_branch":"master"}},"base":{"label":"emberjs:master","ref":"master","sha":"e2d845b69b9282982a37499b7f3a37dffb43d5dd","user":{"login":"emberjs","id":1253363,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNTMzNjM=","avatar_url":"https://avatars2.githubusercontent.com/u/1253363?v=4","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"repo":{"id":22664562,"node_id":"MDEwOlJlcG9zaXRvcnkyMjY2NDU2Mg==","name":"rfcs","full_name":"emberjs/rfcs","owner":{"login":"emberjs","id":1253363,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNTMzNjM=","avatar_url":"https://avatars2.githubusercontent.com/u/1253363?v=4","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emberjs/rfcs","description":"RFCs for changes to Ember","fork":false,"url":"https://api.github.com/repos/emberjs/rfcs","forks_url":"https://api.github.com/repos/emberjs/rfcs/forks","keys_url":"https://api.github.com/repos/emberjs/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emberjs/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emberjs/rfcs/teams","hooks_url":"https://api.github.com/repos/emberjs/rfcs/hooks","issue_events_url":"https://api.github.com/repos/emberjs/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/emberjs/rfcs/events","assignees_url":"https://api.github.com/repos/emberjs/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/emberjs/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/emberjs/rfcs/tags","blobs_url":"https://api.github.com/repos/emberjs/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emberjs/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emberjs/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/emberjs/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emberjs/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/emberjs/rfcs/languages","stargazers_url":"https://api.github.com/repos/emberjs/rfcs/stargazers","contributors_url":"https://api.github.com/repos/emberjs/rfcs/contributors","subscribers_url":"https://api.github.com/repos/emberjs/rfcs/subscribers","subscription_url":"https://api.github.com/repos/emberjs/rfcs/subscription","commits_url":"https://api.github.com/repos/emberjs/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/emberjs/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/emberjs/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/emberjs/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/emberjs/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/emberjs/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emberjs/rfcs/merges","archive_url":"https://api.github.com/repos/emberjs/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emberjs/rfcs/downloads","issues_url":"https://api.github.com/repos/emberjs/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/emberjs/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/emberjs/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/emberjs/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emberjs/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/emberjs/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/emberjs/rfcs/deployments","created_at":"2014-08-06T00:49:22Z","updated_at":"2018-08-27T15:44:52Z","pushed_at":"2018-08-28T14:18:12Z","git_url":"git://github.com/emberjs/rfcs.git","ssh_url":"git@github.com:emberjs/rfcs.git","clone_url":"https://github.com/emberjs/rfcs.git","svn_url":"https://github.com/emberjs/rfcs","homepage":"https://emberjs.github.io/rfcs/","size":1619,"stargazers_count":615,"watchers_count":615,"language":"Shell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":271,"mirror_url":null,"archived":false,"open_issues_count":143,"license":null,"forks":271,"open_issues":143,"watchers":615,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/353"},"html":{"href":"https://github.com/emberjs/rfcs/pull/353"},"issue":{"href":"https://api.github.com/repos/emberjs/rfcs/issues/353"},"comments":{"href":"https://api.github.com/repos/emberjs/rfcs/issues/353/comments"},"review_comments":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/353/comments"},"review_comment":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/emberjs/rfcs/pulls/353/commits"},"statuses":{"href":"https://api.github.com/repos/emberjs/rfcs/statuses/929499ca334bd02aa9c08b1ed484b2267135b37b"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"rwjblue"}}