From aa94dee2cc754a84a555a731e2e40832ab7be1be Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 11:33:27 -0700 Subject: [PATCH 01/17] report: make urls clickable --- .../report/html/renderer/details-renderer.js | 15 ++++++++++++++- lighthouse-core/report/html/report-styles.css | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index d7cb6abe0e34..0e2bdf19dcf7 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -113,7 +113,7 @@ class DetailsRenderer { } const element = this._dom.createElement('div', 'lh-text__url'); - element.appendChild(this._renderText(displayedPath)); + element.appendChild(this._renderAnchor(displayedPath, url)); if (displayedHost) { const hostElem = this._renderText(displayedHost); @@ -160,6 +160,19 @@ class DetailsRenderer { return element; } + /** + * @param {string} text + * @param {string} href + * @return {Element} + */ + _renderAnchor(text, href) { + const element = this._dom.createElement('a', 'lh-anchor'); + element.textContent = text; + element.href = href; + element.target = '_blank'; + return element; + } + /** * @param {string} text * @return {Element} diff --git a/lighthouse-core/report/html/report-styles.css b/lighthouse-core/report/html/report-styles.css index d1752a9dc00e..1abf2c5a4df6 100644 --- a/lighthouse-core/report/html/report-styles.css +++ b/lighthouse-core/report/html/report-styles.css @@ -1372,6 +1372,11 @@ object-fit: contain; } +a.lh-anchor { + color: inherit; + text-decoration: none; +} + /* Chevron https://codepen.io/paulirish/pen/LmzEmK */ From 5ebc4196a2918fcca5912f0f2e978788c3a640a5 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 11:43:25 -0700 Subject: [PATCH 02/17] request chain --- lighthouse-core/report/html/renderer/crc-details-renderer.js | 1 + lighthouse-core/report/html/templates.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lighthouse-core/report/html/renderer/crc-details-renderer.js b/lighthouse-core/report/html/renderer/crc-details-renderer.js index 150064d477f2..71ab43bb01f5 100644 --- a/lighthouse-core/report/html/renderer/crc-details-renderer.js +++ b/lighthouse-core/report/html/renderer/crc-details-renderer.js @@ -123,6 +123,7 @@ class CriticalRequestChainRenderer { const {file, hostname} = Util.parseURL(segment.node.request.url); const treevalEl = dom.find('.crc-node__tree-value', chainsEl); dom.find('.crc-node__tree-file', treevalEl).textContent = `${file}`; + dom.find('.crc-node__tree-file', treevalEl).href = segment.node.request.url; dom.find('.crc-node__tree-hostname', treevalEl).textContent = hostname ? `(${hostname})` : ''; if (!segment.hasChildren) { diff --git a/lighthouse-core/report/html/templates.html b/lighthouse-core/report/html/templates.html index 11d1d78e05fd..1057b343f604 100644 --- a/lighthouse-core/report/html/templates.html +++ b/lighthouse-core/report/html/templates.html @@ -769,7 +769,7 @@ - + () From 64a7cf0c2d1a80e057e97a0ce9f5ffabe9f8040d Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 13:29:39 -0700 Subject: [PATCH 03/17] fix tests --- .../test/report/html/renderer/details-renderer-test.js | 4 ++-- .../test/report/html/renderer/report-ui-features-test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lighthouse-core/test/report/html/renderer/details-renderer-test.js b/lighthouse-core/test/report/html/renderer/details-renderer-test.js index fec4f3233664..7639bff4db18 100644 --- a/lighthouse-core/test/report/html/renderer/details-renderer-test.js +++ b/lighthouse-core/test/report/html/renderer/details-renderer-test.js @@ -385,7 +385,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-text')); + assert.ok(urlEl.firstChild.classList.contains('lh-anchor')); assert.equal(urlEl.textContent, displayUrlText); }); @@ -410,7 +410,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-text')); + assert.ok(urlEl.firstChild.classList.contains('lh-anchor')); assert.equal(urlEl.textContent, displayUrlText); }); diff --git a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js index d706fc4f82fd..7448cf3f7d20 100644 --- a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js +++ b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js @@ -185,7 +185,7 @@ describe('ReportUIFeatures', () => { function getUrlsInTable() { return dom - .findAll('#uses-webp-images .lh-details .lh-text__url .lh-text:first-child', container) + .findAll('#uses-webp-images .lh-details .lh-text__url .lh-anchor:first-child', container) .map(el => el.textContent); } From 4bd8a9e60ca2c5f89b0e44673ca5f68be3b0f1d8 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 16:06:52 -0700 Subject: [PATCH 04/17] noopener --- lighthouse-core/report/html/renderer/details-renderer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index 0e2bdf19dcf7..cebd57b6c1ce 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -170,6 +170,7 @@ class DetailsRenderer { element.textContent = text; element.href = href; element.target = '_blank'; + element.rel = 'noopener'; return element; } From 12f47289810dd0e858803e505727596185e8e0ec Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 16:13:22 -0700 Subject: [PATCH 05/17] renderLink --- .../report/html/renderer/details-renderer.js | 30 +++++-------------- .../html/renderer/report-ui-features-test.js | 3 +- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index cebd57b6c1ce..63272c0bb14c 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -113,7 +113,7 @@ class DetailsRenderer { } const element = this._dom.createElement('div', 'lh-text__url'); - element.appendChild(this._renderAnchor(displayedPath, url)); + element.appendChild(this._renderLink(displayedPath, new URL(url))); if (displayedHost) { const hostElem = this._renderText(displayedHost); @@ -130,21 +130,21 @@ class DetailsRenderer { } /** - * @param {LH.Audit.Details.LinkValue} details + * @param {string} text + * @param {URL} url * @return {Element} */ - _renderLink(details) { + _renderLink(text, url) { const allowedProtocols = ['https:', 'http:']; - const url = new URL(details.url); if (!allowedProtocols.includes(url.protocol)) { // Fall back to just the link text if protocol not allowed. - return this._renderText(details.text); + return this._renderText(text); } - const a = this._dom.createElement('a'); + const a = this._dom.createElement('a', 'lh-anchor'); a.rel = 'noopener'; a.target = '_blank'; - a.textContent = details.text; + a.textContent = text; a.href = url.href; return a; @@ -160,20 +160,6 @@ class DetailsRenderer { return element; } - /** - * @param {string} text - * @param {string} href - * @return {Element} - */ - _renderAnchor(text, href) { - const element = this._dom.createElement('a', 'lh-anchor'); - element.textContent = text; - element.href = href; - element.target = '_blank'; - element.rel = 'noopener'; - return element; - } - /** * @param {string} text * @return {Element} @@ -219,7 +205,7 @@ class DetailsRenderer { return this._renderCode(value.value); } case 'link': { - return this._renderLink(value); + return this._renderLink(value.text, new URL(value.url)); } case 'node': { return this.renderNode(value); diff --git a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js index 7448cf3f7d20..b5e2b7ffee11 100644 --- a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js +++ b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js @@ -185,7 +185,8 @@ describe('ReportUIFeatures', () => { function getUrlsInTable() { return dom - .findAll('#uses-webp-images .lh-details .lh-text__url .lh-anchor:first-child', container) + .findAll('#uses-webp-images .lh-details .lh-text__url .lh-anchor:first-child', + container) .map(el => el.textContent); } From d6eae56832b49072c9ee8442c6182ece429eea7a Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 16:15:15 -0700 Subject: [PATCH 06/17] rename --- lighthouse-core/report/html/renderer/details-renderer.js | 2 +- lighthouse-core/report/html/report-styles.css | 2 +- lighthouse-core/report/html/templates.html | 3 +-- .../test/report/html/renderer/details-renderer-test.js | 4 ++-- .../test/report/html/renderer/report-ui-features-test.js | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index 63272c0bb14c..2e4acfa61a5f 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -141,7 +141,7 @@ class DetailsRenderer { return this._renderText(text); } - const a = this._dom.createElement('a', 'lh-anchor'); + const a = this._dom.createElement('a', 'lh-link'); a.rel = 'noopener'; a.target = '_blank'; a.textContent = text; diff --git a/lighthouse-core/report/html/report-styles.css b/lighthouse-core/report/html/report-styles.css index 1abf2c5a4df6..a74825f2447e 100644 --- a/lighthouse-core/report/html/report-styles.css +++ b/lighthouse-core/report/html/report-styles.css @@ -1372,7 +1372,7 @@ object-fit: contain; } -a.lh-anchor { +a.lh-link { color: inherit; text-decoration: none; } diff --git a/lighthouse-core/report/html/templates.html b/lighthouse-core/report/html/templates.html index 1057b343f604..35dbb72175d7 100644 --- a/lighthouse-core/report/html/templates.html +++ b/lighthouse-core/report/html/templates.html @@ -769,9 +769,8 @@ - + () - diff --git a/lighthouse-core/test/report/html/renderer/details-renderer-test.js b/lighthouse-core/test/report/html/renderer/details-renderer-test.js index 7639bff4db18..520987eb2429 100644 --- a/lighthouse-core/test/report/html/renderer/details-renderer-test.js +++ b/lighthouse-core/test/report/html/renderer/details-renderer-test.js @@ -385,7 +385,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-anchor')); + assert.ok(urlEl.firstChild.classList.contains('lh-link')); assert.equal(urlEl.textContent, displayUrlText); }); @@ -410,7 +410,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-anchor')); + assert.ok(urlEl.firstChild.classList.contains('lh-link')); assert.equal(urlEl.textContent, displayUrlText); }); diff --git a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js index b5e2b7ffee11..cf5148b6e2f6 100644 --- a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js +++ b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js @@ -185,8 +185,7 @@ describe('ReportUIFeatures', () => { function getUrlsInTable() { return dom - .findAll('#uses-webp-images .lh-details .lh-text__url .lh-anchor:first-child', - container) + .findAll('#uses-webp-images .lh-details .lh-text__url .lh-link:first-child', container) .map(el => el.textContent); } From fbc179f0cfafa84614fc57fefd9edea5cfc3d6a2 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 17 Jun 2019 18:08:13 -0700 Subject: [PATCH 07/17] fix types --- lighthouse-core/report/html/renderer/crc-details-renderer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/report/html/renderer/crc-details-renderer.js b/lighthouse-core/report/html/renderer/crc-details-renderer.js index 71ab43bb01f5..adfe9244e7d2 100644 --- a/lighthouse-core/report/html/renderer/crc-details-renderer.js +++ b/lighthouse-core/report/html/renderer/crc-details-renderer.js @@ -122,8 +122,9 @@ class CriticalRequestChainRenderer { // Fill in url, host, and request size information. const {file, hostname} = Util.parseURL(segment.node.request.url); const treevalEl = dom.find('.crc-node__tree-value', chainsEl); - dom.find('.crc-node__tree-file', treevalEl).textContent = `${file}`; - dom.find('.crc-node__tree-file', treevalEl).href = segment.node.request.url; + const fileEl = /** @type {HTMLAnchorElement} */ (dom.find('.crc-node__tree-file', treevalEl)); + fileEl.textContent = `${file}`; + fileEl.href = segment.node.request.url; dom.find('.crc-node__tree-hostname', treevalEl).textContent = hostname ? `(${hostname})` : ''; if (!segment.hasChildren) { From 6c43e7e2d5a0e1e22cab0c51a61dbb407fd09a97 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Tue, 18 Jun 2019 13:37:24 -0700 Subject: [PATCH 08/17] remove lh-link --- lighthouse-core/report/html/renderer/details-renderer.js | 2 +- lighthouse-core/report/html/report-styles.css | 3 ++- lighthouse-core/report/html/templates.html | 2 +- .../test/report/html/renderer/details-renderer-test.js | 4 ++-- .../test/report/html/renderer/report-ui-features-test.js | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index 2e4acfa61a5f..ce8f899a0a55 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -141,7 +141,7 @@ class DetailsRenderer { return this._renderText(text); } - const a = this._dom.createElement('a', 'lh-link'); + const a = this._dom.createElement('a'); a.rel = 'noopener'; a.target = '_blank'; a.textContent = text; diff --git a/lighthouse-core/report/html/report-styles.css b/lighthouse-core/report/html/report-styles.css index a74825f2447e..1453a54c34d9 100644 --- a/lighthouse-core/report/html/report-styles.css +++ b/lighthouse-core/report/html/report-styles.css @@ -1372,7 +1372,8 @@ object-fit: contain; } -a.lh-link { +.lh-text__url > a, +.lh-crc .crc-node__tree-value > a { color: inherit; text-decoration: none; } diff --git a/lighthouse-core/report/html/templates.html b/lighthouse-core/report/html/templates.html index 35dbb72175d7..4e523b129af1 100644 --- a/lighthouse-core/report/html/templates.html +++ b/lighthouse-core/report/html/templates.html @@ -769,7 +769,7 @@ - + () diff --git a/lighthouse-core/test/report/html/renderer/details-renderer-test.js b/lighthouse-core/test/report/html/renderer/details-renderer-test.js index 520987eb2429..fec4f3233664 100644 --- a/lighthouse-core/test/report/html/renderer/details-renderer-test.js +++ b/lighthouse-core/test/report/html/renderer/details-renderer-test.js @@ -385,7 +385,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-link')); + assert.ok(urlEl.firstChild.classList.contains('lh-text')); assert.equal(urlEl.textContent, displayUrlText); }); @@ -410,7 +410,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-link')); + assert.ok(urlEl.firstChild.classList.contains('lh-text')); assert.equal(urlEl.textContent, displayUrlText); }); diff --git a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js index cf5148b6e2f6..d706fc4f82fd 100644 --- a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js +++ b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js @@ -185,7 +185,7 @@ describe('ReportUIFeatures', () => { function getUrlsInTable() { return dom - .findAll('#uses-webp-images .lh-details .lh-text__url .lh-link:first-child', container) + .findAll('#uses-webp-images .lh-details .lh-text__url .lh-text:first-child', container) .map(el => el.textContent); } From 858b63ad6fcfa744217977f96235213a9c2beda5 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Tue, 18 Jun 2019 13:38:07 -0700 Subject: [PATCH 09/17] noopener --- lighthouse-core/report/html/templates.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/report/html/templates.html b/lighthouse-core/report/html/templates.html index 4e523b129af1..e2492a9fe047 100644 --- a/lighthouse-core/report/html/templates.html +++ b/lighthouse-core/report/html/templates.html @@ -769,7 +769,7 @@ - + () From ebeda1b3b49cc94b55ac0196a942387529a8e22d Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Tue, 18 Jun 2019 13:41:51 -0700 Subject: [PATCH 10/17] renderlink args --- .../report/html/renderer/details-renderer.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index ce8f899a0a55..21e872c0b143 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -113,7 +113,7 @@ class DetailsRenderer { } const element = this._dom.createElement('div', 'lh-text__url'); - element.appendChild(this._renderLink(displayedPath, new URL(url))); + element.appendChild(this._renderLink({text: displayedPath, url})); if (displayedHost) { const hostElem = this._renderText(displayedHost); @@ -130,21 +130,21 @@ class DetailsRenderer { } /** - * @param {string} text - * @param {URL} url + * @param {Omit} details * @return {Element} */ - _renderLink(text, url) { + _renderLink(details) { const allowedProtocols = ['https:', 'http:']; + const url = new URL(details.url); if (!allowedProtocols.includes(url.protocol)) { // Fall back to just the link text if protocol not allowed. - return this._renderText(text); + return this._renderText(details.text); } const a = this._dom.createElement('a'); a.rel = 'noopener'; a.target = '_blank'; - a.textContent = text; + a.textContent = details.text; a.href = url.href; return a; @@ -205,7 +205,7 @@ class DetailsRenderer { return this._renderCode(value.value); } case 'link': { - return this._renderLink(value.text, new URL(value.url)); + return this._renderLink(value); } case 'node': { return this.renderNode(value); From a032633a3d01039e017f18f2145f5ffbf65e9daf Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Tue, 18 Jun 2019 14:15:47 -0700 Subject: [PATCH 11/17] Update lighthouse-core/report/html/renderer/details-renderer.js Co-Authored-By: Brendan Kenny --- lighthouse-core/report/html/renderer/details-renderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index 21e872c0b143..4128e5180ebd 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -130,7 +130,7 @@ class DetailsRenderer { } /** - * @param {Omit} details + * @param {{text: string, url: string}} details * @return {Element} */ _renderLink(details) { From a000cb45943bc5fd6515ec5a453116ce1df430bc Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Tue, 18 Jun 2019 14:19:32 -0700 Subject: [PATCH 12/17] fix test --- .../test/report/html/renderer/details-renderer-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/test/report/html/renderer/details-renderer-test.js b/lighthouse-core/test/report/html/renderer/details-renderer-test.js index fec4f3233664..ec0986af00cb 100644 --- a/lighthouse-core/test/report/html/renderer/details-renderer-test.js +++ b/lighthouse-core/test/report/html/renderer/details-renderer-test.js @@ -385,7 +385,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-text')); + assert.equal(urlEl.firstChild.nodeName, 'A'); assert.equal(urlEl.textContent, displayUrlText); }); @@ -410,7 +410,7 @@ describe('DetailsRenderer', () => { assert.equal(urlEl.localName, 'div'); assert.equal(urlEl.title, urlText); assert.equal(urlEl.dataset.url, urlText); - assert.ok(urlEl.firstChild.classList.contains('lh-text')); + assert.equal(urlEl.firstChild.nodeName, 'A'); assert.equal(urlEl.textContent, displayUrlText); }); From 425d7ec911f274a9b27de34aab54ca90961b71a8 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Tue, 18 Jun 2019 14:20:29 -0700 Subject: [PATCH 13/17] fix test --- .../test/report/html/renderer/report-ui-features-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js index d706fc4f82fd..2beb09fec0b0 100644 --- a/lighthouse-core/test/report/html/renderer/report-ui-features-test.js +++ b/lighthouse-core/test/report/html/renderer/report-ui-features-test.js @@ -185,7 +185,7 @@ describe('ReportUIFeatures', () => { function getUrlsInTable() { return dom - .findAll('#uses-webp-images .lh-details .lh-text__url .lh-text:first-child', container) + .findAll('#uses-webp-images .lh-details .lh-text__url a:first-child', container) .map(el => el.textContent); } From 7d93bde61a62808f6acb08479795c86013e8a90e Mon Sep 17 00:00:00 2001 From: Paul Irish Date: Thu, 20 Jun 2019 14:56:21 -0700 Subject: [PATCH 14/17] report: allow CRC to use renderTextUrl (#9237) --- .../html/renderer/crc-details-renderer.js | 23 ++++++++------- .../report/html/renderer/details-renderer.js | 8 ++--- lighthouse-core/report/html/report-styles.css | 29 +++++++++---------- lighthouse-core/report/html/templates.html | 9 +++--- .../renderer/crc-details-renderer-test.js | 6 ++-- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/lighthouse-core/report/html/renderer/crc-details-renderer.js b/lighthouse-core/report/html/renderer/crc-details-renderer.js index adfe9244e7d2..fe020cf3758f 100644 --- a/lighthouse-core/report/html/renderer/crc-details-renderer.js +++ b/lighthouse-core/report/html/renderer/crc-details-renderer.js @@ -84,9 +84,10 @@ class CriticalRequestChainRenderer { * @param {DOM} dom * @param {DocumentFragment} tmpl * @param {CRCSegment} segment + * @param {DetailsRenderer} detailsRenderer * @return {Node} */ - static createChainNode(dom, tmpl, segment) { + static createChainNode(dom, tmpl, segment, detailsRenderer) { const chainsEl = dom.cloneTemplate('#tmpl-lh-crc__chains', tmpl); // Hovering over request shows full URL. @@ -120,12 +121,10 @@ class CriticalRequestChainRenderer { } // Fill in url, host, and request size information. - const {file, hostname} = Util.parseURL(segment.node.request.url); + const url = segment.node.request.url; + const linkEl = detailsRenderer.renderTextURL(url); const treevalEl = dom.find('.crc-node__tree-value', chainsEl); - const fileEl = /** @type {HTMLAnchorElement} */ (dom.find('.crc-node__tree-file', treevalEl)); - fileEl.textContent = `${file}`; - fileEl.href = segment.node.request.url; - dom.find('.crc-node__tree-hostname', treevalEl).textContent = hostname ? `(${hostname})` : ''; + treevalEl.appendChild(linkEl); if (!segment.hasChildren) { const {startTime, endTime, transferSize} = segment.node.request; @@ -148,14 +147,15 @@ class CriticalRequestChainRenderer { * @param {CRCSegment} segment * @param {Element} elem Parent element. * @param {LH.Audit.Details.CriticalRequestChain} details + * @param {DetailsRenderer} detRenderer */ - static buildTree(dom, tmpl, segment, elem, details) { - elem.appendChild(CriticalRequestChainRenderer.createChainNode(dom, tmpl, segment)); + static buildTree(dom, tmpl, segment, elem, details, detRenderer) { + elem.appendChild(CriticalRequestChainRenderer.createChainNode(dom, tmpl, segment, detRenderer)); if (segment.node.children) { for (const key of Object.keys(segment.node.children)) { const childSegment = CriticalRequestChainRenderer.createSegment(segment.node.children, key, segment.startTime, segment.transferSize, segment.treeMarkers, segment.isLastChild); - CriticalRequestChainRenderer.buildTree(dom, tmpl, childSegment, elem, details); + CriticalRequestChainRenderer.buildTree(dom, tmpl, childSegment, elem, details, detRenderer); } } } @@ -164,9 +164,10 @@ class CriticalRequestChainRenderer { * @param {DOM} dom * @param {ParentNode} templateContext * @param {LH.Audit.Details.CriticalRequestChain} details + * @param {DetailsRenderer} detRenderer * @return {Element} */ - static render(dom, templateContext, details) { + static render(dom, templateContext, details, detRenderer) { const tmpl = dom.cloneTemplate('#tmpl-lh-crc', templateContext); const containerEl = dom.find('.lh-crc', tmpl); @@ -182,7 +183,7 @@ class CriticalRequestChainRenderer { for (const key of Object.keys(root.tree)) { const segment = CriticalRequestChainRenderer.createSegment(root.tree, key, root.startTime, root.transferSize); - CriticalRequestChainRenderer.buildTree(dom, tmpl, segment, containerEl, details); + CriticalRequestChainRenderer.buildTree(dom, tmpl, segment, containerEl, details, detRenderer); } return dom.find('.lh-crc-container', tmpl); diff --git a/lighthouse-core/report/html/renderer/details-renderer.js b/lighthouse-core/report/html/renderer/details-renderer.js index 4128e5180ebd..6f881bbec91d 100644 --- a/lighthouse-core/report/html/renderer/details-renderer.js +++ b/lighthouse-core/report/html/renderer/details-renderer.js @@ -53,7 +53,7 @@ class DetailsRenderer { case 'table': return this._renderTable(details); case 'criticalrequestchain': - return CriticalRequestChainRenderer.render(this._dom, this._templateContext, details); + return CriticalRequestChainRenderer.render(this._dom, this._templateContext, details, this); case 'opportunity': return this._renderTable(details); @@ -97,7 +97,7 @@ class DetailsRenderer { * @param {string} text * @return {HTMLElement} */ - _renderTextURL(text) { + renderTextURL(text) { const url = text; let displayedPath; @@ -211,7 +211,7 @@ class DetailsRenderer { return this.renderNode(value); } case 'url': { - return this._renderTextURL(value.value); + return this.renderTextURL(value.value); } default: { throw new Error(`Unknown valueType: ${value.type}`); @@ -256,7 +256,7 @@ class DetailsRenderer { case 'url': { const strValue = String(value); if (URL_PREFIXES.some(prefix => strValue.startsWith(prefix))) { - return this._renderTextURL(strValue); + return this.renderTextURL(strValue); } else { // Fall back to
 rendering if not actually a URL.
           return this._renderCode(strValue);
diff --git a/lighthouse-core/report/html/report-styles.css b/lighthouse-core/report/html/report-styles.css
index 1453a54c34d9..726805cf506a 100644
--- a/lighthouse-core/report/html/report-styles.css
+++ b/lighthouse-core/report/html/report-styles.css
@@ -149,29 +149,29 @@
     --color-green-700: var(--color-green);
     --color-teal-600: var(--color-cyan-500);
     --color-orange-700: var(--color-orange);
-  
+
     --color-black-200: var(--color-black-800);
     --color-black-400: var(--color-black-600);
     --color-black-600: var(--color-black-500);
-  
+
     --topbar-bg: var(--color-black);
     --plugin-badge-bg: var(--color-black-800);
     --env-item-bg: var(--color-black);
     --report-secondary-border-color: var(--color-black-200);
-  
+
     --body-background-color: var(--color-black-900);
     --body-text-color: var(--color-black-100);
     --secondary-text-color: var(--color-black-400);
-  
+
     --plugin-icon-url: var(--plugin-icon-url-dark);
-  
+
     --informative-color: var(--color-blue-200);
-  
+
     --medium-50-gray: #757575;
     --medium-75-gray: var(--color-white);
-  
+
     --color-hover: rgba(0, 0, 0, 0.2);
-  
+
     --pwa-fast-reliable-gray-url: var(--pwa-fast-reliable-gray-url-dark);
     --pwa-installable-gray-url: var(--pwa-installable-gray-url-dark);
     --pwa-optimized-gray-url: var(--pwa-optimized-gray-url-dark);
@@ -1351,12 +1351,8 @@
   width: 12%;
 }
 
-.lh-text__url:hover {
-  text-decoration: underline dotted #999;
-  text-decoration-skip-ink: auto;
-}
 
-.lh-text__url > .lh-text, .lh-text__url-host {
+.lh-text__url-host {
   display: inline;
 }
 
@@ -1372,12 +1368,15 @@
   object-fit: contain;
 }
 
-.lh-text__url > a,
-.lh-crc .crc-node__tree-value > a {
+.lh-text__url > a {
   color: inherit;
   text-decoration: none;
 }
 
+.lh-text__url > a:hover {
+  text-decoration: underline dotted #999;
+}
+
 /* Chevron
    https://codepen.io/paulirish/pen/LmzEmK
  */
diff --git a/lighthouse-core/report/html/templates.html b/lighthouse-core/report/html/templates.html
index e2492a9fe047..97afb8007ff2 100644
--- a/lighthouse-core/report/html/templates.html
+++ b/lighthouse-core/report/html/templates.html
@@ -741,12 +741,12 @@
       .lh-crc .crc-node__tree-value {
         margin-left: 10px;
       }
+      .lh-crc .crc-node__tree-value div {
+        display: inline;
+      }
       .lh-crc .crc-node__chain-duration {
         font-weight: 700;
       }
-      .lh-crc .crc-node__tree-hostname {
-        color: #595959;
-      }
       .lh-crc .crc-initial-nav {
         color: #595959;
         font-style: italic;
@@ -769,8 +769,7 @@
 
           
           
-            
-            ()
+
           
         
       
diff --git a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
index 79de69ef5d6d..860c9fbc307a 100644
--- a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
+++ b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
@@ -94,13 +94,13 @@ describe('DetailsRenderer', () => {
 
     // Main request
     assert.equal(chains.length, 4, 'generates correct number of chain nodes');
-    assert.equal(chains[0].querySelector('.crc-node__tree-hostname').textContent, '(example.com)');
+    assert.equal(chains[0].querySelector('.lh-text__url-host').textContent, '(example.com)');
 
     // Children
     assert.ok(chains[1].querySelector('.crc-node__tree-marker .vert-right'));
     assert.equal(chains[1].querySelectorAll('.crc-node__tree-marker .right').length, 2);
-    assert.equal(chains[1].querySelector('.crc-node__tree-file').textContent, '/b.js');
-    assert.equal(chains[1].querySelector('.crc-node__tree-hostname').textContent, '(example.com)');
+    assert.equal(chains[1].querySelector('.lh-text__url a').textContent, '/b.js');
+    assert.equal(chains[1].querySelector('.lh-text__url-host').textContent, '(example.com)');
     const durationNodes = chains[1].querySelectorAll('.crc-node__chain-duration');
     assert.equal(durationNodes[0].textContent, ' - 5,000\xa0ms, ');
     // Note: actual transferSize is 2000 bytes but formatter formats to KBs.

From c7504ab8024c2d13461b40a7085057bd7c89cd0e Mon Sep 17 00:00:00 2001
From: Connor Clark 
Date: Mon, 24 Jun 2019 10:36:04 -0700
Subject: [PATCH 15/17] detailsRenderer

---
 .../html/renderer/crc-details-renderer.js     | 24 ++++++++++---------
 .../renderer/crc-details-renderer-test.js     |  5 +++-
 .../html/renderer/details-renderer-test.js    |  3 +++
 3 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/lighthouse-core/report/html/renderer/crc-details-renderer.js b/lighthouse-core/report/html/renderer/crc-details-renderer.js
index fe020cf3758f..0c53f0865510 100644
--- a/lighthouse-core/report/html/renderer/crc-details-renderer.js
+++ b/lighthouse-core/report/html/renderer/crc-details-renderer.js
@@ -147,15 +147,15 @@ class CriticalRequestChainRenderer {
    * @param {CRCSegment} segment
    * @param {Element} elem Parent element.
    * @param {LH.Audit.Details.CriticalRequestChain} details
-   * @param {DetailsRenderer} detRenderer
+   * @param {DetailsRenderer} detailsRenderer
    */
-  static buildTree(dom, tmpl, segment, elem, details, detRenderer) {
-    elem.appendChild(CriticalRequestChainRenderer.createChainNode(dom, tmpl, segment, detRenderer));
+  static buildTree(dom, tmpl, segment, elem, details, detailsRenderer) {
+    elem.appendChild(CRCRenderer.createChainNode(dom, tmpl, segment, detailsRenderer));
     if (segment.node.children) {
       for (const key of Object.keys(segment.node.children)) {
-        const childSegment = CriticalRequestChainRenderer.createSegment(segment.node.children, key,
+        const childSegment = CRCRenderer.createSegment(segment.node.children, key,
           segment.startTime, segment.transferSize, segment.treeMarkers, segment.isLastChild);
-        CriticalRequestChainRenderer.buildTree(dom, tmpl, childSegment, elem, details, detRenderer);
+        CRCRenderer.buildTree(dom, tmpl, childSegment, elem, details, detailsRenderer);
       }
     }
   }
@@ -164,10 +164,10 @@ class CriticalRequestChainRenderer {
    * @param {DOM} dom
    * @param {ParentNode} templateContext
    * @param {LH.Audit.Details.CriticalRequestChain} details
-   * @param {DetailsRenderer} detRenderer
+   * @param {DetailsRenderer} detailsRenderer
    * @return {Element}
    */
-  static render(dom, templateContext, details, detRenderer) {
+  static render(dom, templateContext, details, detailsRenderer) {
     const tmpl = dom.cloneTemplate('#tmpl-lh-crc', templateContext);
     const containerEl = dom.find('.lh-crc', tmpl);
 
@@ -179,17 +179,19 @@ class CriticalRequestChainRenderer {
         Util.formatMilliseconds(details.longestChain.duration);
 
     // Construct visual tree.
-    const root = CriticalRequestChainRenderer.initTree(details.chains);
+    const root = CRCRenderer.initTree(details.chains);
     for (const key of Object.keys(root.tree)) {
-      const segment = CriticalRequestChainRenderer.createSegment(root.tree, key,
-          root.startTime, root.transferSize);
-      CriticalRequestChainRenderer.buildTree(dom, tmpl, segment, containerEl, details, detRenderer);
+      const segment = CRCRenderer.createSegment(root.tree, key, root.startTime, root.transferSize);
+      CRCRenderer.buildTree(dom, tmpl, segment, containerEl, details, detailsRenderer);
     }
 
     return dom.find('.lh-crc-container', tmpl);
   }
 }
 
+// Alias b/c the name is really long.
+const CRCRenderer = CriticalRequestChainRenderer;
+
 // Allow Node require()'ing.
 if (typeof module !== 'undefined' && module.exports) {
   module.exports = CriticalRequestChainRenderer;
diff --git a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
index 860c9fbc307a..e2e39a59e2ff 100644
--- a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
+++ b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
@@ -13,6 +13,7 @@ const jsdom = require('jsdom');
 const URL = require('../../../../lib/url-shim.js');
 const Util = require('../../../../report/html/renderer/util.js');
 const DOM = require('../../../../report/html/renderer/dom.js');
+const DetailsRenderer = require('../../../../report/html/renderer/details-renderer.js');
 const CriticalRequestChainRenderer =
     require('../../../../report/html/renderer/crc-details-renderer.js');
 
@@ -75,12 +76,14 @@ const DETAILS = {
 
 describe('DetailsRenderer', () => {
   let dom;
+  let detailsRenderer;
 
   beforeAll(() => {
     global.URL = URL;
     global.Util = Util;
     const {document} = new jsdom.JSDOM(TEMPLATE_FILE).window;
     dom = new DOM(document);
+    detailsRenderer = new DetailsRenderer(dom);
   });
 
   afterAll(() => {
@@ -89,7 +92,7 @@ describe('DetailsRenderer', () => {
   });
 
   it('renders tree structure', () => {
-    const el = CriticalRequestChainRenderer.render(dom, dom.document(), DETAILS);
+    const el = CriticalRequestChainRenderer.render(dom, dom.document(), DETAILS, detailsRenderer);
     const chains = el.querySelectorAll('.crc-node');
 
     // Main request
diff --git a/lighthouse-core/test/report/html/renderer/details-renderer-test.js b/lighthouse-core/test/report/html/renderer/details-renderer-test.js
index ec0986af00cb..f4bd18ab7c07 100644
--- a/lighthouse-core/test/report/html/renderer/details-renderer-test.js
+++ b/lighthouse-core/test/report/html/renderer/details-renderer-test.js
@@ -386,6 +386,9 @@ describe('DetailsRenderer', () => {
       assert.equal(urlEl.title, urlText);
       assert.equal(urlEl.dataset.url, urlText);
       assert.equal(urlEl.firstChild.nodeName, 'A');
+      assert.equal(urlEl.firstChild.href, urlText);
+      assert.equal(urlEl.firstChild.rel, 'noopener');
+      assert.equal(urlEl.firstChild.target, '_blank');
       assert.equal(urlEl.textContent, displayUrlText);
     });
 

From b965f04bad8eb76ef20166c696db6dee8805fb69 Mon Sep 17 00:00:00 2001
From: Connor Clark 
Date: Tue, 25 Jun 2019 16:13:32 -0700
Subject: [PATCH 16/17] fix test

---
 .../test/report/html/renderer/crc-details-renderer-test.js     | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
index e2e39a59e2ff..cca9a9830666 100644
--- a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
+++ b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
@@ -97,7 +97,8 @@ describe('DetailsRenderer', () => {
 
     // Main request
     assert.equal(chains.length, 4, 'generates correct number of chain nodes');
-    assert.equal(chains[0].querySelector('.lh-text__url-host').textContent, '(example.com)');
+    assert.ok(!chains[0].querySelector('.lh-text__url-host'), 'should be no origin for root url');
+    assert.equal(chains[0].querySelector('.lh-text__url a').textContent, 'https://example.com');
 
     // Children
     assert.ok(chains[1].querySelector('.crc-node__tree-marker .vert-right'));

From ccefdd4c0fa7645aa0f332c8310963e741d972ef Mon Sep 17 00:00:00 2001
From: Connor Clark 
Date: Wed, 26 Jun 2019 20:22:58 -0700
Subject: [PATCH 17/17] test

---
 .../test/report/html/renderer/crc-details-renderer-test.js  | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
index cca9a9830666..f5d8ca14ce6a 100644
--- a/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
+++ b/lighthouse-core/test/report/html/renderer/crc-details-renderer-test.js
@@ -99,11 +99,17 @@ describe('DetailsRenderer', () => {
     assert.equal(chains.length, 4, 'generates correct number of chain nodes');
     assert.ok(!chains[0].querySelector('.lh-text__url-host'), 'should be no origin for root url');
     assert.equal(chains[0].querySelector('.lh-text__url a').textContent, 'https://example.com');
+    assert.equal(chains[0].querySelector('.lh-text__url a').href, 'https://example.com/');
+    assert.equal(chains[0].querySelector('.lh-text__url a').rel, 'noopener');
+    assert.equal(chains[0].querySelector('.lh-text__url a').target, '_blank');
 
     // Children
     assert.ok(chains[1].querySelector('.crc-node__tree-marker .vert-right'));
     assert.equal(chains[1].querySelectorAll('.crc-node__tree-marker .right').length, 2);
     assert.equal(chains[1].querySelector('.lh-text__url a').textContent, '/b.js');
+    assert.equal(chains[1].querySelector('.lh-text__url a').href, 'https://example.com/b.js');
+    assert.equal(chains[1].querySelector('.lh-text__url a').rel, 'noopener');
+    assert.equal(chains[1].querySelector('.lh-text__url a').target, '_blank');
     assert.equal(chains[1].querySelector('.lh-text__url-host').textContent, '(example.com)');
     const durationNodes = chains[1].querySelectorAll('.crc-node__chain-duration');
     assert.equal(durationNodes[0].textContent, ' - 5,000\xa0ms, ');