{"action":"created","comment":{"url":"https://api.github.com/repos/ampproject/amphtml/pulls/comments/68099390","id":68099390,"diff_hunk":"@@ -89,318 +60,35 @@ class AmpAd extends AMP.BaseElement {\n   }\n \n   /** @override */\n-  isReadyToBuild() {\n-    // TODO(dvoytenko, #1014): Review and try a more immediate approach.\n-    // Wait until DOMReady.\n-    return false;\n-  }\n-\n-  /** @override */\n   buildCallback() {\n-    /** @private {?Element} */\n-    this.iframe_ = null;\n-\n-    /** @private {?Element} */\n-    this.placeholder_ = this.getPlaceholder();\n-\n-    /** @private {?Element} */\n-    this.fallback_ = this.getFallback();\n-\n-    /** @private {boolean} */\n-    this.isInFixedContainer_ = false;\n-\n-    /**\n-     * The layout box of the ad iframe (as opposed to the amp-ad tag).\n-     * In practice it often has padding to create a grey or similar box\n-     * around ads.\n-     * @private {!LayoutRect}\n-     */\n-    this.iframeLayoutBox_ = null;\n-\n-    /**\n-     * Call to stop listening to viewport changes.\n-     * @private {?function()}\n-     */\n-    this.unlistenViewportChanges_ = null;\n-\n-    /** @private {IntersectionObserver} */\n-    this.intersectionObserver_ = null;\n-\n-    /**\n-     * @private @const\n-     */\n-    this.viewer_ = viewerFor(this.getWin());\n-  }\n-\n-  /**\n-   * Prefetches and preconnects URLs related to the ad.\n-   * @override\n-   */\n-  preconnectCallback(onLayout) {\n-    // We always need the bootstrap.\n-    prefetchBootstrap(this.getWin());\n     const type = this.element.getAttribute('type');\n-    const prefetch = adPrefetch[type];\n-    const preconnect = adPreconnect[type];\n-    if (typeof prefetch == 'string') {\n-      this.preconnect.prefetch(prefetch, 'script');\n-    } else if (prefetch) {\n-      prefetch.forEach(p => {\n-        this.preconnect.prefetch(p, 'script');\n-      });\n-    }\n-    if (typeof preconnect == 'string') {\n-      this.preconnect.url(preconnect, onLayout);\n-    } else if (preconnect) {\n-      preconnect.forEach(p => {\n-        this.preconnect.url(p, onLayout);\n-      });\n-    }\n-    // If fully qualified src for ad script is specified we preconnect to it.\n-    const src = this.element.getAttribute('src');\n-    if (src) {\n-      // We only preconnect to the src because we cannot know whether the URL\n-      // will have caching headers set.\n-      this.preconnect.url(src);\n-    }\n-  }\n-\n-  /**\n-   * @override\n-   */\n-  onLayoutMeasure() {\n-    this.isInFixedContainer_ = this.isPositionFixed();\n-    // We remeasured this tag, lets also remeasure the iframe. Should be\n-    // free now and it might have changed.\n-    this.measureIframeLayoutBox_();\n-    // When the framework has the need to remeasure us, our position might\n-    // have changed. Send an intersection record if needed. This does nothing\n-    // if we aren't currently in view.\n-    if (this.intersectionObserver_) {\n-      this.intersectionObserver_.fire();\n-    }\n-  }\n-\n-  /**\n-   * Measure the layout box of the iframe if we rendered it already.\n-   * @private\n-   */\n-  measureIframeLayoutBox_() {\n-    if (this.iframe_) {\n-      this.iframeLayoutBox_ =\n-          this.getViewport().getLayoutRect(this.iframe_);\n-    }\n-  }\n-\n-  /**\n-   * @override\n-   */\n-  getIntersectionElementLayoutBox() {\n-    if (!this.iframe_) {\n-      return super.getIntersectionElementLayoutBox();\n-    }\n-    if (!this.iframeLayoutBox_) {\n-      this.measureIframeLayoutBox_();\n-    }\n-    return this.iframeLayoutBox_;\n-  }\n-\n-  /**\n-   * @return {boolean} whether this element or its ancestors have position\n-   * fixed (unless they are POSITION_FIXED_TAG_WHITELIST).\n-   * This should only be called when a layout on the page was just forced\n-   * anyway.\n-   */\n-  isPositionFixed() {\n-    let el = this.element;\n-    let hasFixedAncestor = false;\n-    do {\n-      if (POSITION_FIXED_TAG_WHITELIST[el.tagName]) {\n-        return false;\n-      }\n-      if (this.getWin()/*because only called from onLayoutMeasure */\n-          ./*OK*/getComputedStyle(el).position == 'fixed') {\n-        // Because certain blessed elements may contain a position fixed\n-        // container (which contain an ad), we continue to search the\n-        // ancestry tree.\n-        hasFixedAncestor = true;\n-      }\n-      el = el.parentNode;\n-    } while (el.tagName != 'BODY');\n-    return hasFixedAncestor;\n-  }\n-\n-  /** @override */\n-  layoutCallback() {\n-    if (!this.iframe_) {\n-      user.assert(!this.isInFixedContainer_,\n-          '<amp-ad> is not allowed to be placed in elements with ' +\n-          'position:fixed: %s', this.element);\n-      loadingAdsCount++;\n-      delayIdForTesting = timer.delay(() => {\n-        // Unfortunately we don't really have a good way to measure how long it\n-        // takes to load an ad, so we'll just pretend it takes 1 second for\n-        // now.\n-        loadingAdsCount--;\n-      }, 1000);\n-      return getAdCid(this).then(cid => {\n-        if (cid) {\n-          this.element.setAttribute('ampcid', cid);\n-        }\n-        this.iframe_ = getIframe(this.element.ownerDocument.defaultView,\n-            this.element);\n-        this.iframe_.setAttribute('scrolling', 'no');\n-        this.applyFillContent(this.iframe_);\n-        this.intersectionObserver_ =\n-            new IntersectionObserver(this, this.iframe_, /* opt_is3P */true);\n-        // Triggered by context.noContentAvailable() inside the ad iframe.\n-        listenForOnce(this.iframe_, 'no-content', () => {\n-          this.noContentHandler_();\n-        }, /* opt_is3P */ true);\n-        // Triggered by context.reportRenderedEntityIdentifier(…) inside the ad\n-        // iframe.\n-        listenForOnce(this.iframe_, 'entity-id', info => {\n-          this.element.creativeId = info.id;\n-        }, /* opt_is3P */ true);\n-        listenFor(this.iframe_, 'embed-size', data => {\n-          let newHeight, newWidth;\n-          if (data.width !== undefined) {\n-            newWidth = Math.max(this.element./*OK*/offsetWidth +\n-                data.width - this.iframe_./*OK*/offsetWidth, data.width);\n-            this.iframe_.width = data.width;\n-            this.element.setAttribute('width', newWidth);\n-          }\n-          if (data.height !== undefined) {\n-            newHeight = Math.max(this.element./*OK*/offsetHeight +\n-                data.height - this.iframe_./*OK*/offsetHeight, data.height);\n-            this.iframe_.height = data.height;\n-            this.element.setAttribute('height', newHeight);\n-          }\n-          if (newHeight !== undefined || newWidth !== undefined) {\n-            this.updateSize_(newHeight, newWidth);\n-          }\n-        }, /* opt_is3P */ true);\n-        this.iframe_.style.visibility = 'hidden';\n-        listenForOnce(this.iframe_, 'render-start', () => {\n-          this.iframe_.style.visibility = '';\n-          this.sendEmbedInfo_(this.isInViewport());\n-        }, /* opt_is3P */ true);\n-        this.viewer_.onVisibilityChanged(() => {\n-          this.sendEmbedInfo_(this.isInViewport());\n-        });\n-        this.element.appendChild(this.iframe_);\n-        return loadPromise(this.iframe_);\n-      });\n-    }\n-    return loadPromise(this.iframe_);\n-  }\n-\n-  /** @override  */\n-  unlayoutCallback() {\n-    if (!this.iframe_) {\n-      return true;\n-    }\n-\n-    removeElement(this.iframe_);\n-    if (this.placeholder_) {\n-      this.togglePlaceholder(true);\n-    }\n-    if (this.fallback_) {\n-      this.toggleFallback(false);\n-    }\n-\n-    this.iframe_ = null;\n-    // IntersectionObserver's listeners were cleaned up by\n-    // setInViewport(false) before #unlayoutCallback\n-    this.intersectionObserver_ = null;\n-    return true;\n-  }\n-\n-  /** @override  */\n-  viewportCallback(inViewport) {\n-    if (this.intersectionObserver_) {\n-      this.intersectionObserver_.onViewportCallback(inViewport);\n-    }\n-    this.sendEmbedInfo_(inViewport);\n-  }\n-\n-  /**\n-   * @param {boolean} inViewport\n-   * @private\n-   */\n-  sendEmbedInfo_(inViewport) {\n-    if (this.iframe_) {\n-      const targetOrigin =\n-          this.iframe_.src ? parseUrl(this.iframe_.src).origin : '*';\n-      postMessage(this.iframe_, 'embed-state', {\n-        inViewport,\n-        pageHidden: !this.viewer_.isVisible(),\n-      }, targetOrigin, /* opt_is3P */ true);\n-    }\n-  }\n-\n-  /** @override  */\n-  overflowCallback(overflown, requestedHeight, requestedWidth) {\n-    if (overflown) {\n-      const targetOrigin =\n-          this.iframe_.src ? parseUrl(this.iframe_.src).origin : '*';\n-      postMessage(\n-          this.iframe_,\n-          'embed-size-denied',\n-          {requestedHeight, requestedWidth},\n-          targetOrigin,\n-          /* opt_is3P */ true);\n-    }\n-  }\n-\n-  /**\n-   * Updates the element's dimensions to accommodate the iframe's\n-   *    requested dimensions.\n-   * @param {number|undefined} newWidth\n-   * @param {number|undefined} newHeight\n-   * @private\n-   */\n-  updateSize_(newHeight, newWidth) {\n-    this.attemptChangeSize(newHeight, newWidth, () => {\n-      const targetOrigin =\n-          this.iframe_.src ? parseUrl(this.iframe_.src).origin : '*';\n-      postMessage(\n-          this.iframe_,\n-          'embed-size-changed',\n-          {requestedHeight: newHeight, requestedWidth: newWidth},\n-          targetOrigin,\n-          /* opt_is3P */ true);\n-    });\n-  }\n-\n-  /**\n-   * Activates the fallback if the ad reports that the ad slot cannot\n-   * be filled.\n-   * @private\n-   */\n-  noContentHandler_() {\n-    // If a fallback does not exist attempt to collapse the ad.\n-    if (!this.fallback_) {\n-      this.attemptChangeHeight(0, () => {\n-        this.element.style.display = 'none';\n-      });\n-    }\n-    this.deferMutate(() => {\n-      if (this.fallback_) {\n-        // Hide placeholder when falling back.\n-        if (this.placeholder_) {\n-          this.togglePlaceholder(false);\n-        }\n-        this.toggleFallback(true);\n-      }\n-      // Remove the iframe only if it is not the master.\n-      if (this.iframe_.name.indexOf('_master') == -1) {\n-        removeElement(this.iframe_);\n-        this.iframe_ = null;\n-      }\n-    });\n+    if (!type) {\n+      // Unspecified or empty type.  Nothing to do here except bail out.\n+      return;\n+    }\n+    // TODO(tdrl): Check amp-ad registry to see if they have this already.\n+    if (!a4aRegistry[type] ||\n+        !a4aRegistry[type](this.getWin(), this.element)) {\n+      // Network either has not provided any A4A implementation or the\n+      // implementation exists, but has explicitly chosen not to handle this\n+      // tag as A4A.  Fall back to the 3p implementation.\n+      const newChild = this.element.ownerDocument.createElement(TAG_3P_IMPL);\n+      copyAttributes_(this.element, newChild);","path":"extensions/amp-ad/0.1/amp-ad.js","position":428,"original_position":428,"commit_id":"29197c8e6a6915708885fac655de967aac570ba5","original_commit_id":"5c63d0605aebb0064506f2b714f0ae2f5e360c94","user":{"login":"tdrl","id":17705064,"avatar_url":"https://avatars.githubusercontent.com/u/17705064?v=3","gravatar_id":"","url":"https://api.github.com/users/tdrl","html_url":"https://github.com/tdrl","followers_url":"https://api.github.com/users/tdrl/followers","following_url":"https://api.github.com/users/tdrl/following{/other_user}","gists_url":"https://api.github.com/users/tdrl/gists{/gist_id}","starred_url":"https://api.github.com/users/tdrl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tdrl/subscriptions","organizations_url":"https://api.github.com/users/tdrl/orgs","repos_url":"https://api.github.com/users/tdrl/repos","events_url":"https://api.github.com/users/tdrl/events{/privacy}","received_events_url":"https://api.github.com/users/tdrl/received_events","type":"User","site_admin":false},"body":"Done.","created_at":"2016-06-22T17:40:33Z","updated_at":"2016-06-22T17:40:33Z","html_url":"https://github.com/ampproject/amphtml/pull/3534#discussion_r68099390","pull_request_url":"https://api.github.com/repos/ampproject/amphtml/pulls/3534","_links":{"self":{"href":"https://api.github.com/repos/ampproject/amphtml/pulls/comments/68099390"},"html":{"href":"https://github.com/ampproject/amphtml/pull/3534#discussion_r68099390"},"pull_request":{"href":"https://api.github.com/repos/ampproject/amphtml/pulls/3534"}}},"pull_request":{"url":"https://api.github.com/repos/ampproject/amphtml/pulls/3534","id":73425600,"html_url":"https://github.com/ampproject/amphtml/pull/3534","diff_url":"https://github.com/ampproject/amphtml/pull/3534.diff","patch_url":"https://github.com/ampproject/amphtml/pull/3534.patch","issue_url":"https://api.github.com/repos/ampproject/amphtml/issues/3534","number":3534,"state":"open","locked":false,"title":"Changes to implement A4A (AMP ads for AMP pages)","user":{"login":"bobcassels","id":3493758,"avatar_url":"https://avatars.githubusercontent.com/u/3493758?v=3","gravatar_id":"","url":"https://api.github.com/users/bobcassels","html_url":"https://github.com/bobcassels","followers_url":"https://api.github.com/users/bobcassels/followers","following_url":"https://api.github.com/users/bobcassels/following{/other_user}","gists_url":"https://api.github.com/users/bobcassels/gists{/gist_id}","starred_url":"https://api.github.com/users/bobcassels/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bobcassels/subscriptions","organizations_url":"https://api.github.com/users/bobcassels/orgs","repos_url":"https://api.github.com/users/bobcassels/repos","events_url":"https://api.github.com/users/bobcassels/events{/privacy}","received_events_url":"https://api.github.com/users/bobcassels/received_events","type":"User","site_admin":false},"body":"This implements infrastructure to support AMP Ads for AMP Pages (A4A) as outlined in #3133.  This is not ready for general use yet but rather initial work on implementing an A4A experiment.  In particular, there is currently no public signing service.  An example implementation for a specific ad network is at https://github.com/google/amphtml/tree/a4a-adsense. However, ad networks may wish to wait to implement their own A4A integration until a public AMP creative signing service is available.\r\n\r\nThis is a no-retagging change: existing publisher pages should continue to work as written, with unchanged behavior.\r\n\r\nConsiderations:\r\n\r\n- AmpA4A is an abstract class providing functionality shared across ad networks seeking AMP ads for AMP pages capability.  Networks will need to extend and implement abstract functions.\r\n- AmpAd (tag `<amp-ad>`) serves as a loader which will add either the 3p or a network-specific A4A extension element as a child.  The 3p implementation (named AmpAd3PImpl) implements the same functionality as the original AMPHTML `<amp-ad>` tag, and is included with the amp-ad extension bundle to ensure no change in latency.\r\n- The decision to use the A4A implementation is made via lookup of predicate functions based on the ad type attribute.  Networks can choose not to use A4A, in which case 3p will be used.  If an ad network does not register a predicate, the implementation defaults to the existing 3p ad implementation.  (That is, existing ad networks will continue their current behavior, unless the network implementers take positive action to change it.)\r\n- The response to the CORS XHR ad request will be privately cacheable allowing for it to be rendered within a cross-domain iframe by creating an iframe whose source equals the ad URL.  \r\n- AMPA4A will render the creative to the page in one of the following methods:\r\n - If the creative does not include signature or signature is not verified:  creative is rendered within cross domain iframe (should hit browser cache) on layoutCallback using the same constraints as a 3p ad.\r\n - If the creative is verified as AMP and the browser supports Shadow DOM (e.g., Chrome): creative is rendered as soon as it is verified and is inserted within shadow root in the publisher page.  Shadow DOM ensures CSS isolation.\r\n - If the creative is verified as AMP but the browser does not support Shadow DOM (e.g., Safari): creative is rendered as soon as it is verified via cross domain iframe. \r\n\r\nTODO:\r\n- Add more unit test coverage\r\n- AdSense and Doubleclick-specific implementations to be provided in later PRs\r\n","created_at":"2016-06-10T19:43:42Z","updated_at":"2016-06-22T17:40:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"fdcb3b5ca8bde168a44f2c88e51d39bd3cda7ba8","assignee":{"login":"cramforce","id":89679,"avatar_url":"https://avatars.githubusercontent.com/u/89679?v=3","gravatar_id":"","url":"https://api.github.com/users/cramforce","html_url":"https://github.com/cramforce","followers_url":"https://api.github.com/users/cramforce/followers","following_url":"https://api.github.com/users/cramforce/following{/other_user}","gists_url":"https://api.github.com/users/cramforce/gists{/gist_id}","starred_url":"https://api.github.com/users/cramforce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cramforce/subscriptions","organizations_url":"https://api.github.com/users/cramforce/orgs","repos_url":"https://api.github.com/users/cramforce/repos","events_url":"https://api.github.com/users/cramforce/events{/privacy}","received_events_url":"https://api.github.com/users/cramforce/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/ampproject/amphtml/pulls/3534/commits","review_comments_url":"https://api.github.com/repos/ampproject/amphtml/pulls/3534/comments","review_comment_url":"https://api.github.com/repos/ampproject/amphtml/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ampproject/amphtml/issues/3534/comments","statuses_url":"https://api.github.com/repos/ampproject/amphtml/statuses/29197c8e6a6915708885fac655de967aac570ba5","head":{"label":"google:a4a-core","ref":"a4a-core","sha":"29197c8e6a6915708885fac655de967aac570ba5","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":51965089,"name":"amphtml","full_name":"google/amphtml","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/amphtml","description":"AMP HTML source code, samples, and documentation.  See below for more info.","fork":true,"url":"https://api.github.com/repos/google/amphtml","forks_url":"https://api.github.com/repos/google/amphtml/forks","keys_url":"https://api.github.com/repos/google/amphtml/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/amphtml/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/amphtml/teams","hooks_url":"https://api.github.com/repos/google/amphtml/hooks","issue_events_url":"https://api.github.com/repos/google/amphtml/issues/events{/number}","events_url":"https://api.github.com/repos/google/amphtml/events","assignees_url":"https://api.github.com/repos/google/amphtml/assignees{/user}","branches_url":"https://api.github.com/repos/google/amphtml/branches{/branch}","tags_url":"https://api.github.com/repos/google/amphtml/tags","blobs_url":"https://api.github.com/repos/google/amphtml/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/amphtml/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/amphtml/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/amphtml/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/amphtml/statuses/{sha}","languages_url":"https://api.github.com/repos/google/amphtml/languages","stargazers_url":"https://api.github.com/repos/google/amphtml/stargazers","contributors_url":"https://api.github.com/repos/google/amphtml/contributors","subscribers_url":"https://api.github.com/repos/google/amphtml/subscribers","subscription_url":"https://api.github.com/repos/google/amphtml/subscription","commits_url":"https://api.github.com/repos/google/amphtml/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/amphtml/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/amphtml/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/amphtml/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/amphtml/contents/{+path}","compare_url":"https://api.github.com/repos/google/amphtml/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/amphtml/merges","archive_url":"https://api.github.com/repos/google/amphtml/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/amphtml/downloads","issues_url":"https://api.github.com/repos/google/amphtml/issues{/number}","pulls_url":"https://api.github.com/repos/google/amphtml/pulls{/number}","milestones_url":"https://api.github.com/repos/google/amphtml/milestones{/number}","notifications_url":"https://api.github.com/repos/google/amphtml/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/amphtml/labels{/name}","releases_url":"https://api.github.com/repos/google/amphtml/releases{/id}","deployments_url":"https://api.github.com/repos/google/amphtml/deployments","created_at":"2016-02-18T00:04:16Z","updated_at":"2016-06-19T16:03:24Z","pushed_at":"2016-06-22T16:05:57Z","git_url":"git://github.com/google/amphtml.git","ssh_url":"git@github.com:google/amphtml.git","clone_url":"https://github.com/google/amphtml.git","svn_url":"https://github.com/google/amphtml","homepage":"https://ampproject.org","size":95267,"stargazers_count":14,"watchers_count":14,"language":"JavaScript","has_issues":false,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":8,"mirror_url":null,"open_issues_count":2,"forks":8,"open_issues":2,"watchers":14,"default_branch":"master"}},"base":{"label":"ampproject:master","ref":"master","sha":"1fb9e24d4d0f6488d563994cab29b747a6e93f25","user":{"login":"ampproject","id":14114390,"avatar_url":"https://avatars.githubusercontent.com/u/14114390?v=3","gravatar_id":"","url":"https://api.github.com/users/ampproject","html_url":"https://github.com/ampproject","followers_url":"https://api.github.com/users/ampproject/followers","following_url":"https://api.github.com/users/ampproject/following{/other_user}","gists_url":"https://api.github.com/users/ampproject/gists{/gist_id}","starred_url":"https://api.github.com/users/ampproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ampproject/subscriptions","organizations_url":"https://api.github.com/users/ampproject/orgs","repos_url":"https://api.github.com/users/ampproject/repos","events_url":"https://api.github.com/users/ampproject/events{/privacy}","received_events_url":"https://api.github.com/users/ampproject/received_events","type":"Organization","site_admin":false},"repo":{"id":41766002,"name":"amphtml","full_name":"ampproject/amphtml","owner":{"login":"ampproject","id":14114390,"avatar_url":"https://avatars.githubusercontent.com/u/14114390?v=3","gravatar_id":"","url":"https://api.github.com/users/ampproject","html_url":"https://github.com/ampproject","followers_url":"https://api.github.com/users/ampproject/followers","following_url":"https://api.github.com/users/ampproject/following{/other_user}","gists_url":"https://api.github.com/users/ampproject/gists{/gist_id}","starred_url":"https://api.github.com/users/ampproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ampproject/subscriptions","organizations_url":"https://api.github.com/users/ampproject/orgs","repos_url":"https://api.github.com/users/ampproject/repos","events_url":"https://api.github.com/users/ampproject/events{/privacy}","received_events_url":"https://api.github.com/users/ampproject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ampproject/amphtml","description":"AMP HTML source code, samples, and documentation.  See below for more info.","fork":false,"url":"https://api.github.com/repos/ampproject/amphtml","forks_url":"https://api.github.com/repos/ampproject/amphtml/forks","keys_url":"https://api.github.com/repos/ampproject/amphtml/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ampproject/amphtml/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ampproject/amphtml/teams","hooks_url":"https://api.github.com/repos/ampproject/amphtml/hooks","issue_events_url":"https://api.github.com/repos/ampproject/amphtml/issues/events{/number}","events_url":"https://api.github.com/repos/ampproject/amphtml/events","assignees_url":"https://api.github.com/repos/ampproject/amphtml/assignees{/user}","branches_url":"https://api.github.com/repos/ampproject/amphtml/branches{/branch}","tags_url":"https://api.github.com/repos/ampproject/amphtml/tags","blobs_url":"https://api.github.com/repos/ampproject/amphtml/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ampproject/amphtml/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ampproject/amphtml/git/refs{/sha}","trees_url":"https://api.github.com/repos/ampproject/amphtml/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ampproject/amphtml/statuses/{sha}","languages_url":"https://api.github.com/repos/ampproject/amphtml/languages","stargazers_url":"https://api.github.com/repos/ampproject/amphtml/stargazers","contributors_url":"https://api.github.com/repos/ampproject/amphtml/contributors","subscribers_url":"https://api.github.com/repos/ampproject/amphtml/subscribers","subscription_url":"https://api.github.com/repos/ampproject/amphtml/subscription","commits_url":"https://api.github.com/repos/ampproject/amphtml/commits{/sha}","git_commits_url":"https://api.github.com/repos/ampproject/amphtml/git/commits{/sha}","comments_url":"https://api.github.com/repos/ampproject/amphtml/comments{/number}","issue_comment_url":"https://api.github.com/repos/ampproject/amphtml/issues/comments{/number}","contents_url":"https://api.github.com/repos/ampproject/amphtml/contents/{+path}","compare_url":"https://api.github.com/repos/ampproject/amphtml/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ampproject/amphtml/merges","archive_url":"https://api.github.com/repos/ampproject/amphtml/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ampproject/amphtml/downloads","issues_url":"https://api.github.com/repos/ampproject/amphtml/issues{/number}","pulls_url":"https://api.github.com/repos/ampproject/amphtml/pulls{/number}","milestones_url":"https://api.github.com/repos/ampproject/amphtml/milestones{/number}","notifications_url":"https://api.github.com/repos/ampproject/amphtml/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ampproject/amphtml/labels{/name}","releases_url":"https://api.github.com/repos/ampproject/amphtml/releases{/id}","deployments_url":"https://api.github.com/repos/ampproject/amphtml/deployments","created_at":"2015-09-01T22:10:53Z","updated_at":"2016-06-22T16:17:29Z","pushed_at":"2016-06-22T17:04:11Z","git_url":"git://github.com/ampproject/amphtml.git","ssh_url":"git@github.com:ampproject/amphtml.git","clone_url":"https://github.com/ampproject/amphtml.git","svn_url":"https://github.com/ampproject/amphtml","homepage":"https://ampproject.org","size":113884,"stargazers_count":7733,"watchers_count":7733,"language":"JavaScript","has_issues":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":1066,"mirror_url":null,"open_issues_count":523,"forks":1066,"open_issues":523,"watchers":7733,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ampproject/amphtml/pulls/3534"},"html":{"href":"https://github.com/ampproject/amphtml/pull/3534"},"issue":{"href":"https://api.github.com/repos/ampproject/amphtml/issues/3534"},"comments":{"href":"https://api.github.com/repos/ampproject/amphtml/issues/3534/comments"},"review_comments":{"href":"https://api.github.com/repos/ampproject/amphtml/pulls/3534/comments"},"review_comment":{"href":"https://api.github.com/repos/ampproject/amphtml/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ampproject/amphtml/pulls/3534/commits"},"statuses":{"href":"https://api.github.com/repos/ampproject/amphtml/statuses/29197c8e6a6915708885fac655de967aac570ba5"}}}}
{"actor":{"display_login":"tdrl"}}