{"action":"created","comment":{"url":"https://api.github.com/repos/angular/material2/pulls/comments/59959266","id":59959266,"diff_hunk":"@@ -0,0 +1,239 @@\n+import {Injectable} from 'angular2/core';\n+import {Http} from 'angular2/http';\n+import {Observable} from 'rxjs/Rx';\n+\n+/**\n+  *  Configuration for an icon, including the URL and possibly the cached SVG element.\n+  */\n+class IconConfig {\n+  svgElement: SVGElement = null;\n+  constructor(public url: string) {\n+  }\n+}\n+\n+@Injectable()\n+export class MdIconRegistry {\n+  // IconConfig objects and cached SVG elements for individual icons.\n+  // First level of cache is namespace (which is the empty string if not specified).\n+  // Second level is the icon name within the namespace.\n+  private _iconConfigs = new Map<string, Map<string, IconConfig>>();\n+\n+  // IconConfig objects and cached SVG elements for icon sets.\n+  // Multiple icon sets can be registered under the same namespace.\n+  private _iconSetConfigs = new Map<string, IconConfig[]>();\n+\n+  // Cache for icons loaded by direct URLs.\n+  private _cachedIconsByUrl = new Map<string, SVGElement>();\n+\n+  private _fontClassNamesByAlias = new Map<string, string>();\n+\n+  private _inProgressUrlFetches = new Map<string, Observable<string>>();\n+\n+  private _defaultFontSetClass = 'material-icons';\n+\n+  constructor(private _http: Http) {\n+  }\n+\n+  public addIcon(iconName: string, url: string): this {\n+    return this.addIconInNamespace('', iconName, url);\n+  }\n+\n+  public addIconInNamespace(namespace: string, iconName: string, url: string): this {\n+    let iconSetMap = this._iconConfigs.get(namespace);\n+    if (!iconSetMap) {\n+      iconSetMap = new Map<string, IconConfig>();\n+      this._iconConfigs.set(namespace, iconSetMap);\n+    }\n+    iconSetMap.set(iconName, new IconConfig(url));\n+    return this;\n+  }\n+\n+  public addIconSet(url: string): this {\n+      return this.addIconSetInNamespace('', url);\n+  }\n+\n+  public addIconSetInNamespace(namespace: string, url: string): this {\n+    const config = new IconConfig(url);\n+    if (this._iconSetConfigs.has(namespace)) {\n+      this._iconSetConfigs.get(namespace).push(config);\n+    } else {\n+      this._iconSetConfigs.set(namespace, [config]);\n+    }\n+    return this;\n+  }\n+\n+  public registerFontSet(alias: string, className?: string): this {\n+    this._fontClassNamesByAlias.set(alias, className || alias);\n+    return this;\n+  }\n+\n+  public setDefaultFontSetClass(className: string) {\n+    this._defaultFontSetClass = className;\n+    return this;\n+  }\n+\n+  public getDefaultFontSetClass(): string {\n+    return this._defaultFontSetClass;\n+  }\n+\n+  loadIconFromNamespaceByName(namespace: string, iconName: string): Observable<SVGElement> {\n+    // Return (copy of) cached icon if possible.\n+    if (this._iconConfigs.has(namespace) && this._iconConfigs.get(namespace).has(iconName)) {\n+      const config = this._iconConfigs.get(namespace).get(iconName);\n+      if (config.svgElement) {\n+        // We already have the SVG element for this icon, return a copy.\n+        return Observable.of(config.svgElement.cloneNode(true));\n+      } else {\n+        // Fetch the icon from the config's URL, cache it, and return a copy.\n+        return this._loadIconFromConfig(config)\n+          .do((svg: SVGElement) => config.svgElement = svg)\n+          .map((svg: SVGElement) => svg.cloneNode(true));\n+      }\n+    }\n+    // See if we have any icon sets registered for the set name.\n+    const iconSetConfigs = this._iconSetConfigs.get(namespace);\n+    if (iconSetConfigs) {\n+      // For all the icon set SVG elements we've fetched, see if any contain an icon with the\n+      // requested name.\n+      const namedIcon = this._extractIconWithNameFromAnySet(iconName, iconSetConfigs);\n+      if (namedIcon) {\n+        // We could cache namedSvg in _iconConfigs, but since we have to make a copy every\n+        // time anyway, there's probably not much advantage compared to just always extracting\n+        // it from the icon set.\n+        return Observable.of(namedIcon);\n+      }\n+      // Not found in any cached icon sets. If there are icon sets with URLs that we haven't\n+      // fetched, fetch them now and look for iconName in the results.\n+      const iconSetFetchRequests = <[Observable<SVGElement>]>[];\n+      iconSetConfigs.forEach((setConfig) => {\n+        if (!setConfig.svgElement) {\n+          iconSetFetchRequests.push(\n+              this._loadIconSetFromConfig(setConfig)\n+                  .catch((err: any, source: any, caught: any): Observable<SVGElement> => {\n+                    // Swallow errors fetching individual URLs so the combined Observable won't\n+                    // necessarily fail.\n+                    console.log(`Loading icon set URL: ${setConfig.url} failed with error: ${err}`);\n+                    return Observable.of(null);\n+                  })\n+                  .do((svg: SVGElement) => {\n+                    // Cache SVG element.\n+                    if (svg) {\n+                      setConfig.svgElement = svg;\n+                    }\n+                  })\n+          );\n+        }\n+      });\n+      // Fetch all the icon set URLs. When the requests complete, every IconSet should have a\n+      // cached SVG element (unless the request failed), and we can check again for the icon.\n+      return Observable.forkJoin(iconSetFetchRequests)\n+        .map((ignoredResults: any) => {\n+          const foundIcon = this._extractIconWithNameFromAnySet(iconName, iconSetConfigs);\n+          if (!foundIcon) {\n+            throw Error(`Failed to find icon name: ${iconName} in namespace: ${namespace}`);\n+          }\n+          return foundIcon;\n+        });\n+    }\n+    return Observable.throw(Error(`Unknown icon name: ${iconName} in namespace: ${namespace}`));\n+  }\n+\n+  private _extractIconWithNameFromAnySet(iconName: string, setConfigs: IconConfig[]): SVGElement {\n+    // Iterate backwards, so icon sets added later have precedence.\n+    for (let i = setConfigs.length - 1; i >= 0; i--) {\n+      const config = setConfigs[i];\n+      if (config.svgElement) {\n+        const foundIcon = this._extractSvgIconFromSet(config.svgElement, iconName, config);\n+        if (foundIcon) {\n+          return foundIcon;\n+        }\n+      }\n+    }\n+    return null;\n+  }\n+\n+  loadIconFromUrl(url: string): Observable<SVGElement> {\n+    if (this._cachedIconsByUrl.has(url)) {\n+      return Observable.of(this._cachedIconsByUrl.get(url).cloneNode(true));\n+    }\n+    return this._loadIconFromConfig(new IconConfig(url))\n+        .do((svg: SVGElement) => this._cachedIconsByUrl.set(url, svg));\n+  }\n+\n+  classNameForFontAlias(alias: string): string {\n+    return this._fontClassNamesByAlias.get(alias) || alias;\n+  }\n+\n+  private _fetchUrl(url: string): Observable<string> {\n+    // Store in-progress fetches to avoid sending a duplicate request for a URL when there is\n+    // already a request in progress for that URL. It's necessary to call share() on the\n+    // Observable returned by http.get() so that multiple subscribers don't cause multiple XHRs.\n+    if (this._inProgressUrlFetches.has(url)) {\n+      return this._inProgressUrlFetches.get(url);\n+    }\n+    const req = this._http.get(url)\n+        .map((response) => response.text())\n+        .finally(() => {\n+          this._inProgressUrlFetches.delete(url);\n+        })\n+        .share();\n+    this._inProgressUrlFetches.set(url, req);\n+    return req;\n+  }\n+\n+  private _loadIconFromConfig(config: IconConfig): Observable<SVGElement> {\n+    return this._fetchUrl(config.url)\n+        .map(svgText => this._createSvgElementForSingleIcon(svgText, config));\n+  }\n+\n+  private _loadIconSetFromConfig(config: IconConfig): Observable<SVGElement> {\n+    return this._fetchUrl(config.url)\n+        .map((svgText) => this._svgElementFromString(svgText));\n+  }\n+\n+  private _createSvgElementForSingleIcon(responseText: string, config: IconConfig): SVGElement {\n+    const svg = this._svgElementFromString(responseText);\n+    this._setSvgAttributes(svg, config);\n+    return svg;\n+  }\n+\n+  private _setSvgAttributes(svg: SVGElement, config: IconConfig) {\n+    if (!svg.getAttribute('xmlns')) {\n+      svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n+    }\n+    svg.setAttribute('fit', '');\n+    svg.setAttribute('height', '100%');\n+    svg.setAttribute('width', '100%');\n+    svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');\n+    svg.setAttribute('focusable', 'false'); // Disable IE11 default behavior to make SVGs focusable.\n+  }\n+\n+  private _extractSvgIconFromSet(\n+      iconSet: SVGElement, iconName: string, config: IconConfig): SVGElement {\n+    const iconNode = iconSet.querySelector('#' + iconName);\n+    if (!iconNode) {\n+      return null;\n+    }\n+    // createElement('SVG') doesn't work as expected; the DOM ends up with\n+    // the correct nodes, but the SVG content doesn't render. Instead we\n+    // have to create an empty SVG node using innerHTML and append its content.\n+    // http://stackoverflow.com/questions/23003278/svg-innerhtml-in-firefox-can-not-display\n+    const svg = this._svgElementFromString('<svg></svg>');\n+    // Clone the node so we don't remove it from the parent icon set element.\n+    svg.appendChild(iconNode.cloneNode(true));","path":"src/components/icon/icon-registry.ts","position":223,"original_position":223,"commit_id":"03bcbed1c9c1ed8c6eac5037e6fddeb5456be907","original_commit_id":"03bcbed1c9c1ed8c6eac5037e6fddeb5456be907","user":{"login":"jelbourn","id":838736,"avatar_url":"https://avatars.githubusercontent.com/u/838736?v=3","gravatar_id":"","url":"https://api.github.com/users/jelbourn","html_url":"https://github.com/jelbourn","followers_url":"https://api.github.com/users/jelbourn/followers","following_url":"https://api.github.com/users/jelbourn/following{/other_user}","gists_url":"https://api.github.com/users/jelbourn/gists{/gist_id}","starred_url":"https://api.github.com/users/jelbourn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jelbourn/subscriptions","organizations_url":"https://api.github.com/users/jelbourn/orgs","repos_url":"https://api.github.com/users/jelbourn/repos","events_url":"https://api.github.com/users/jelbourn/events{/privacy}","received_events_url":"https://api.github.com/users/jelbourn/received_events","type":"User","site_admin":false},"body":"Is this making any assumptions about the element type of `iconNode`? ","created_at":"2016-04-16T01:05:20Z","updated_at":"2016-04-16T01:05:20Z","html_url":"https://github.com/angular/material2/pull/281#discussion_r59959266","pull_request_url":"https://api.github.com/repos/angular/material2/pulls/281","_links":{"self":{"href":"https://api.github.com/repos/angular/material2/pulls/comments/59959266"},"html":{"href":"https://github.com/angular/material2/pull/281#discussion_r59959266"},"pull_request":{"href":"https://api.github.com/repos/angular/material2/pulls/281"}}},"pull_request":{"url":"https://api.github.com/repos/angular/material2/pulls/281","id":65832490,"html_url":"https://github.com/angular/material2/pull/281","diff_url":"https://github.com/angular/material2/pull/281.diff","patch_url":"https://github.com/angular/material2/pull/281.patch","issue_url":"https://api.github.com/repos/angular/material2/issues/281","number":281,"state":"open","locked":false,"title":"md-icon (in-progress)","user":{"login":"dozingcat","id":489398,"avatar_url":"https://avatars.githubusercontent.com/u/489398?v=3","gravatar_id":"","url":"https://api.github.com/users/dozingcat","html_url":"https://github.com/dozingcat","followers_url":"https://api.github.com/users/dozingcat/followers","following_url":"https://api.github.com/users/dozingcat/following{/other_user}","gists_url":"https://api.github.com/users/dozingcat/gists{/gist_id}","starred_url":"https://api.github.com/users/dozingcat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dozingcat/subscriptions","organizations_url":"https://api.github.com/users/dozingcat/orgs","repos_url":"https://api.github.com/users/dozingcat/repos","events_url":"https://api.github.com/users/dozingcat/events{/privacy}","received_events_url":"https://api.github.com/users/dozingcat/received_events","type":"User","site_admin":false},"body":"Preview PR for md-icon. Doc at https://docs.google.com/a/google.com/document/d/1zWTjnSLFPV4II9IxpIehyeSFtnzw_efdy7kEerMRIuo/edit?usp=sharing","created_at":"2016-04-08T19:04:13Z","updated_at":"2016-04-16T01:05:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"01d165731e483e18b9a4c4a37ea471ccad64da95","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/angular/material2/pulls/281/commits","review_comments_url":"https://api.github.com/repos/angular/material2/pulls/281/comments","review_comment_url":"https://api.github.com/repos/angular/material2/pulls/comments{/number}","comments_url":"https://api.github.com/repos/angular/material2/issues/281/comments","statuses_url":"https://api.github.com/repos/angular/material2/statuses/03bcbed1c9c1ed8c6eac5037e6fddeb5456be907","head":{"label":"dozingcat:mdicon","ref":"mdicon","sha":"03bcbed1c9c1ed8c6eac5037e6fddeb5456be907","user":{"login":"dozingcat","id":489398,"avatar_url":"https://avatars.githubusercontent.com/u/489398?v=3","gravatar_id":"","url":"https://api.github.com/users/dozingcat","html_url":"https://github.com/dozingcat","followers_url":"https://api.github.com/users/dozingcat/followers","following_url":"https://api.github.com/users/dozingcat/following{/other_user}","gists_url":"https://api.github.com/users/dozingcat/gists{/gist_id}","starred_url":"https://api.github.com/users/dozingcat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dozingcat/subscriptions","organizations_url":"https://api.github.com/users/dozingcat/orgs","repos_url":"https://api.github.com/users/dozingcat/repos","events_url":"https://api.github.com/users/dozingcat/events{/privacy}","received_events_url":"https://api.github.com/users/dozingcat/received_events","type":"User","site_admin":false},"repo":{"id":53767913,"name":"material2","full_name":"dozingcat/material2","owner":{"login":"dozingcat","id":489398,"avatar_url":"https://avatars.githubusercontent.com/u/489398?v=3","gravatar_id":"","url":"https://api.github.com/users/dozingcat","html_url":"https://github.com/dozingcat","followers_url":"https://api.github.com/users/dozingcat/followers","following_url":"https://api.github.com/users/dozingcat/following{/other_user}","gists_url":"https://api.github.com/users/dozingcat/gists{/gist_id}","starred_url":"https://api.github.com/users/dozingcat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dozingcat/subscriptions","organizations_url":"https://api.github.com/users/dozingcat/orgs","repos_url":"https://api.github.com/users/dozingcat/repos","events_url":"https://api.github.com/users/dozingcat/events{/privacy}","received_events_url":"https://api.github.com/users/dozingcat/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dozingcat/material2","description":"Material Design components for Angular 2","fork":true,"url":"https://api.github.com/repos/dozingcat/material2","forks_url":"https://api.github.com/repos/dozingcat/material2/forks","keys_url":"https://api.github.com/repos/dozingcat/material2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dozingcat/material2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dozingcat/material2/teams","hooks_url":"https://api.github.com/repos/dozingcat/material2/hooks","issue_events_url":"https://api.github.com/repos/dozingcat/material2/issues/events{/number}","events_url":"https://api.github.com/repos/dozingcat/material2/events","assignees_url":"https://api.github.com/repos/dozingcat/material2/assignees{/user}","branches_url":"https://api.github.com/repos/dozingcat/material2/branches{/branch}","tags_url":"https://api.github.com/repos/dozingcat/material2/tags","blobs_url":"https://api.github.com/repos/dozingcat/material2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dozingcat/material2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dozingcat/material2/git/refs{/sha}","trees_url":"https://api.github.com/repos/dozingcat/material2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dozingcat/material2/statuses/{sha}","languages_url":"https://api.github.com/repos/dozingcat/material2/languages","stargazers_url":"https://api.github.com/repos/dozingcat/material2/stargazers","contributors_url":"https://api.github.com/repos/dozingcat/material2/contributors","subscribers_url":"https://api.github.com/repos/dozingcat/material2/subscribers","subscription_url":"https://api.github.com/repos/dozingcat/material2/subscription","commits_url":"https://api.github.com/repos/dozingcat/material2/commits{/sha}","git_commits_url":"https://api.github.com/repos/dozingcat/material2/git/commits{/sha}","comments_url":"https://api.github.com/repos/dozingcat/material2/comments{/number}","issue_comment_url":"https://api.github.com/repos/dozingcat/material2/issues/comments{/number}","contents_url":"https://api.github.com/repos/dozingcat/material2/contents/{+path}","compare_url":"https://api.github.com/repos/dozingcat/material2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dozingcat/material2/merges","archive_url":"https://api.github.com/repos/dozingcat/material2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dozingcat/material2/downloads","issues_url":"https://api.github.com/repos/dozingcat/material2/issues{/number}","pulls_url":"https://api.github.com/repos/dozingcat/material2/pulls{/number}","milestones_url":"https://api.github.com/repos/dozingcat/material2/milestones{/number}","notifications_url":"https://api.github.com/repos/dozingcat/material2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dozingcat/material2/labels{/name}","releases_url":"https://api.github.com/repos/dozingcat/material2/releases{/id}","deployments_url":"https://api.github.com/repos/dozingcat/material2/deployments","created_at":"2016-03-13T04:44:56Z","updated_at":"2016-03-13T04:44:57Z","pushed_at":"2016-04-15T21:15:06Z","git_url":"git://github.com/dozingcat/material2.git","ssh_url":"git@github.com:dozingcat/material2.git","clone_url":"https://github.com/dozingcat/material2.git","svn_url":"https://github.com/dozingcat/material2","homepage":"","size":611,"stargazers_count":0,"watchers_count":0,"language":"TypeScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"angular:master","ref":"master","sha":"8d77163709e5ac52cdfa010ddc4d6cb16d1dd082","user":{"login":"angular","id":139426,"avatar_url":"https://avatars.githubusercontent.com/u/139426?v=3","gravatar_id":"","url":"https://api.github.com/users/angular","html_url":"https://github.com/angular","followers_url":"https://api.github.com/users/angular/followers","following_url":"https://api.github.com/users/angular/following{/other_user}","gists_url":"https://api.github.com/users/angular/gists{/gist_id}","starred_url":"https://api.github.com/users/angular/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/angular/subscriptions","organizations_url":"https://api.github.com/users/angular/orgs","repos_url":"https://api.github.com/users/angular/repos","events_url":"https://api.github.com/users/angular/events{/privacy}","received_events_url":"https://api.github.com/users/angular/received_events","type":"Organization","site_admin":false},"repo":{"id":49016322,"name":"material2","full_name":"angular/material2","owner":{"login":"angular","id":139426,"avatar_url":"https://avatars.githubusercontent.com/u/139426?v=3","gravatar_id":"","url":"https://api.github.com/users/angular","html_url":"https://github.com/angular","followers_url":"https://api.github.com/users/angular/followers","following_url":"https://api.github.com/users/angular/following{/other_user}","gists_url":"https://api.github.com/users/angular/gists{/gist_id}","starred_url":"https://api.github.com/users/angular/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/angular/subscriptions","organizations_url":"https://api.github.com/users/angular/orgs","repos_url":"https://api.github.com/users/angular/repos","events_url":"https://api.github.com/users/angular/events{/privacy}","received_events_url":"https://api.github.com/users/angular/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/angular/material2","description":"Material Design components for Angular 2","fork":false,"url":"https://api.github.com/repos/angular/material2","forks_url":"https://api.github.com/repos/angular/material2/forks","keys_url":"https://api.github.com/repos/angular/material2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/angular/material2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/angular/material2/teams","hooks_url":"https://api.github.com/repos/angular/material2/hooks","issue_events_url":"https://api.github.com/repos/angular/material2/issues/events{/number}","events_url":"https://api.github.com/repos/angular/material2/events","assignees_url":"https://api.github.com/repos/angular/material2/assignees{/user}","branches_url":"https://api.github.com/repos/angular/material2/branches{/branch}","tags_url":"https://api.github.com/repos/angular/material2/tags","blobs_url":"https://api.github.com/repos/angular/material2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/angular/material2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/angular/material2/git/refs{/sha}","trees_url":"https://api.github.com/repos/angular/material2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/angular/material2/statuses/{sha}","languages_url":"https://api.github.com/repos/angular/material2/languages","stargazers_url":"https://api.github.com/repos/angular/material2/stargazers","contributors_url":"https://api.github.com/repos/angular/material2/contributors","subscribers_url":"https://api.github.com/repos/angular/material2/subscribers","subscription_url":"https://api.github.com/repos/angular/material2/subscription","commits_url":"https://api.github.com/repos/angular/material2/commits{/sha}","git_commits_url":"https://api.github.com/repos/angular/material2/git/commits{/sha}","comments_url":"https://api.github.com/repos/angular/material2/comments{/number}","issue_comment_url":"https://api.github.com/repos/angular/material2/issues/comments{/number}","contents_url":"https://api.github.com/repos/angular/material2/contents/{+path}","compare_url":"https://api.github.com/repos/angular/material2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/angular/material2/merges","archive_url":"https://api.github.com/repos/angular/material2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/angular/material2/downloads","issues_url":"https://api.github.com/repos/angular/material2/issues{/number}","pulls_url":"https://api.github.com/repos/angular/material2/pulls{/number}","milestones_url":"https://api.github.com/repos/angular/material2/milestones{/number}","notifications_url":"https://api.github.com/repos/angular/material2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/angular/material2/labels{/name}","releases_url":"https://api.github.com/repos/angular/material2/releases{/id}","deployments_url":"https://api.github.com/repos/angular/material2/deployments","created_at":"2016-01-04T18:50:02Z","updated_at":"2016-04-16T01:00:27Z","pushed_at":"2016-04-15T22:20:46Z","git_url":"git://github.com/angular/material2.git","ssh_url":"git@github.com:angular/material2.git","clone_url":"https://github.com/angular/material2.git","svn_url":"https://github.com/angular/material2","homepage":"","size":796,"stargazers_count":1601,"watchers_count":1601,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":186,"mirror_url":null,"open_issues_count":56,"forks":186,"open_issues":56,"watchers":1601,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/angular/material2/pulls/281"},"html":{"href":"https://github.com/angular/material2/pull/281"},"issue":{"href":"https://api.github.com/repos/angular/material2/issues/281"},"comments":{"href":"https://api.github.com/repos/angular/material2/issues/281/comments"},"review_comments":{"href":"https://api.github.com/repos/angular/material2/pulls/281/comments"},"review_comment":{"href":"https://api.github.com/repos/angular/material2/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/angular/material2/pulls/281/commits"},"statuses":{"href":"https://api.github.com/repos/angular/material2/statuses/03bcbed1c9c1ed8c6eac5037e6fddeb5456be907"}}}}