Last active
October 19, 2018 14:15
-
-
Save perjerz/c6e9e1e248cd4febc3f8294b370adc26 to your computer and use it in GitHub Desktop.
Lighthouse
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
@license | |
Copyright 2018 Google Inc. All Rights Reserved. | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS-IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
--> | |
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> | |
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAADjklEQVR4AWI08P/HQEvAQrxSQKvlECfLFYXx75xCY2qmh89GbNvOMjb3v9jOOlxnFWxj206ebQ3b7q6q+z1rNagu8/zvPSZACAABpeUAA0miMgU7SA7JjCraFGwZwECOwvL75dWjsKgWBKtx0jvWo+vkBAFbACCkByMP6nMn48+AVgXB2fzSCwsv22/lMGlUhmJ0AE7BH8dyUUDbUEgN6RzJRSeaPxhdRYR0Inel+7Hd5lBiFpkMAxACc0394//9C4voFHDiAAGLpuOXebdfdHfctgwJKaZRLRKy6ItrSis6RBnVBgGtbHyKTEmJHQoEXoBCE5BCrDeA2ogMUIGDAKEBDEhUqwgMqBYDjW4DQzmuffVdqff42/ZQYYqVcMXGZsMPyCsH3lyJSetxvEaxAQXdjR1HjfwCdIS7lo2DZke26Qe+MXO12OWkGT0O6oE7vMGkMnkYw4aN1KQgMKExhXqswfiov4+a7MQ11XPnbr/5qpKlgACAAQj94Lu271bN9DUecQasIZlNzG72llRAAKJiAi+/BSHrSFjRvQhg3DEKEqJh08tsmLTx597+f6enr4cc2Zpk57pihfX24dW7RHcOLLUbJYhJSl0ErQCI9BVXH/XrO97QasuvQQSiECa0BrQCIIJp6X9T/r8QG6L71WYSqCoIIGo2BZDUBnS/D9EA9Nun1iYvbM0MFExIDQRoKFatc1Z6zrm5uWeObJotq0BGV9FuQBWq5a4Fw3PPz848rZHstZSuA5FWAFSMP2nOppOOGpl6qh9PCSg0IFyHKjSQyDNQHTru2t75NOEe0fsf246oAmFkI6vCdnWvbQFQFCKx8vCswV8TrDLiDLgH4Nr7RAtNsrC9d8sfk7b8ls4igdNy8CQKAISlsB0FjZfd3Lfp155tf8fKI4BxZZIj/oTdVEAIAcJFOCmzauHG71I7/rdreUAgAqpDP05fDARCAQQARwEIBQSVxq0FyaLvZZtevpHa8WHw8cft6cpxlq8eAJtIhnSbWDf951yx3y13OqUuu5qyGgkxCgGFh9cDihDGbTa6BqvT1lWmrav3bmt2ZMJ4mU6TGgIC4DBzcv/JqAau1WhzSt3x9Ixk/4Jk/8J4ZrrViFMA4W6A7+WK8xcVjvyrOmVD0FbAXokcT48r+xVqLKvuJYbmpNadnlp3mpufJHOe/GXktM+r09bT8kEdq9BRYAbGSgzP7ll82U71Mc+ZFooXgwAAAABJRU5ErkJggg=="> | |
<title>Lighthouse Report</title> | |
<style>/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
.lh-vars { | |
--text-font-family: Roboto, Helvetica, Arial, sans-serif; | |
--monospace-font-family: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; | |
--body-background-color: #fff; | |
--body-font-size: 14px; | |
--body-line-height: 18px; | |
--subheader-font-size: 14px; | |
--subheader-line-height: 20px; | |
--subheader-color: hsl(206, 6%, 25%); | |
--header-bg-color: #f1f3f4; | |
--header-font-size: 20px; | |
--header-line-height: 24px; | |
--title-font-size: 24px; | |
--title-line-height: 28px; | |
--caption-font-size: 12px; | |
--caption-line-height: 16px; | |
--default-padding: 12px; | |
--section-padding: 16px; | |
--section-indent: 16px; | |
--audit-group-indent: 16px; | |
--audit-item-gap: 5px; | |
--audit-indent: 16px; | |
--text-indent: 8px; | |
--expandable-indent: 20px; | |
--secondary-text-color: #565656; | |
/*--accent-color: #3879d9;*/ | |
--fail-color: hsl(1, 73%, 45%); | |
--average-color: hsl(31, 100%, 45%); /* md orange 800 */ | |
--pass-color: hsl(139, 70%, 30%); | |
--informative-color: #0c50c7; | |
--medium-75-gray: #757575; | |
--medium-50-gray: hsl(210, 17%, 98%); | |
--medium-100-gray: hsl(200, 12%, 95%); | |
--warning-color: #ffab00; /* md amber a700 */ | |
--report-border-color: #ccc; | |
--report-secondary-border-color: #ebebeb; | |
--metric-timeline-rule-color: #b3b3b3; | |
--display-value-gray: hsl(216, 5%, 39%); | |
--report-width: calc(60 * var(--body-font-size)); | |
--report-header-height: 161px; | |
--report-header-color: #202124; | |
--navitem-font-size: var(--body-font-size); | |
--navitem-line-height: var(--body-line-height); | |
--navitem-hpadding: var(--body-font-size); | |
--navitem-vpadding: calc(var(--navitem-line-height) / 2); | |
--lh-score-highlight-bg: hsla(0, 0%, 90%, 0.2); | |
--lh-score-icon-background-size: 24px; | |
--lh-score-margin: 12px; | |
--lh-table-header-bg: #f8f9fa; | |
--lh-table-higlight-bg: hsla(0, 0%, 75%, 0.1); | |
--lh-sparkline-height: 5px; | |
--lh-sparkline-thin-height: 3px; | |
--lh-filmstrip-thumbnail-width: 60px; | |
--lh-score-icon-width: calc(var(--body-font-size) / 14 * 16); | |
--lh-category-score-width: calc(5 * var(--body-font-size)); | |
--lh-audit-vpadding: 8px; | |
--lh-audit-index-width: 18px; | |
--lh-audit-hgap: 12px; | |
--lh-audit-group-vpadding: 8px; | |
--lh-section-vpadding: 12px; | |
--chevron-size: 12px; | |
/* Voodoo magic here to get narrow columns. 0 doesn't size the column like our friend 1px does */ | |
--bytes-col-width: 1px; | |
--pass-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><title>check</title><path fill="hsl(139, 70%, 30%)" d="M24 4C12.95 4 4 12.95 4 24c0 11.04 8.95 20 20 20 11.04 0 20-8.96 20-20 0-11.05-8.96-20-20-20zm-4 30L10 24l2.83-2.83L20 28.34l15.17-15.17L38 16 20 34z"/></svg>'); | |
--average-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><title>info</title><path fill="hsl(31, 100%, 45%)" d="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm2 30h-4V22h4v12zm0-16h-4v-4h4v4z"/></svg>'); | |
--fail-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><title>warn</title><path fill="hsl(1, 73%, 45%)" d="M2 42h44L24 4 2 42zm24-6h-4v-4h4v4zm0-8h-4v-8h4v8z"/></svg>'); | |
--content-paste-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="hsl(216, 5%, 39%)" d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'); | |
--av-timer-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="hsl(216, 5%, 39%)"><path d="M0 0h24v24H0z" fill="none"/><path d="M15 1H9v2h6V1zm-4 13h2V8h-2v6zm8.03-6.61l1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42A8.962 8.962 0 0 0 12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9a8.994 8.994 0 0 0 7.03-14.61zM12 20c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></svg>'); | |
--photo-filter-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path fill="none" d="M0 0h48v48H0V0z"/><path d="M38.04 20v18H10V10h18V6H10.04c-2.2 0-4 1.8-4 4v28c0 2.2 1.8 4 4 4h28c2.2 0 4-1.8 4-4V20h-4zM34 20l1.88-4.12L40 14l-4.12-1.88L34 8l-1.88 4.12L28 14l4.12 1.88zm-7.5 1.5L24 16l-2.5 5.5L16 24l5.5 2.5L24 32l2.5-5.5L32 24z" fill="hsl(216, 5%, 39%)"/></svg>'); | |
--visibility-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path d="M0 0h48v48H0z" fill="none"/><path d="M24 9C14 9 5.46 15.22 2 24c3.46 8.78 12 15 22 15 10.01 0 18.54-6.22 22-15-3.46-8.78-11.99-15-22-15zm0 25c-5.52 0-10-4.48-10-10s4.48-10 10-10 10 4.48 10 10-4.48 10-10 10zm0-16c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6z" fill="hsl(216, 5%, 39%)"/></svg>'); | |
--check-circle-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path d="M0 0h48v48H0z" fill="none"/><path d="M24 4C12.95 4 4 12.95 4 24c0 11.04 8.95 20 20 20 11.04 0 20-8.96 20-20 0-11.05-8.96-20-20-20zm-4 30L10 24l2.83-2.83L20 28.34l15.17-15.17L38 16 20 34z" fill="hsl(216, 5%, 39%)"/></svg>'); | |
--check-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path d="M0 0h48v48H0z" fill="none"/><path d="M18 32.34L9.66 24l-2.83 2.83L18 38l24-24-2.83-2.83z"/></svg>'); | |
--search-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path d="M31 28h-1.59l-.55-.55C30.82 25.18 32 22.23 32 19c0-7.18-5.82-13-13-13S6 11.82 6 19s5.82 13 13 13c3.23 0 6.18-1.18 8.45-3.13l.55.55V31l10 9.98L40.98 38 31 28zm-12 0a9 9 0 1 1 .001-18.001A9 9 0 0 1 19 28z" fill="hsl(216, 5%, 39%)"/><path d="M0 0h48v48H0z" fill="none" /></svg>'); | |
--remove-circle-icon-url: url('data:image/svg+xml;utf8,<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" fill="hsl(216, 5%, 39%)"/></svg>'); | |
} | |
.lh-vars.lh-devtools { | |
--text-font-family: '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande', sans-serif; | |
--monospace-font-family: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; | |
--body-font-size: 12px; | |
--body-line-height: 16px; | |
--subheader-font-size: 14px; | |
--subheader-line-height: 18px; | |
--header-font-size: 16px; | |
--header-line-height: 20px; | |
--title-font-size: 20px; | |
--title-line-height: 24px; | |
--caption-font-size: 11px; | |
--caption-line-height: 14px; | |
--default-padding: 12px; | |
--section-padding: 12px; | |
--section-indent: 8px; | |
--audit-group-indent: 16px; | |
--audit-indent: 16px; | |
--expandable-indent: 16px; | |
--lh-audit-vpadding: 4px; | |
--lh-audit-hgap: 12px; | |
--lh-audit-group-vpadding: 12px; | |
--lh-section-vpadding: 8px; | |
} | |
@keyframes fadeIn { | |
0% { opacity: 0;} | |
100% { opacity: 0.6;} | |
} | |
.lh-root * { | |
box-sizing: border-box; | |
} | |
.lh-root { | |
font-family: var(--text-font-family); | |
font-size: var(--body-font-size); | |
margin: 0; | |
line-height: var(--body-line-height); | |
background: var(--body-background-color); | |
scroll-behavior: smooth; | |
} | |
.lh-root :focus { | |
outline: -webkit-focus-ring-color auto 3px; | |
} | |
.lh-root summary:focus { | |
outline: none; | |
box-shadow: 0 0 0 1px hsl(217, 89%, 61%); | |
} | |
.lh-root [hidden] { | |
display: none !important; | |
} | |
.lh-root details > summary { | |
cursor: pointer; | |
} | |
.lh-audit-group a, | |
.lh-category-header__description a { | |
color: #0c50c7; | |
} | |
.lh-audit__description { | |
--inner-audit-left-padding: calc(var(--text-indent) + var(--lh-audit-index-width) + 2 * var(--audit-item-gap)); | |
--inner-audit-right-padding: calc(var(--text-indent) + 2px); | |
padding-left: var(--inner-audit-left-padding); | |
padding-right: var(--inner-audit-right-padding); | |
padding-top: 8px; | |
padding-bottom: 8px; | |
} | |
.lh-details { | |
font-size: var(--body-font-size); | |
margin-top: var(--default-padding); | |
margin-bottom: var(--default-padding); | |
/* whatever the .lh-details side margins are */ | |
width: 100%; | |
} | |
.lh-details.flex .lh-code { | |
max-width: 70%; | |
} | |
/* Report header */ | |
.report-icon { | |
opacity: 0.7; | |
} | |
.report-icon:hover { | |
opacity: 1; | |
} | |
.report-icon[disabled] { | |
opacity: 0.3; | |
pointer-events: none; | |
} | |
.report-icon--share { | |
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/></svg>'); | |
} | |
.report-icon--print { | |
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/><path fill="none" d="M0 0h24v24H0z"/></svg>'); | |
} | |
.report-icon--copy { | |
background-image: url('data:image/svg+xml;utf8,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>'); | |
} | |
.report-icon--open { | |
background-image: url('data:image/svg+xml;utf8,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"/></svg>'); | |
} | |
.report-icon--download { | |
background-image: url('data:image/svg+xml;utf8,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'); | |
} | |
/* Node */ | |
.lh-node { | |
display: block; | |
font-family: var(--monospace-font-family); | |
word-break: break-word; | |
color: hsl(174, 100%, 27%); | |
} | |
.lh-node:hover { | |
background: hsl(0, 0%, 98%); | |
border-radius: 2px; | |
} | |
/* Score */ | |
.lh-audit__score-icon { | |
margin-left: var(--lh-score-margin); | |
width: var(--lh-score-icon-width); | |
height: var(--lh-score-icon-width); | |
background: none no-repeat center center / contain; | |
} | |
.lh-audit--pass .lh-audit__display-text { | |
color: var(--pass-color); | |
} | |
.lh-audit--pass .lh-audit__score-icon { | |
background-image: var(--pass-icon-url); | |
} | |
.lh-audit--average .lh-audit__display-text { | |
color: var(--average-color); | |
} | |
.lh-audit--average .lh-audit__score-icon { | |
background-image: var(--average-icon-url); | |
} | |
.lh-audit--fail .lh-audit__display-text { | |
color: var(--fail-color); | |
} | |
.lh-audit--fail .lh-audit__score-icon { | |
background-image: var(--fail-icon-url); | |
} | |
.lh-audit--informative .lh-audit__display-text { | |
color: var(--display-value-gray); | |
} | |
.lh-audit--informative .lh-audit__score-icon, | |
.lh-audit--manual .lh-audit__score-icon { | |
visibility: hidden; | |
} | |
.lh-audit--error .lh-audit__score-icon { | |
display: none; | |
} | |
.lh-category-header__description, | |
.lh-audit__description { | |
color: var(--secondary-text-color); | |
} | |
.lh-category-header__description { | |
font-size: var(--body-font-size); | |
margin: calc(var(--default-padding) / 2) 0 var(--default-padding); | |
} | |
.lh-audit__index, | |
.lh-audit__title, | |
.lh-audit__display-text, | |
.lh-audit__score-icon, | |
.lh-load-opportunity__sparkline, | |
.lh-chevron-container { | |
margin: 0 var(--audit-item-gap); | |
} | |
.lh-audit__index { | |
margin-left: 0; | |
} | |
.lh-chevron-container { | |
margin-right: 0; | |
} | |
.lh-audit__header .lh-audit__index { | |
width: var(--lh-audit-index-width); | |
} | |
.lh-audit__title { | |
flex: 1; | |
} | |
/* Expandable Details (Audit Groups, Audits) */ | |
.lh-audit__header { | |
display: flex; | |
padding: var(--lh-audit-vpadding) var(--text-indent); | |
} | |
.lh-audit--load-opportunity .lh-audit__header { | |
display: block; | |
} | |
.lh-audit__header:hover { | |
background-color: #F8F9FA; | |
} | |
.lh-audit-group__summary::-webkit-details-marker, | |
.lh-expandable-details__summary::-webkit-details-marker { | |
display: none; | |
} | |
/* Perf Metric */ | |
.lh-columns { | |
display: flex; | |
width: 100%; | |
} | |
@media screen and (max-width: 640px) { | |
.lh-columns { | |
flex-wrap: wrap; | |
} | |
} | |
.lh-column { | |
flex: 1; | |
} | |
.lh-column:first-of-type { | |
margin-right: 24px; | |
} | |
@media screen and (max-width: 800px) { | |
.lh-column:first-of-type { | |
margin-right: 8px; | |
} | |
} | |
@media screen and (max-width: 640px) { | |
.lh-column { | |
flex-basis: 100%; | |
} | |
.lh-column:first-of-type { | |
margin-right: 0px; | |
} | |
} | |
.lh-metric { | |
border-bottom: 1px solid var(--report-secondary-border-color); | |
} | |
.lh-metric__innerwrap { | |
display: flex; | |
justify-content: space-between; | |
padding: 11px var(--text-indent); | |
} | |
.lh-metric__details { | |
order: -1; | |
} | |
.lh-metric__title { | |
font-size: var(--body-font-size); | |
line-height: var(--body-line-height); | |
display: flex; | |
white-space: nowrap; | |
} | |
.lh-metric__name { | |
flex: 1; | |
} | |
.lh-metrics__disclaimer { | |
color: var(--medium-75-gray); | |
text-align: right; | |
margin: var(--lh-section-vpadding) 0; | |
padding: 0 var(--text-indent); | |
} | |
.lh-metric__description { | |
color: var(--secondary-text-color); | |
} | |
.lh-metric__value { | |
white-space: nowrap; /* No wrapping between metric value and the icon */ | |
} | |
.lh-metric .lh-metric__value::after { | |
content: ''; | |
width: var(--lh-score-icon-width); | |
height: var(--lh-score-icon-width); | |
background-size: contain; | |
display: inline-block; | |
vertical-align: text-bottom; | |
margin-left: calc(var(--body-font-size) / 2); | |
} | |
.lh-metric--pass .lh-metric__value { | |
color: var(--pass-color); | |
} | |
.lh-metric--pass .lh-metric__value::after { | |
background: var(--pass-icon-url) no-repeat 50% 50%; | |
} | |
.lh-metric--average .lh-metric__value { | |
color: var(--average-color); | |
padding-left: 16px; | |
} | |
.lh-metric--average .lh-metric__value::after { | |
background: var(--average-icon-url) no-repeat 50% 50%; | |
} | |
.lh-metric--fail .lh-metric__value { | |
color: var(--fail-color); | |
} | |
.lh-metric--fail .lh-metric__value::after { | |
background: var(--fail-icon-url) no-repeat 50% 50%; | |
} | |
.lh-metric--error .lh-metric__value, | |
.lh-metric--error .lh-metric__description { | |
color: var(--fail-color); | |
} | |
/* Hide icon if there was an error */ | |
.lh-metric--error .lh-metric__value::after { | |
display: none; | |
} | |
/* Perf load opportunity */ | |
.lh-load-opportunity__cols { | |
display: flex; | |
align-items: flex-start; | |
} | |
.lh-load-opportunity__header .lh-load-opportunity__col { | |
background-color: var(--medium-50-gray); | |
color: var(--medium-75-gray); | |
text-align: center; | |
display: unset; | |
line-height: calc(2.3 * var(--body-font-size)); | |
} | |
.lh-load-opportunity__col { | |
display: flex; | |
justify-content: space-between; | |
} | |
.lh-load-opportunity__col--one { | |
flex: 5; | |
margin-right: 2px; | |
} | |
.lh-load-opportunity__col--two { | |
flex: 4; | |
} | |
.lh-audit--load-opportunity .lh-audit__display-text { | |
text-align: right; | |
flex: 0 0 calc(3 * var(--body-font-size)); | |
} | |
/* Sparkline */ | |
.lh-load-opportunity__sparkline { | |
flex: 1; | |
margin-top: calc((var(--body-line-height) - var(--lh-sparkline-height)) / 2); | |
} | |
.lh-sparkline { | |
height: var(--lh-sparkline-height); | |
width: 100%; | |
} | |
.lh-sparkline__bar { | |
height: 100%; | |
float: right; | |
} | |
.lh-audit--pass .lh-sparkline__bar { | |
background: var(--pass-color); | |
} | |
.lh-audit--average .lh-sparkline__bar { | |
background: var(--average-color); | |
} | |
.lh-audit--fail .lh-sparkline__bar { | |
background: var(--fail-color); | |
} | |
/* Filmstrip */ | |
.lh-filmstrip-container { | |
padding: 0 var(--expandable-indent); | |
/* smaller gap between metrics and filmstrip */ | |
margin: -16px auto 0 auto; | |
} | |
.lh-filmstrip { | |
display: flex; | |
flex-direction: row; | |
justify-content: space-between; | |
padding-bottom: var(--default-padding); | |
} | |
.lh-filmstrip__frame { | |
text-align: right; | |
position: relative; | |
} | |
.lh-filmstrip__thumbnail { | |
border: 1px solid var(--report-secondary-border-color); | |
max-height: 100px; | |
max-width: 60px; | |
} | |
@media screen and (max-width: 750px) { | |
.lh-filmstrip { | |
flex-wrap: wrap; | |
justify-content: left; | |
} | |
.lh-filmstrip__frame { | |
margin: calc(var(--default-padding) / 3); | |
} | |
} | |
/* Audit */ | |
.lh-audit { | |
border-bottom: 1px solid var(--report-secondary-border-color); | |
} | |
.lh-audit--error .lh-audit__display-text { | |
color: var(--fail-color); | |
} | |
/* Audit Group */ | |
.lh-audit-group { | |
margin: var(--lh-audit-group-vpadding) 0; | |
} | |
.lh-audit-group__header { | |
font-size: var(--subheader-font-size); | |
line-height: var(--subheader-line-height); | |
color: var(--subheader-color); | |
flex: 1; | |
font-weight: bold; | |
} | |
.lh-audit-group__header::before { | |
content: ''; | |
width: calc(var(--subheader-font-size) / 14 * 24); | |
height: calc(var(--subheader-font-size) / 14 * 24); | |
margin-right: calc(var(--subheader-font-size) / 2); | |
background: var(--medium-100-gray) none no-repeat center / 16px; | |
display: inline-block; | |
border-radius: 50%; | |
vertical-align: middle; | |
} | |
/* A11y/Seo groups within Passed don't get an icon */ | |
.lh-audit-group--unadorned .lh-audit-group__header::before { | |
content: none; | |
} | |
.lh-audit-group--manual .lh-audit-group__header::before { | |
background-image: var(--search-icon-url); | |
} | |
.lh-passed-audits .lh-audit-group__header::before { | |
background-image: var(--check-icon-url); | |
} | |
.lh-audit-group--diagnostics .lh-audit-group__header::before { | |
background-image: var(--content-paste-icon-url); | |
} | |
.lh-audit-group--opportunities .lh-audit-group__header::before { | |
background-image: var(--photo-filter-icon-url); | |
} | |
.lh-audit-group--metrics .lh-audit-group__header::before { | |
background-image: var(--av-timer-icon-url); | |
} | |
.lh-audit-group--not-applicable .lh-audit-group__header::before { | |
background-image: var(--remove-circle-icon-url); | |
} | |
/* Removing too much whitespace */ | |
.lh-audit-group--metrics { | |
margin-top: -28px; | |
border-bottom: none; | |
} | |
.lh-audit-group__summary { | |
display: flex; | |
justify-content: space-between; | |
padding-right: var(--text-indent); | |
} | |
.lh-audit-group__itemcount { | |
color: var(--display-value-gray); | |
margin: 3px 10px 0; | |
} | |
.lh-audit-group__summary .lh-chevron { | |
margin-top: calc((var(--body-line-height) - 5px) / 2); | |
} | |
.lh-audit-group__description { | |
font-size: var(--body-font-size); | |
color: var(--medium-75-gray); | |
margin: var(--lh-audit-group-vpadding) 0; | |
} | |
.lh-audit-group--unadorned .lh-audit-group__description { | |
margin-top: 0; | |
} | |
.lh-audit-explanation { | |
margin: var(--lh-audit-vpadding) 0 calc(var(--lh-audit-vpadding) / 2); | |
line-height: var(--caption-line-height); | |
} | |
.lh-audit--fail .lh-audit-explanation { | |
color: var(--fail-color); | |
} | |
/* Report */ | |
.lh-container { | |
display: flex; | |
max-width: var(--report-width); | |
word-wrap: break-word; | |
margin: 0 auto; | |
} | |
.lh-header-sticky { | |
position: sticky; | |
top: 0; | |
width: 100%; | |
z-index: 2; | |
will-change: transform; | |
} | |
.lh-header-plain { | |
margin-top: var(--section-padding); | |
} | |
.lh-header-container { | |
display: block; | |
margin: 0 auto; | |
max-width: var(--report-width); | |
position: relative; | |
word-wrap: break-word; | |
} | |
.lh-report { | |
background-color: #fff; | |
} | |
@media screen { | |
.lh-report { | |
width: var(--report-width); | |
} | |
} | |
.lh-exception { | |
font-size: large; | |
} | |
.lh-code { | |
white-space: normal; | |
margin-top: 0; | |
font-size: 85%; | |
word-break: break-word; | |
} | |
.lh-warnings { | |
--item-margin: calc(var(--body-line-height) / 6); | |
border: 1px solid var(--average-color); | |
border-radius: 4px; | |
margin: var(--lh-audit-vpadding) 0; | |
padding: calc(var(--lh-audit-vpadding) / 2) var(--lh-audit-vpadding); | |
} | |
.lh-warnings--toplevel { | |
--item-margin: calc(var(--header-line-height) / 4); | |
color: var(--secondary-text-color); | |
margin: var(--section-padding); | |
padding: var(--section-padding); | |
} | |
.lh-warnings ul { | |
padding-left: calc(var(--section-padding) * 2); | |
margin: 0; | |
} | |
.lh-warnings li { | |
margin: var(--item-margin) 0; | |
} | |
.lh-warnings li:last-of-type { | |
margin-bottom: 0; | |
} | |
.lh-scores-header { | |
display: flex; | |
justify-content: left; | |
overflow-x: hidden; | |
position: relative; | |
padding: var(--section-indent) calc(var(--section-indent) / 2) calc(var(--section-indent) * 2); | |
} | |
.lh-scores-header__solo { | |
padding: 0; | |
border: 0; | |
} | |
.lh-scores-header .lh-gauge__wrapper { | |
margin: 0 4px; | |
} | |
.lh-scorescale { | |
color: var(--medium-75-gray); | |
padding: 0 calc(var(--section-indent) * 1.5) 0; | |
text-align: right; | |
transform-origin: bottom right; | |
will-change: opacity; /* opacity is changed on scroll */ | |
} | |
.lh-scorescale-range { | |
margin-left: 10px; | |
white-space: nowrap; | |
} | |
.lh-scorescale-range::before { | |
content: ''; | |
width: var(--body-font-size); | |
height: calc(var(--body-font-size) * .60); | |
border-radius: 4px; | |
display: inline-block; | |
margin: 0 5px; | |
} | |
.lh-scorescale-range--pass::before { | |
background-color: var(--pass-color); | |
} | |
.lh-scorescale-range--average::before { | |
background-color: var(--average-color); | |
} | |
.lh-scorescale-range--fail::before { | |
background-color: var(--fail-color); | |
} | |
/* Hide category score gauages if it's a single category report */ | |
.lh-header--solo-category .lh-scores-wrapper { | |
display: none; | |
} | |
.lh-categories { | |
width: 100%; | |
overflow: hidden; | |
} | |
.lh-category { | |
--circle-size: calc(2.5 * var(--header-font-size)); | |
padding: var(--section-padding); | |
} | |
.lh-category:first-of-type { | |
padding-top: calc(2 * var(--section-padding)); | |
border: none; | |
} | |
/* section hash link jump should preserve fixed header | |
https://css-tricks.com/hash-tag-links-padding/ | |
*/ | |
.lh-category > .lh-permalink { | |
margin-top: calc((var(--report-header-height) + var(--default-padding)) * -1); | |
padding-bottom: calc(var(--report-header-height) + var(--default-padding)); | |
display: block; | |
visibility: hidden; | |
} | |
.lh-category-header { | |
font-size: var(--header-font-size); | |
min-height: var(--circle-size); | |
margin-bottom: var(--lh-section-vpadding); | |
} | |
.lh-category-header__title { | |
line-height: 24px; | |
} | |
.lh-category-header .lh-score__gauge .lh-gauge__label { | |
display: none; | |
} | |
.lh-category-header .lh-score__gauge { | |
float: right; | |
} | |
.lh-category-header .lh-score__gauge { | |
margin-left: var(--section-indent); | |
} | |
.lh-category-header .lh-audit__title { | |
font-size: var(--header-font-size); | |
line-height: var(--header-line-height); | |
} | |
.lh-passed-audits[open] summary.lh-passed-audits-summary { | |
margin-bottom: calc(var(--default-padding) * 2); | |
} | |
summary.lh-passed-audits-summary { | |
margin: calc(var(--default-padding) * 2) var(--default-padding); | |
margin-left: var(--default-padding); | |
margin-bottom: 0; | |
font-size: 15px; | |
display: flex; | |
align-items: center; | |
} | |
#lh-log { | |
position: fixed; | |
background-color: #323232; | |
color: #fff; | |
min-height: 48px; | |
min-width: 288px; | |
padding: 16px 24px; | |
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); | |
border-radius: 2px; | |
margin: 12px; | |
font-size: 14px; | |
cursor: default; | |
transition: transform 0.3s, opacity 0.3s; | |
transform: translateY(100px); | |
opacity: 0; | |
-webkit-font-smoothing: antialiased; | |
bottom: 0; | |
left: 0; | |
z-index: 3; | |
} | |
#lh-log.show { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
/* 964 fits the min-width of the filmstrip */ | |
@media screen and (max-width: 964px) { | |
.lh-report { | |
margin-left: 0; | |
width: 100%; | |
min-width: 400px; | |
} | |
} | |
@media print { | |
body { | |
-webkit-print-color-adjust: exact; /* print background colors */ | |
} | |
.lh-container { | |
display: block; | |
} | |
.lh-report { | |
margin-left: 0; | |
padding-top: 0; | |
} | |
.lh-categories { | |
margin-top: 0; | |
} | |
} | |
.lh-table { | |
--image-preview-size: 24px; | |
border-collapse: collapse; | |
} | |
.lh-table thead { | |
background: var(--lh-table-header-bg); | |
} | |
.lh-table thead th { | |
color: var(--medium-75-gray); | |
font-weight: normal; | |
} | |
.lh-table tbody tr:nth-child(even) { | |
background-color: var(--lh-table-higlight-bg); | |
} | |
.lh-table th, | |
.lh-table td { | |
padding: 8px 6px; | |
} | |
/* Looks unnecessary, but mostly for keeping the <th>s left-aligned */ | |
.lh-table-column--text, | |
.lh-table-column--url, | |
/* .lh-table-column--thumbnail, */ | |
/* .lh-table-column--empty,*/ | |
.lh-table-column--code, | |
.lh-table-column--node { | |
text-align: left; | |
} | |
.lh-table-column--bytes, | |
.lh-table-column--timespanMs, | |
.lh-table-column--ms { | |
text-align: right; | |
} | |
.lh-table-column--thumbnail { | |
width: calc(var(--image-preview-size) * 2); | |
} | |
.lh-table-column--url { | |
min-width: 250px; | |
white-space: nowrap; | |
max-width: 0; | |
} | |
/* Keep bytes columns narrow if they follow the URL column */ | |
.lh-table-column--url + th.lh-table-column--bytes, | |
.lh-table-column--url + .lh-table-column--bytes + th.lh-table-column--bytes, | |
.lh-table-column--url + .lh-table-column--bytes + th.lh-table-column--timespanMs { | |
max-width: var(--bytes-col-width); | |
} | |
.lh-table-column--code { | |
max-width: var(--url-col-max-width); | |
} | |
.lh-text__url { | |
overflow: hidden; | |
text-overflow: ellipsis; | |
} | |
.lh-text__url:hover { | |
text-decoration: underline dotted #999; | |
text-decoration-skip-ink: auto; | |
} | |
.lh-text__url > .lh-text, .lh-text__url-host { | |
display: inline-block; | |
} | |
.lh-text__url-host { | |
margin-left: calc(var(--body-font-size) / 2); | |
opacity: 0.6; | |
font-size: 90% | |
} | |
.lh-thumbnail { | |
height: var(--image-preview-size); | |
width: var(--image-preview-size); | |
object-fit: contain; | |
} | |
/* Chevron | |
https://codepen.io/paulirish/pen/LmzEmK | |
*/ | |
.lh-chevron { | |
--chevron-angle: 42deg; | |
width: var(--chevron-size); | |
height: var(--chevron-size); | |
margin-top: calc((var(--body-line-height) - 12px) / 2); | |
} | |
.lh-chevron__lines { | |
transition: transform 0.4s; | |
transform: translateY(var(--body-line-height)); | |
} | |
.lh-chevron__line { | |
stroke: var(--display-value-gray); | |
stroke-width: var(--chevron-size); | |
stroke-linecap: square; | |
transform-origin: 50%; | |
transform: rotate(var(--chevron-angle)); | |
transition: transform 300ms, stroke 300ms; | |
} | |
.lh-audit-group > .lh-audit-group__summary > .lh-chevron .lh-chevron__line-right, | |
.lh-audit-group[open] > .lh-audit-group__summary > .lh-chevron .lh-chevron__line-left, | |
.lh-audit > .lh-expandable-details .lh-chevron__line-right, | |
.lh-audit > .lh-expandable-details[open] .lh-chevron__line-left { | |
transform: rotate(calc(var(--chevron-angle) * -1)); | |
} | |
.lh-audit-group[open] > .lh-audit-group__summary > .lh-chevron .lh-chevron__line-right, | |
.lh-audit > .lh-expandable-details[open] .lh-chevron__line-right { | |
transform: rotate(var(--chevron-angle)); | |
} | |
.lh-audit-group[open] > .lh-audit-group__summary > .lh-chevron .lh-chevron__lines, | |
.lh-audit > .lh-expandable-details[open] .lh-chevron__lines { | |
transform: translateY(calc(var(--chevron-size) * -1)); | |
} | |
/* Tooltip */ | |
.tooltip-boundary { | |
position: relative; | |
} | |
.tooltip { | |
position: absolute; | |
display: none; /* Don't retain these layers when not needed */ | |
opacity: 0; | |
background: #ffffff; | |
min-width: 246px; | |
max-width: 275px; | |
padding: 15px; | |
border-radius: 5px; | |
text-align: initial; | |
} | |
/* shrink tooltips to not be cutoff on left edge of narrow viewports | |
45vw is chosen to be ~= width of the left column of metrics | |
*/ | |
@media screen and (max-width: 535px) { | |
.tooltip { | |
min-width: 45vw; | |
padding: 3vw; | |
} | |
} | |
.tooltip-boundary:hover { | |
background-color: #F8F9FA; | |
} | |
.tooltip-boundary:hover .tooltip { | |
display: block; | |
animation: fadeInTooltip 250ms; | |
animation-fill-mode: forwards; | |
animation-delay: 850ms; | |
bottom: 100%; | |
z-index: 1; | |
will-change: opacity; | |
right: 0; | |
} | |
.tooltip::before { | |
content: ""; | |
border: solid transparent; | |
border-bottom-color: #fff; | |
border-width: 10px; | |
position: absolute; | |
bottom: -20px; | |
right: 6px; | |
transform: rotate(180deg); | |
pointer-events: none; | |
} | |
@keyframes fadeInTooltip { | |
0% { opacity: 0; } | |
75% { opacity: 1; } | |
100% { opacity: 1; filter: drop-shadow(1px 0px 1px #aaa) drop-shadow(0px 2px 4px hsla(206, 6%, 25%, 0.15)); } | |
} | |
</style> | |
</head> | |
<body class="lh-root lh-vars"> | |
<noscript>Lighthouse report requires JavaScript. Please enable.</noscript> | |
<div hidden><!-- | |
@license | |
Copyright 2018 Google Inc. All Rights Reserved. | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS-IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
--> | |
<!-- Lighthouse run warnings --> | |
<template id="tmpl-lh-warnings--toplevel"> | |
<div class="lh-warnings lh-warnings--toplevel"> | |
<strong class="lh-warnings__msg"></strong> | |
<ul></ul> | |
</div> | |
</template> | |
<!-- Lighthouse score scale --> | |
<template id="tmpl-lh-scorescale"> | |
<div class="lh-scorescale"> | |
<span class="lh-scorescale-label"></span> | |
<span class="lh-scorescale-range lh-scorescale-range--fail">0-49</span> | |
<span class="lh-scorescale-range lh-scorescale-range--average">50-89</span> | |
<span class="lh-scorescale-range lh-scorescale-range--pass">90-100</span> | |
</div> | |
</template> | |
<!-- Toggle arrow chevron --> | |
<template id="tmpl-lh-chevron"> | |
<svg class="lh-chevron" title="See audits" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100"> | |
<g class="lh-chevron__lines"> | |
<path class="lh-chevron__line lh-chevron__line-left" d="M10 50h40" stroke="#707173"/> | |
<path class="lh-chevron__line lh-chevron__line-right" d="M90 50H50" stroke="#707173"/> | |
</g> | |
</svg> | |
</template> | |
<!-- Lighthouse category header --> | |
<template id="tmpl-lh-category-header"> | |
<div class="lh-category-header"> | |
<div class="lh-score__gauge"></div> | |
<span class="lh-category-header__title"></span> | |
<div class="lh-category-header__description"></div> | |
</div> | |
</template> | |
<!-- Lighthouse audit --> | |
<template id="tmpl-lh-audit"> | |
<div class="lh-audit"> | |
<details class="lh-expandable-details"> | |
<summary class="lh-audit__header lh-expandable-details__summary"> | |
<span class="lh-audit__index"></span> | |
<span class="lh-audit__title"></span> | |
<span class="lh-audit__display-text"></span> | |
<div class="lh-audit__score-icon"></div> | |
<div class="lh-chevron-container"></div> | |
</summary> | |
<div class="lh-audit__description"></div> | |
</details> | |
</div> | |
</template> | |
<!-- Lighthouse perf metric --> | |
<template id="tmpl-lh-metric"> | |
<div class="lh-metric"> | |
<div class="lh-metric__innerwrap tooltip-boundary"> | |
<span class="lh-metric__title"></span> | |
<div class="lh-metric__value"></div> | |
<div class="lh-metric__description tooltip"></div> | |
</div> | |
</div> | |
</template> | |
<!-- Lighthouse perf opportunity --> | |
<template id="tmpl-lh-opportunity"> | |
<div class="lh-audit lh-audit--load-opportunity"> | |
<details class="lh-expandable-details"> | |
<summary class="lh-audit__header lh-expandable-details__summary"> | |
<div class="lh-load-opportunity__cols"> | |
<div class="lh-load-opportunity__col lh-load-opportunity__col--one"> | |
<span class="lh-audit__index"></span> | |
<div class="lh-audit__title"></div> | |
</div> | |
<div class="lh-load-opportunity__col lh-load-opportunity__col--two"> | |
<div class="lh-load-opportunity__sparkline"> | |
<div class="lh-sparkline"><div class="lh-sparkline__bar"></div></div> | |
</div> | |
<div class="lh-audit__display-text"></div> | |
<div class="lh-chevron-container" title="See resources"></div> | |
</div> | |
</div> | |
</summary> | |
<div class="lh-audit__description"></div> | |
</details> | |
</div> | |
</template> | |
<!-- Lighthouse perf opportunity header --> | |
<template id="tmpl-lh-opportunity-header"> | |
<div class="lh-load-opportunity__header lh-load-opportunity__cols"> | |
<div class="lh-load-opportunity__col lh-load-opportunity__col--one"></div> | |
<div class="lh-load-opportunity__col lh-load-opportunity__col--two"></div> | |
</div> | |
</template> | |
<!-- Lighthouse score container --> | |
<template id="tmpl-lh-scores-wrapper"> | |
<style> | |
.lh-scores-wrapper__background, | |
.lh-scores-wrapper__shadow { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: white; | |
border-radius: 8px; | |
} | |
.lh-scores-wrapper__shadow { | |
border-radius: 0; | |
box-shadow: rgba(0, 0, 0, 0.2) 0px 3px 0px -2px | |
} | |
.lh-scores-container { | |
padding-bottom: calc(var(--section-indent) / 2); | |
position: relative; | |
width: 100%; | |
} | |
</style> | |
<div class="lh-scores-wrapper"> | |
<div class="lh-scores-container"> | |
<div class="lh-scores-wrapper__background"></div> | |
<div class="lh-scores-wrapper__shadow"></div> | |
</div> | |
</div> | |
</template> | |
<!-- Lighthouse header --> | |
<template id="tmpl-lh-heading"> | |
<style> | |
:root { | |
--report-header-overlap-top: 30px; | |
} | |
.lh-header-bg { | |
background-color: var(--header-bg-color); | |
height: var(--report-header-height); | |
left: 0; | |
position: absolute; | |
top: 0; | |
width: 100%; | |
will-change: transform; | |
} | |
.lh-lighthouse { | |
position: absolute; | |
top: var(--report-header-height); | |
right: 50%; | |
transform: translate3d(calc(var(--report-width) / 2), -100%, 0); | |
opacity: 1; | |
transform-origin: bottom right; | |
will-change: transform, opacity; | |
} | |
.lh-header { | |
width: 100%; | |
height: var(--report-header-height); | |
max-width: 100%; /* support text-overflow on url */ | |
position: relative; | |
} | |
.lh-metadata { | |
flex: 1 1 0; | |
padding: calc(var(--section-padding) / 2); | |
padding-left: var(--section-indent); | |
line-height: 20px; | |
color: var(--report-header-color); | |
z-index: 1; | |
position: relative; | |
} | |
.lh-metadata__results { | |
text-overflow: ellipsis; | |
white-space: nowrap; | |
} | |
.lh-metadata__url { | |
color: currentColor; | |
} | |
.lh-scores-wrapper { | |
margin-top: -30px; | |
transform: translateZ(1px); | |
} | |
.lh-scores-wrapper__shadow { | |
opacity: 0; | |
} | |
.lh-scores-wrapper__background, | |
.lh-scores-wrapper__shadow { | |
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.1); | |
border-radius: 8px; | |
will-change: opacity, transform; | |
transform-origin: top; | |
} | |
.lh-product-info, .lh-toolbar__metadata { | |
align-items: center; | |
white-space: nowrap; | |
color: #5F6369; | |
display: flex; | |
font-size: calc(var(--body-font-size) * 0.9); | |
margin-left: var(--section-indent); | |
opacity: 0; | |
transform: translateY(-50%); | |
will-change: opacity; | |
} | |
.lh-product-info__icon { | |
height: 20px; | |
margin-right: var(--default-padding); | |
} | |
.lh-toolbar { | |
height: 50px; | |
position: absolute; | |
top: 25px; | |
will-change: transform; | |
display: flex; | |
width: calc(100% - 70px); /* give room for export */ | |
} | |
.lh-toolbar__metadata { | |
overflow: hidden; | |
text-overflow: ellipsis; | |
width: 100%; | |
} | |
.lh-toolbar__url { | |
color: currentColor; | |
display: block; | |
white-space: nowrap; | |
margin-right: 2px; | |
} | |
.lh-export { | |
position: absolute; | |
right: var(--section-indent); | |
transform: translateY(0); | |
top: calc(var(--section-padding) / 2); | |
will-change: transform; | |
z-index: 2; | |
} | |
.lh-export__button { | |
background-color: #fff; | |
border: 1px solid #dadada; | |
border-radius: 2px; | |
cursor: pointer; | |
outline: none; | |
height: 32px; | |
width: 48px; | |
background-repeat: no-repeat; | |
background-size: 20px; | |
background-position: 50% 50%; | |
will-change: transform; | |
} | |
.lh-export__button:focus, | |
.lh-export__button.active { | |
box-shadow: 1px 1px 3px #ccc; | |
} | |
.lh-export__button.active + .lh-export__dropdown { | |
opacity: 1; | |
clip: rect(0, 164px, 200px, 0); | |
} | |
.lh-export__dropdown { | |
position: absolute; | |
background-color: #fff; | |
border: 1px solid var(--report-border-color); | |
border-radius: 3px; | |
padding: calc(var(--default-padding) / 2) 0; | |
cursor: pointer; | |
top: 36px; | |
right: 0; | |
box-shadow: 1px 1px 3px #ccc; | |
min-width: 125px; | |
clip: rect(0, 164px, 0, 0); | |
opacity: 0; | |
transition: all 200ms cubic-bezier(0,0,0.2,1); | |
} | |
.lh-export__dropdown a { | |
display: block; | |
color: currentColor; | |
text-decoration: none; | |
white-space: nowrap; | |
padding: 0 12px; | |
line-height: 2; | |
} | |
.lh-export__dropdown a:hover, | |
.lh-export__dropdown a:focus { | |
background-color: #efefef; | |
outline: none; | |
} | |
.lh-export__dropdown .report-icon { | |
cursor: pointer; | |
background-repeat: no-repeat; | |
background-position: 8px 50%; | |
background-size: 18px; | |
background-color: transparent; | |
text-indent: 18px; | |
} | |
/* copy icon needs slight adjustments to look great */ | |
.lh-export__dropdown .report-icon--copy { | |
background-size: 16px; | |
background-position: 9px 50%; | |
} | |
/* save-as-gist option hidden in report */ | |
.lh-export__dropdown .lh-export--gist { | |
display: none; | |
} | |
.lh-config { | |
color: var(--secondary-text-color); | |
} | |
.lh-config__timestamp { | |
font-size: var(--caption-font-size); | |
display: block; | |
} | |
a.lh-config__emulation { | |
color: inherit; | |
text-decoration: none; | |
} | |
@media screen and (max-width: 964px) { | |
.lh-export__dropdown { | |
right: 0; | |
left: initial; | |
} | |
} | |
@media print { | |
.lh-header { | |
position: static; | |
margin-left: 0; | |
} | |
} | |
/* | |
TODO: Enable animating the clouds | |
.lh-lighthouse__clouds { | |
animation: panacross 30s linear infinite; | |
animation-play-state: paused; | |
} | |
@keyframes panacross { | |
0% { transform: translateX(0px); } | |
77% { transform: translateX(-680px); } | |
77.0001% { transform: translateX(195px); } | |
100% { transform: translateX(0px); } | |
} */ | |
</style> | |
<div class="lh-header-bg"></div> | |
<div class="lh-lighthouse"> | |
<svg width="217" height="148" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | |
<defs> | |
<mask id="a" x="-56" y="-54" width="284" height="202" maskUnits="userSpaceOnUse"> | |
<path d="M-56-54h284v202H-56z" fill="#fff"/> | |
</mask> | |
<linearGradient id="b" x1="-525.16" y1="560.08" x2="-524.23" y2="560.08" gradientTransform="matrix(91 0 0 -77 47797 43181)" gradientUnits="userSpaceOnUse"> | |
<stop offset="0" stop-color="#f1f3f4"/> | |
<stop offset="1" stop-color="#fff"/> | |
</linearGradient> | |
</defs> | |
<g mask="url(#a)"> | |
<path d="M95 47h24v2H95z" fill="#ec5548"/> | |
<path d="M98 49h18v11H98z" fill="#fbc21b"/> | |
<path d="M95 59h24v7H95z" fill="#ec5548"/> | |
<path d="M97.63 66h19.74l2.63 47H95z" fill="#fff"/> | |
<path d="M107 38a10 10 0 0 1 10 10v1H97v-1a10 10 0 0 1 10-10zM96.77 82.23l21-10.7.63 11.87-22.31 11.87zM95 110.8L119.1 98l.9 14H95z" fill="#ec5548"/> | |
<path d="M0 148a177.58 177.58 0 0 1 217 0z" fill="#e8eaed"/> | |
<path d="M103 49a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z" fill="#fef0c8"/> | |
<path d="M7 16l91 33.18v10L7 93z" fill="url(#b)"/> | |
</g> | |
<g mask="url(#a)" class="lh-lighthouse__clouds"> | |
<path d="M60 .19A9.77 9.77 0 0 1 61.93 0a9.44 9.44 0 0 1 9.24 7.83A7.24 7.24 0 0 1 79 14.45v.73A7.37 7.37 0 0 1 76.2 21h-31a7.44 7.44 0 0 1-1.2-4.09 7.31 7.31 0 0 1 7.26-7.36 6.84 6.84 0 0 1 1.28.1v-.11A9.51 9.51 0 0 1 60 .19m79.78 22.31h-17.9a4.37 4.37 0 0 1-.63-2.25 4.2 4.2 0 0 1 4.16-4.25 4.37 4.37 0 0 1 .72.06V16a5.35 5.35 0 0 1 10.64-1h.33a4.2 4.2 0 0 1 4.15 4.25 4.29 4.29 0 0 1-1.47 3.25zM163 62h-24.15a5.1 5.1 0 0 1-.85-2.81 5.65 5.65 0 0 1 6.59-5.19v-.08a7.07 7.07 0 0 1 7.24-6.92 7.15 7.15 0 0 1 7.17 5.64h.44a5.46 5.46 0 0 1 5.6 5.32A5.19 5.19 0 0 1 163 62z" fill="#fff"/> | |
</g> | |
</svg> | |
</div> | |
<div class="lh-header-container"> | |
<div class="lh-header"> | |
<div class="lh-metadata"> | |
<div class="lh-metadata__results"><a href="" class="lh-metadata__url" target="_blank" rel="noopener"></a></div> | |
<div class="lh-config"> | |
<span class="lh-config__timestamp"></span> | |
<a href="#runtime-settings" class="lh-config__emulation"></a> | |
</div> | |
</div> | |
</div> | |
<div class="lh-scores-wrapper-placeholder"></div> | |
<div class="lh-toolbar"> | |
<div class="lh-product-info"> | |
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAADjklEQVR4AWI08P/HQEvAQrxSQKvlECfLFYXx75xCY2qmh89GbNvOMjb3v9jOOlxnFWxj206ebQ3b7q6q+z1rNagu8/zvPSZACAABpeUAA0miMgU7SA7JjCraFGwZwECOwvL75dWjsKgWBKtx0jvWo+vkBAFbACCkByMP6nMn48+AVgXB2fzSCwsv22/lMGlUhmJ0AE7BH8dyUUDbUEgN6RzJRSeaPxhdRYR0Inel+7Hd5lBiFpkMAxACc0394//9C4voFHDiAAGLpuOXebdfdHfctgwJKaZRLRKy6ItrSis6RBnVBgGtbHyKTEmJHQoEXoBCE5BCrDeA2ogMUIGDAKEBDEhUqwgMqBYDjW4DQzmuffVdqff42/ZQYYqVcMXGZsMPyCsH3lyJSetxvEaxAQXdjR1HjfwCdIS7lo2DZke26Qe+MXO12OWkGT0O6oE7vMGkMnkYw4aN1KQgMKExhXqswfiov4+a7MQ11XPnbr/5qpKlgACAAQj94Lu271bN9DUecQasIZlNzG72llRAAKJiAi+/BSHrSFjRvQhg3DEKEqJh08tsmLTx597+f6enr4cc2Zpk57pihfX24dW7RHcOLLUbJYhJSl0ErQCI9BVXH/XrO97QasuvQQSiECa0BrQCIIJp6X9T/r8QG6L71WYSqCoIIGo2BZDUBnS/D9EA9Nun1iYvbM0MFExIDQRoKFatc1Z6zrm5uWeObJotq0BGV9FuQBWq5a4Fw3PPz848rZHstZSuA5FWAFSMP2nOppOOGpl6qh9PCSg0IFyHKjSQyDNQHTru2t75NOEe0fsf246oAmFkI6vCdnWvbQFQFCKx8vCswV8TrDLiDLgH4Nr7RAtNsrC9d8sfk7b8ls4igdNy8CQKAISlsB0FjZfd3Lfp155tf8fKI4BxZZIj/oTdVEAIAcJFOCmzauHG71I7/rdreUAgAqpDP05fDARCAQQARwEIBQSVxq0FyaLvZZtevpHa8WHw8cft6cpxlq8eAJtIhnSbWDf951yx3y13OqUuu5qyGgkxCgGFh9cDihDGbTa6BqvT1lWmrav3bmt2ZMJ4mU6TGgIC4DBzcv/JqAau1WhzSt3x9Ixk/4Jk/8J4ZrrViFMA4W6A7+WK8xcVjvyrOmVD0FbAXokcT48r+xVqLKvuJYbmpNadnlp3mpufJHOe/GXktM+r09bT8kEdq9BRYAbGSgzP7ll82U71Mc+ZFooXgwAAAABJRU5ErkJggg==" alt="" class="lh-product-info__icon" /> | |
<span class="lh-product-info__name">Lighthouse</span> | |
<span class="lh-product-info__version"></span> | |
</div> | |
<div class="lh-toolbar__metadata"> | |
<a href="" class="lh-toolbar__url" target="_blank" rel="noopener"></a> | |
<span class="lh-toggle-arrow" title="See report's runtime settings"></span> | |
</div> | |
</div> | |
<div class="lh-export"> | |
<button class="report-icon report-icon--share lh-export__button" title="Export report"></button> | |
<div class="lh-export__dropdown"> | |
<!-- TODO(i18n): localize export dropdown --> | |
<a href="#" class="report-icon report-icon--print" data-action="print-summary">Print Summary</a> | |
<a href="#" class="report-icon report-icon--print" data-action="print-expanded">Print Expanded</a> | |
<a href="#" class="report-icon report-icon--copy" data-action="copy">Copy JSON</a> | |
<a href="#" class="report-icon report-icon--download" data-action="save-html">Save as HTML</a> | |
<a href="#" class="report-icon report-icon--download" data-action="save-json">Save as JSON</a> | |
<a href="#" class="report-icon report-icon--open lh-export--viewer" data-action="open-viewer">Open in Viewer</a> | |
<a href="#" class="report-icon report-icon--open lh-export--gist" data-action="save-gist">Save as Gist</a> | |
</div> | |
</div> | |
</template> | |
<!-- Lighthouse footer --> | |
<template id="tmpl-lh-footer"> | |
<style> | |
.lh-footer { | |
background-color: var(--header-bg-color); | |
border-top: 1px solid var(--report-secondary-border-color); | |
padding: var(--section-indent) calc(var(--default-padding) * 2); | |
} | |
.lh-footer .lh-generated { | |
text-align: center; | |
border-top: 1px solid var(--report-border-color); | |
padding-top: var(--default-padding); | |
} | |
.lh-env { | |
padding: var(--default-padding) 0; | |
} | |
.lh-env__items { | |
padding-left: 16px; | |
} | |
span.lh-env__name { | |
font-weight: bold; | |
color: var(--secondary-text-color); | |
} | |
span.lh-env__description { | |
font-family: var(--monospace-font-family); | |
font-size: var(--caption-font-size); | |
padding-left: 5px; | |
} | |
</style> | |
<footer class="lh-footer"> | |
<!-- TODO(i18n): localize runtime settings --> | |
<div class="lh-env"> | |
<div class="lh-env__title">Runtime settings</div> | |
<ul class="lh-env__items"> | |
<template id="tmpl-lh-env__items"> | |
<li class="lh-env__item"> | |
<span class="lh-env__name"></span> | |
<span class="lh-env__description"></span> | |
</li> | |
</template> | |
</ul> | |
</div> | |
<div class="lh-generated"> | |
Generated by <b>Lighthouse</b> <span class="lh-footer__version"></span> | | |
<a href="https://github.com/GoogleChrome/Lighthouse/issues" target="_blank" rel="noopener">File an issue</a> | |
</div> | |
</footer> | |
</template> | |
<!-- Lighthouse score gauge --> | |
<template id="tmpl-lh-gauge"> | |
<style> | |
.lh-gauge__wrapper { | |
--circle-size: calc(3 * var(--header-font-size)); | |
--circle-size-half: calc(var(--circle-size) / 2); | |
--circle-background: hsl(216, 12%, 92%); | |
--circle-border-width: 9; | |
--inset-size: calc(var(--circle-size) - 2 * var(--circle-border-width)); | |
--transition-length: 1s; | |
} | |
.lh-gauge__wrapper--pass, | |
.lh-gauge__wrapper--pass .lh-gauge { | |
--circle-color: var(--pass-color); | |
color: var(--circle-color); | |
} | |
.lh-gauge__wrapper--average, | |
.lh-gauge__wrapper--average .lh-gauge { | |
--circle-color: var(--average-color); | |
color: var(--circle-color); | |
} | |
.lh-gauge__wrapper--fail, | |
.lh-gauge__wrapper--fail .lh-gauge { | |
--circle-color: var(--fail-color); | |
color: var(--circle-color); | |
} | |
.lh-gauge { | |
max-width: 360px; | |
max-height: 360px; | |
stroke-linecap: round; | |
width: var(--circle-size); | |
height: var(--circle-size); | |
} | |
.lh-gauge-base { | |
fill: none; | |
stroke: var(--circle-background); | |
stroke-width: var(--circle-border-width); | |
} | |
.lh-gauge-arc { | |
fill: none; | |
stroke: var(--circle-color); | |
stroke-width: var(--circle-border-width); | |
animation: load-gauge var(--transition-length) ease forwards; | |
animation-delay: 250ms; | |
} | |
@keyframes load-gauge { | |
from { stroke-dasharray: 0 329; } | |
} | |
.lh-gauge__percentage { | |
--spacer: calc((var(--circle-size) - var(--inset-size)) / 2); | |
width: 100%; | |
height: var(--inset-size); | |
position: absolute; | |
border-radius: inherit; | |
font-size: var(--header-font-size); | |
line-height: var(--header-font-size); | |
text-align: center; | |
top: calc(var(--circle-size) / 3); | |
} | |
.lh-gauge__wrapper { | |
display: inline-flex; | |
align-items: center; | |
flex-direction: column; | |
text-decoration: none; | |
flex: 1; | |
min-width: auto; | |
position: relative; | |
/* Contain the layout style paint & layers during animation*/ | |
contain: content; | |
will-change: opacity; /* Only using for layer promotion */ | |
} | |
.lh-gauge__label { | |
font-size: var(--body-font-size); | |
line-height: var(--body-line-height); | |
margin-top: calc(0.5 * var(--body-line-height)); | |
text-align: center; | |
color: black; | |
} | |
</style> | |
<a href="#" class="lh-gauge__wrapper"> | |
<svg viewBox="0 0 120 120" class="lh-gauge" fill="none" stroke-width="2"> | |
<circle class="lh-gauge-base" r="53" cx="60" cy="60"></circle> | |
<circle class="lh-gauge-arc" transform="rotate(-90 60 60)" stroke-dasharray="0 329" stroke-dashoffset="0" r="53" cx="60" cy="60"></circle> | |
</svg> | |
<div class="lh-gauge__percentage"></div> | |
<div class="lh-gauge__label"></div> | |
</a> | |
</template> | |
<!-- Lighthouse crtiical request chains component --> | |
<template id="tmpl-lh-crc"> | |
<div class="lh-crc-container"> | |
<style> | |
.lh-crc .tree-marker { | |
width: 12px; | |
height: 26px; | |
display: block; | |
float: left; | |
background-position: top left; | |
} | |
.lh-crc .horiz-down { | |
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><g fill="%23D8D8D8" fill-rule="evenodd"><path d="M16 12v2H-2v-2z"/><path d="M9 12v14H7V12z"/></g></svg>'); | |
} | |
.lh-crc .right { | |
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M16 12v2H0v-2z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>'); | |
} | |
.lh-crc .up-right { | |
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M7 0h2v14H7zm2 12h7v2H9z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>'); | |
} | |
.lh-crc .vert-right { | |
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M7 0h2v27H7zm2 12h7v2H9z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>'); | |
} | |
.lh-crc .vert { | |
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M7 0h2v26H7z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>'); | |
} | |
.lh-crc .crc-tree { | |
font-size: 14px; | |
width: 100%; | |
overflow-x: auto; | |
} | |
.lh-crc .crc-node { | |
height: 26px; | |
line-height: 26px; | |
white-space: nowrap; | |
} | |
.lh-crc .crc-node__tree-value { | |
margin-left: 10px; | |
} | |
.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; | |
} | |
.lh-crc__summary-value { | |
margin-bottom: 10px; | |
} | |
</style> | |
<div> | |
<div class="lh-crc__summary-value"> | |
<span class="lh-crc__longest_duration_label"></span> <b class="lh-crc__longest_duration"></b> | |
</div> | |
</div> | |
<div class="lh-crc"> | |
<div class="crc-initial-nav"></div> | |
<!-- stamp for each chain --> | |
<template id="tmpl-lh-crc__chains"> | |
<div class="crc-node"> | |
<span class="crc-node__tree-marker"> | |
</span> | |
<span class="crc-node__tree-value"> | |
<span class="crc-node__tree-file"><!-- fill me: node.request.url.file --></span> | |
<span class="crc-node__tree-hostname">(<!-- fill me: node.request.url.host -->)</span> | |
</span> | |
</div> | |
</template> | |
</div> | |
</div> | |
</template> | |
</div> | |
<main><!-- report populated here --></main> | |
<div id="lh-log"></div> | |
<script>/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/* globals self URL */ | |
const ELLIPSIS = '\u2026'; | |
const NBSP = '\xa0'; | |
const PASS_THRESHOLD = 0.9; | |
const RATINGS = { | |
PASS: {label: 'pass', minScore: PASS_THRESHOLD}, | |
AVERAGE: {label: 'average', minScore: 0.5}, | |
FAIL: {label: 'fail'}, | |
ERROR: {label: 'error'}, | |
}; | |
class Util { | |
static get PASS_THRESHOLD() { | |
return PASS_THRESHOLD; | |
} | |
static get MS_DISPLAY_VALUE() { | |
return `%10d${NBSP}ms`; | |
} | |
/** | |
* Returns a new LHR that's reshaped for slightly better ergonomics within the report rendereer. | |
* Also, sets up the localized UI strings used within renderer and number/date formatting | |
* The LHR passed in is not mutated. | |
* TODO(team): we all agree the LHR shape change is technical debt we should fix | |
* @param {LH.Result} result | |
* @return {LH.ReportResult} | |
*/ | |
static prepareReportResult(result) { | |
// If any mutations happen to the report within the renderers, we want the original object untouched | |
const clone = /** @type {LH.ReportResult} */ (JSON.parse(JSON.stringify(result))); | |
// If LHR is older (≤3.0.3), it has no locale setting. Set default. | |
if (!clone.configSettings.locale) { | |
clone.configSettings.locale = 'en'; | |
} | |
Util.setNumberDateLocale(clone.configSettings.locale); | |
if (clone.i18n && clone.i18n.rendererFormattedStrings) { | |
Util.updateAllUIStrings(clone.i18n.rendererFormattedStrings); | |
} | |
if (typeof clone.categories !== 'object') throw new Error('No categories provided.'); | |
clone.reportCategories = Object.values(clone.categories); | |
// For convenience, smoosh all AuditResults into their auditDfn (which has just weight & group) | |
for (const category of clone.reportCategories) { | |
category.auditRefs.forEach(auditMeta => { | |
const result = clone.audits[auditMeta.id]; | |
auditMeta.result = result; | |
}); | |
} | |
return clone; | |
} | |
/** | |
* @param {LH.I18NRendererStrings} rendererFormattedStrings | |
*/ | |
static updateAllUIStrings(rendererFormattedStrings) { | |
// TODO(i18n): don't mutate these here but on the LHR and pass that around everywhere | |
for (const [key, value] of Object.entries(rendererFormattedStrings)) { | |
Util.UIStrings[key] = value; | |
} | |
} | |
/** | |
* @param {string|Array<string|number>=} displayValue | |
* @return {string} | |
*/ | |
static formatDisplayValue(displayValue) { | |
if (typeof displayValue === 'string') return displayValue; | |
if (!displayValue) return ''; | |
const replacementRegex = /%([0-9]*(\.[0-9]+)?d|s)/; | |
const template = /** @type {string} */ (displayValue[0]); | |
if (typeof template !== 'string') { | |
// First value should always be the format string, but we don't want to fail to build | |
// a report, return a placeholder. | |
return 'UNKNOWN'; | |
} | |
let output = template; | |
for (const replacement of displayValue.slice(1)) { | |
if (!replacementRegex.test(output)) { | |
// eslint-disable-next-line no-console | |
console.warn('Too many replacements given'); | |
break; | |
} | |
output = output.replace(replacementRegex, match => { | |
const granularity = Number(match.match(/[0-9.]+/)) || 1; | |
return match === '%s' ? | |
replacement.toLocaleString() : | |
(Math.round(Number(replacement) / granularity) * granularity).toLocaleString(); | |
}); | |
} | |
if (replacementRegex.test(output)) { | |
// eslint-disable-next-line no-console | |
console.warn('Not enough replacements given'); | |
} | |
return output; | |
} | |
/** | |
* Used to determine if the "passed" for the purposes of showing up in the "failed" or "passed" | |
* sections of the report. | |
* | |
* @param {{score: (number|null), scoreDisplayMode: string}} audit | |
* @return {boolean} | |
*/ | |
static showAsPassed(audit) { | |
switch (audit.scoreDisplayMode) { | |
case 'manual': | |
case 'not-applicable': | |
return true; | |
case 'error': | |
case 'informative': | |
return false; | |
case 'numeric': | |
case 'binary': | |
default: | |
return Number(audit.score) >= RATINGS.PASS.minScore; | |
} | |
} | |
/** | |
* Convert a score to a rating label. | |
* @param {number|null} score | |
* @param {string=} scoreDisplayMode | |
* @return {string} | |
*/ | |
static calculateRating(score, scoreDisplayMode) { | |
// Handle edge cases first, manual and not applicable receive 'pass', errored audits receive 'error' | |
if (scoreDisplayMode === 'manual' || scoreDisplayMode === 'not-applicable') { | |
return RATINGS.PASS.label; | |
} else if (scoreDisplayMode === 'error') { | |
return RATINGS.ERROR.label; | |
} else if (score === null) { | |
return RATINGS.FAIL.label; | |
} | |
// At this point, we're rating a standard binary/numeric audit | |
let rating = RATINGS.FAIL.label; | |
if (score >= RATINGS.PASS.minScore) { | |
rating = RATINGS.PASS.label; | |
} else if (score >= RATINGS.AVERAGE.minScore) { | |
rating = RATINGS.AVERAGE.label; | |
} | |
return rating; | |
} | |
/** | |
* Format number. | |
* @param {number} number | |
* @param {number=} granularity Number of decimal places to include. Defaults to 0.1. | |
* @return {string} | |
*/ | |
static formatNumber(number, granularity = 0.1) { | |
const coarseValue = Math.round(number / granularity) * granularity; | |
return coarseValue.toLocaleString(Util.numberDateLocale); | |
} | |
/** | |
* @param {number} size | |
* @param {number=} granularity Controls how coarse the displayed value is, defaults to .01 | |
* @return {string} | |
*/ | |
static formatBytesToKB(size, granularity = 0.1) { | |
const kbs = (Math.round(size / 1024 / granularity) * granularity) | |
.toLocaleString(Util.numberDateLocale); | |
return `${kbs}${NBSP}KB`; | |
} | |
/** | |
* @param {number} ms | |
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 10 | |
* @return {string} | |
*/ | |
static formatMilliseconds(ms, granularity = 10) { | |
const coarseTime = Math.round(ms / granularity) * granularity; | |
return `${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}ms`; | |
} | |
/** | |
* @param {number} ms | |
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 0.1 | |
* @return {string} | |
*/ | |
static formatSeconds(ms, granularity = 0.1) { | |
const coarseTime = Math.round(ms / 1000 / granularity) * granularity; | |
return `${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}s`; | |
} | |
/** | |
* Format time. | |
* @param {string} date | |
* @return {string} | |
*/ | |
static formatDateTime(date) { | |
/** @type {Intl.DateTimeFormatOptions} */ | |
const options = { | |
month: 'short', day: 'numeric', year: 'numeric', | |
hour: 'numeric', minute: 'numeric', timeZoneName: 'short', | |
}; | |
let formatter = new Intl.DateTimeFormat(Util.numberDateLocale, options); | |
// Force UTC if runtime timezone could not be detected. | |
// See https://github.com/GoogleChrome/lighthouse/issues/1056 | |
const tz = formatter.resolvedOptions().timeZone; | |
if (!tz || tz.toLowerCase() === 'etc/unknown') { | |
options.timeZone = 'UTC'; | |
formatter = new Intl.DateTimeFormat(Util.numberDateLocale, options); | |
} | |
return formatter.format(new Date(date)); | |
} | |
/** | |
* Converts a time in milliseconds into a duration string, i.e. `1d 2h 13m 52s` | |
* @param {number} timeInMilliseconds | |
* @return {string} | |
*/ | |
static formatDuration(timeInMilliseconds) { | |
let timeInSeconds = timeInMilliseconds / 1000; | |
if (Math.round(timeInSeconds) === 0) { | |
return 'None'; | |
} | |
/** @type {Array<string>} */ | |
const parts = []; | |
const unitLabels = /** @type {Object<string, number>} */ ({ | |
d: 60 * 60 * 24, | |
h: 60 * 60, | |
m: 60, | |
s: 1, | |
}); | |
Object.keys(unitLabels).forEach(label => { | |
const unit = unitLabels[label]; | |
const numberOfUnits = Math.floor(timeInSeconds / unit); | |
if (numberOfUnits > 0) { | |
timeInSeconds -= numberOfUnits * unit; | |
parts.push(`${numberOfUnits}\xa0${label}`); | |
} | |
}); | |
return parts.join(' '); | |
} | |
/** | |
* @param {URL} parsedUrl | |
* @param {{numPathParts?: number, preserveQuery?: boolean, preserveHost?: boolean}=} options | |
* @return {string} | |
*/ | |
static getURLDisplayName(parsedUrl, options) { | |
// Closure optional properties aren't optional in tsc, so fallback needs undefined values. | |
options = options || {numPathParts: undefined, preserveQuery: undefined, | |
preserveHost: undefined}; | |
const numPathParts = options.numPathParts !== undefined ? options.numPathParts : 2; | |
const preserveQuery = options.preserveQuery !== undefined ? options.preserveQuery : true; | |
const preserveHost = options.preserveHost || false; | |
let name; | |
if (parsedUrl.protocol === 'about:' || parsedUrl.protocol === 'data:') { | |
// Handle 'about:*' and 'data:*' URLs specially since they have no path. | |
name = parsedUrl.href; | |
} else { | |
name = parsedUrl.pathname; | |
const parts = name.split('/').filter(part => part.length); | |
if (numPathParts && parts.length > numPathParts) { | |
name = ELLIPSIS + parts.slice(-1 * numPathParts).join('/'); | |
} | |
if (preserveHost) { | |
name = `${parsedUrl.host}/${name.replace(/^\//, '')}`; | |
} | |
if (preserveQuery) { | |
name = `${name}${parsedUrl.search}`; | |
} | |
} | |
const MAX_LENGTH = 64; | |
// Always elide hexadecimal hash | |
name = name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g, `$1${ELLIPSIS}`); | |
// Also elide other hash-like mixed-case strings | |
name = name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g, | |
`$1${ELLIPSIS}`); | |
// Also elide long number sequences | |
name = name.replace(/(\d{3})\d{6,}/g, `$1${ELLIPSIS}`); | |
// Merge any adjacent ellipses | |
name = name.replace(/\u2026+/g, ELLIPSIS); | |
// Elide query params first | |
if (name.length > MAX_LENGTH && name.includes('?')) { | |
// Try to leave the first query parameter intact | |
name = name.replace(/\?([^=]*)(=)?.*/, `?$1$2${ELLIPSIS}`); | |
// Remove it all if it's still too long | |
if (name.length > MAX_LENGTH) { | |
name = name.replace(/\?.*/, `?${ELLIPSIS}`); | |
} | |
} | |
// Elide too long names next | |
if (name.length > MAX_LENGTH) { | |
const dotIndex = name.lastIndexOf('.'); | |
if (dotIndex >= 0) { | |
name = name.slice(0, MAX_LENGTH - 1 - (name.length - dotIndex)) + | |
// Show file extension | |
`${ELLIPSIS}${name.slice(dotIndex)}`; | |
} else { | |
name = name.slice(0, MAX_LENGTH - 1) + ELLIPSIS; | |
} | |
} | |
return name; | |
} | |
/** | |
* Split a URL into a file, hostname and origin for easy display. | |
* @param {string} url | |
* @return {{file: string, hostname: string, origin: string}} | |
*/ | |
static parseURL(url) { | |
const parsedUrl = new URL(url); | |
return { | |
file: Util.getURLDisplayName(parsedUrl), | |
hostname: parsedUrl.hostname, | |
origin: parsedUrl.origin, | |
}; | |
} | |
/** | |
* @param {LH.Config.Settings} settings | |
* @return {Array<{name: string, description: string}>} | |
*/ | |
static getEnvironmentDisplayValues(settings) { | |
const emulationDesc = Util.getEmulationDescriptions(settings); | |
return [ | |
{ | |
name: 'Device', | |
description: emulationDesc.deviceEmulation, | |
}, | |
{ | |
name: 'Network throttling', | |
description: emulationDesc.networkThrottling, | |
}, | |
{ | |
name: 'CPU throttling', | |
description: emulationDesc.cpuThrottling, | |
}, | |
]; | |
} | |
/** | |
* @param {LH.Config.Settings} settings | |
* @return {{deviceEmulation: string, networkThrottling: string, cpuThrottling: string, summary: string}} | |
*/ | |
static getEmulationDescriptions(settings) { | |
let cpuThrottling; | |
let networkThrottling; | |
let summary; | |
const throttling = settings.throttling; | |
switch (settings.throttlingMethod) { | |
case 'provided': | |
cpuThrottling = 'Provided by environment'; | |
networkThrottling = 'Provided by environment'; | |
summary = 'No throttling applied'; | |
break; | |
case 'devtools': { | |
const {cpuSlowdownMultiplier, requestLatencyMs} = throttling; | |
cpuThrottling = `${Util.formatNumber(cpuSlowdownMultiplier)}x slowdown (DevTools)`; | |
networkThrottling = `${Util.formatNumber(requestLatencyMs)}${NBSP}ms HTTP RTT, ` + | |
`${Util.formatNumber(throttling.downloadThroughputKbps)}${NBSP}Kbps down, ` + | |
`${Util.formatNumber(throttling.uploadThroughputKbps)}${NBSP}Kbps up (DevTools)`; | |
summary = 'Throttled Fast 3G network'; | |
break; | |
} | |
case 'simulate': { | |
const {cpuSlowdownMultiplier, rttMs, throughputKbps} = throttling; | |
cpuThrottling = `${Util.formatNumber(cpuSlowdownMultiplier)}x slowdown (Simulated)`; | |
networkThrottling = `${Util.formatNumber(rttMs)}${NBSP}ms TCP RTT, ` + | |
`${Util.formatNumber(throughputKbps)}${NBSP}Kbps throughput (Simulated)`; | |
summary = 'Simulated Fast 3G network'; | |
break; | |
} | |
default: | |
cpuThrottling = 'Unknown'; | |
networkThrottling = 'Unknown'; | |
summary = 'Unknown'; | |
} | |
let deviceEmulation = 'No emulation'; | |
if (!settings.disableDeviceEmulation) { | |
if (settings.emulatedFormFactor === 'mobile') deviceEmulation = 'Emulated Nexus 5X'; | |
if (settings.emulatedFormFactor === 'desktop') deviceEmulation = 'Emulated Desktop'; | |
} | |
return { | |
deviceEmulation, | |
cpuThrottling, | |
networkThrottling, | |
summary: `${deviceEmulation}, ${summary}`, | |
}; | |
} | |
/** | |
* Set the locale to be used for Util's number and date formatting functions. | |
* @param {LH.Locale} locale | |
*/ | |
static setNumberDateLocale(locale) { | |
Util.numberDateLocale = locale; | |
// When testing, use a locale with more exciting numeric formatting | |
if (Util.numberDateLocale === 'en-XA') Util.numberDateLocale = 'de'; | |
} | |
} | |
/** | |
* This value is updated on each run to the locale of the report | |
* @type {LH.Locale} | |
*/ | |
Util.numberDateLocale = 'en'; | |
/** | |
* Report-renderer-specific strings. | |
* @type {LH.I18NRendererStrings} | |
*/ | |
Util.UIStrings = { | |
/** Disclaimer shown to users below the metric values (First Contentful Paint, Time to Interactive, etc) to warn them that the numbers they see will likely change slightly the next time they run Lighthouse. */ | |
varianceDisclaimer: 'Values are estimated and may vary.', | |
/** Column heading label for the listing of opportunity audits. Each audit title represents an opportunity. There are only 2 columns, so no strict character limit. */ | |
opportunityResourceColumnLabel: 'Opportunity', | |
/** Column heading label for the estimated page load savings of opportunity audits. Estimated Savings is the total amount of time (in seconds) that Lighthouse computed could be reduced from the total page load time, if the suggested action is taken. There are only 2 columns, so no strict character limit. */ | |
opportunitySavingsColumnLabel: 'Estimated Savings', | |
/** An error string displayed next to a particular audit when it has errored, but not provided any specific error message. */ | |
errorMissingAuditInfo: 'Report error: no audit information', | |
/** A label, shown next to an audit title or metric title, indicating that there was an error computing it. The user can hover on the label to reveal a tooltip with the extended error message. Translation should be short (< 20 characters). */ | |
errorLabel: 'Error!', | |
/** This label is shown above a bulleted list of warnings. It is shown directly below an audit that produced warnings. Warnings describe situations the user should be aware of, as Lighthouse was unable to complete all the work required on this audit. For example, The 'Unable to decode image (biglogo.jpg)' warning may show up below an image encoding audit. */ | |
warningHeader: 'Warnings: ', | |
/** The tooltip text on an expandable chevron icon. Clicking the icon expands a section to reveal a list of audit results that was hidden by default. */ | |
auditGroupExpandTooltip: 'Show audits', | |
/** Section heading shown above a list of audits that are passing. 'Passed' here refers to a passing grade. This section is collapsed by default, as the user should be focusing on the failed audits instead. Users can click this heading to reveal the list. */ | |
passedAuditsGroupTitle: 'Passed audits', | |
/** Section heading shown above a list of audits that do not apply to the page. For example, if an audit is 'Are images optimized?', but the page has no images on it, the audit will be marked as not applicable. This is neither passing or failing. This section is collapsed by default, as the user should be focusing on the failed audits instead. Users can click this heading to reveal the list. */ | |
notApplicableAuditsGroupTitle: 'Not applicable', | |
/** Section heading shown above a list of audits that were not computed by Lighthouse. They serve as a list of suggestions for the user to go and manually check. For example, Lighthouse can't automate testing cross-browser compatibility, so that is listed within this section, so the user is reminded to test it themselves. This section is collapsed by default, as the user should be focusing on the failed audits instead. Users can click this heading to reveal the list. */ | |
manualAuditsGroupTitle: 'Additional items to manually check', | |
/** Label shown preceding any important warnings that may have invalidated the entire report. For example, if the user has Chrome extensions installed, they may add enough performance overhead that Lighthouse's performance metrics are unreliable. If shown, this will be displayed at the top of the report UI. */ | |
toplevelWarningsMessage: 'There were issues affecting this run of Lighthouse:', | |
/** Label preceding a pictorial explanation of the scoring scale: 0-50 is red (bad), 50-90 is orange (ok), 90-100 is green (good). These colors are used throughout the report to provide context for how good/bad a particular result is. */ | |
scorescaleLabel: 'Score scale:', | |
/** String of text shown in a graphical representation of the flow of network requests for the web page. This label represents the initial network request that fetches an HTML page. This navigation may be redirected (eg. Initial navigation to http://example.com redirects to https://www.example.com). */ | |
crcInitialNavigation: 'Initial Navigation', | |
/** Label of value shown in the summary of critical request chains. Refers to the total amount of time (milliseconds) of the longest critical path chain/sequence of network requests. Example value: 2310 ms */ | |
crcLongestDurationLabel: 'Maximum critical path latency:', | |
/** Explanation shown to users below performance results to inform them that the test was done with a 3G network connection and to warn them that the numbers they see will likely change slightly the next time they run Lighthouse. 'Lighthouse' becomes link text to additional documentation. */ | |
lsPerformanceCategoryDescription: '[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on emulated 3G. Values are estimated and may vary.', | |
/** Title of the lab data section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. "Lab" is an abbreviated form of "laboratory", and refers to the fact that the data is from a controlled test of a website, not measurements from real users visiting that site. */ | |
labDataTitle: 'Lab Data', | |
}; | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = Util; | |
} else { | |
self.Util = Util; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/* globals URL self */ | |
class DOM { | |
/** | |
* @param {Document} document | |
*/ | |
constructor(document) { | |
/** @type {Document} */ | |
this._document = document; | |
} | |
// TODO(bckenny): can pass along `createElement`'s inferred type | |
/** | |
* @param {string} name | |
* @param {string=} className | |
* @param {Object<string, (string|undefined)>=} attrs Attribute key/val pairs. | |
* Note: if an attribute key has an undefined value, this method does not | |
* set the attribute on the node. | |
* @return {Element} | |
*/ | |
createElement(name, className, attrs = {}) { | |
const element = this._document.createElement(name); | |
if (className) { | |
element.className = className; | |
} | |
Object.keys(attrs).forEach(key => { | |
const value = attrs[key]; | |
if (typeof value !== 'undefined') { | |
element.setAttribute(key, value); | |
} | |
}); | |
return element; | |
} | |
/** | |
* @return {DocumentFragment} | |
*/ | |
createFragment() { | |
return this._document.createDocumentFragment(); | |
} | |
/** | |
* @param {Element} parentElem | |
* @param {string} elementName | |
* @param {string=} className | |
* @param {Object<string, (string|undefined)>=} attrs Attribute key/val pairs. | |
* Note: if an attribute key has an undefined value, this method does not | |
* set the attribute on the node. | |
* @return {Element} | |
*/ | |
createChildOf(parentElem, elementName, className, attrs) { | |
const element = this.createElement(elementName, className, attrs); | |
parentElem.appendChild(element); | |
return element; | |
} | |
/** | |
* @param {string} selector | |
* @param {ParentNode} context | |
* @return {DocumentFragment} A clone of the template content. | |
* @throws {Error} | |
*/ | |
cloneTemplate(selector, context) { | |
const template = /** @type {?HTMLTemplateElement} */ (context.querySelector(selector)); | |
if (!template) { | |
throw new Error(`Template not found: template${selector}`); | |
} | |
const clone = this._document.importNode(template.content, true); | |
// Prevent duplicate styles in the DOM. After a template has been stamped | |
// for the first time, remove the clone's styles so they're not re-added. | |
if (template.hasAttribute('data-stamped')) { | |
this.findAll('style', clone).forEach(style => style.remove()); | |
} | |
template.setAttribute('data-stamped', 'true'); | |
return clone; | |
} | |
/** | |
* Resets the "stamped" state of the templates. | |
*/ | |
resetTemplates() { | |
this.findAll('template[data-stamped]', this._document).forEach(t => { | |
t.removeAttribute('data-stamped'); | |
}); | |
} | |
/** | |
* @param {string} text | |
* @return {Element} | |
*/ | |
convertMarkdownLinkSnippets(text) { | |
const element = this.createElement('span'); | |
// Split on markdown links (e.g. [some link](https://...)). | |
const parts = text.split(/\[([^\]]*?)\]\((https?:\/\/.*?)\)/g); | |
while (parts.length) { | |
// Pop off the same number of elements as there are capture groups. | |
const [preambleText, linkText, linkHref] = parts.splice(0, 3); | |
element.appendChild(this._document.createTextNode(preambleText)); | |
// Append link if there are any. | |
if (linkText && linkHref) { | |
const a = /** @type {HTMLAnchorElement} */ (this.createElement('a')); | |
a.rel = 'noopener'; | |
a.target = '_blank'; | |
a.textContent = linkText; | |
a.href = (new URL(linkHref)).href; | |
element.appendChild(a); | |
} | |
} | |
return element; | |
} | |
/** | |
* @param {string} text | |
* @return {Element} | |
*/ | |
convertMarkdownCodeSnippets(text) { | |
const element = this.createElement('span'); | |
const parts = text.split(/`(.*?)`/g); // Split on markdown code slashes | |
while (parts.length) { | |
// Pop off the same number of elements as there are capture groups. | |
const [preambleText, codeText] = parts.splice(0, 2); | |
element.appendChild(this._document.createTextNode(preambleText)); | |
if (codeText) { | |
const pre = /** @type {HTMLPreElement} */ (this.createElement('code')); | |
pre.textContent = codeText; | |
element.appendChild(pre); | |
} | |
} | |
return element; | |
} | |
/** | |
* @return {Document} | |
*/ | |
document() { | |
return this._document; | |
} | |
/** | |
* TODO(paulirish): import and conditionally apply the DevTools frontend subclasses instead of this | |
* @return {boolean} | |
*/ | |
isDevTools() { | |
return !!this._document.querySelector('.lh-devtools'); | |
} | |
/** | |
* Guaranteed context.querySelector. Always returns an element or throws if | |
* nothing matches query. | |
* @param {string} query | |
* @param {ParentNode} context | |
* @return {HTMLElement} | |
*/ | |
find(query, context) { | |
/** @type {?HTMLElement} */ | |
const result = context.querySelector(query); | |
if (result === null) { | |
throw new Error(`query ${query} not found`); | |
} | |
return result; | |
} | |
/** | |
* Helper for context.querySelectorAll. Returns an Array instead of a NodeList. | |
* @param {string} query | |
* @param {ParentNode} context | |
* @return {Array<HTMLElement>} | |
*/ | |
findAll(query, context) { | |
return Array.from(context.querySelectorAll(query)); | |
} | |
} | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = DOM; | |
} else { | |
self.DOM = DOM; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/* globals self CriticalRequestChainRenderer Util URL */ | |
/** @typedef {import('./dom.js')} DOM */ | |
/** @typedef {import('./crc-details-renderer.js')} CRCDetailsJSON */ | |
/** @typedef {LH.Result.Audit.OpportunityDetails} OpportunityDetails */ | |
/** @type {Array<string>} */ | |
const URL_PREFIXES = ['http://', 'https://', 'data:']; | |
class DetailsRenderer { | |
/** | |
* @param {DOM} dom | |
*/ | |
constructor(dom) { | |
/** @type {DOM} */ | |
this._dom = dom; | |
/** @type {ParentNode} */ | |
this._templateContext; // eslint-disable-line no-unused-expressions | |
} | |
/** | |
* @param {ParentNode} context | |
*/ | |
setTemplateContext(context) { | |
this._templateContext = context; | |
} | |
/** | |
* @param {DetailsJSON|OpportunityDetails} details | |
* @return {Element} | |
*/ | |
render(details) { | |
switch (details.type) { | |
case 'text': | |
return this._renderText(/** @type {StringDetailsJSON} */ (details)); | |
case 'url': | |
return this._renderTextURL(/** @type {StringDetailsJSON} */ (details)); | |
case 'bytes': | |
return this._renderBytes(/** @type {NumericUnitDetailsJSON} */ (details)); | |
case 'ms': | |
// eslint-disable-next-line max-len | |
return this._renderMilliseconds(/** @type {NumericUnitDetailsJSON} */ (details)); | |
case 'link': | |
// @ts-ignore - TODO(bckenny): Fix type hierarchy | |
return this._renderLink(/** @type {LinkDetailsJSON} */ (details)); | |
case 'thumbnail': | |
return this._renderThumbnail(/** @type {ThumbnailDetails} */ (details)); | |
case 'filmstrip': | |
// @ts-ignore - TODO(bckenny): Fix type hierarchy | |
return this._renderFilmstrip(/** @type {FilmstripDetails} */ (details)); | |
case 'table': | |
// @ts-ignore - TODO(bckenny): Fix type hierarchy | |
return this._renderTable(/** @type {TableDetailsJSON} */ (details)); | |
case 'code': | |
return this._renderCode(/** @type {DetailsJSON} */ (details)); | |
case 'node': | |
return this.renderNode(/** @type {NodeDetailsJSON} */(details)); | |
case 'criticalrequestchain': | |
return CriticalRequestChainRenderer.render(this._dom, this._templateContext, | |
// @ts-ignore - TODO(bckenny): Fix type hierarchy | |
/** @type {CRCDetailsJSON} */ (details)); | |
case 'opportunity': | |
// @ts-ignore - TODO(bckenny): Fix type hierarchy | |
return this._renderOpportunityTable(details); | |
default: { | |
throw new Error(`Unknown type: ${details.type}`); | |
} | |
} | |
} | |
/** | |
* @param {{value: number, granularity?: number}} details | |
* @return {Element} | |
*/ | |
_renderBytes(details) { | |
// TODO: handle displayUnit once we have something other than 'kb' | |
const value = Util.formatBytesToKB(details.value, details.granularity); | |
return this._renderText({value}); | |
} | |
/** | |
* @param {{value: number, granularity?: number, displayUnit?: string}} details | |
* @return {Element} | |
*/ | |
_renderMilliseconds(details) { | |
let value = Util.formatMilliseconds(details.value, details.granularity); | |
if (details.displayUnit === 'duration') { | |
value = Util.formatDuration(details.value); | |
} | |
return this._renderText({value}); | |
} | |
/** | |
* @param {{value: string}} text | |
* @return {HTMLElement} | |
*/ | |
_renderTextURL(text) { | |
const url = text.value; | |
let displayedPath; | |
let displayedHost; | |
let title; | |
try { | |
const parsed = Util.parseURL(url); | |
displayedPath = parsed.file === '/' ? parsed.origin : parsed.file; | |
displayedHost = parsed.file === '/' ? '' : `(${parsed.hostname})`; | |
title = url; | |
} catch (/** @type {!Error} */ e) { | |
if (!e.name.startsWith('TypeError')) { | |
throw e; | |
} | |
displayedPath = url; | |
} | |
const element = /** @type {HTMLElement} */ (this._dom.createElement('div', 'lh-text__url')); | |
element.appendChild(this._renderText({ | |
value: displayedPath, | |
})); | |
if (displayedHost) { | |
const hostElem = this._renderText({ | |
value: displayedHost, | |
}); | |
hostElem.classList.add('lh-text__url-host'); | |
element.appendChild(hostElem); | |
} | |
if (title) element.title = url; | |
return element; | |
} | |
/** | |
* @param {LinkDetailsJSON} details | |
* @return {Element} | |
*/ | |
_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({ | |
value: details.text, | |
}); | |
} | |
const a = /** @type {HTMLAnchorElement} */ (this._dom.createElement('a')); | |
a.rel = 'noopener'; | |
a.target = '_blank'; | |
a.textContent = details.text; | |
a.href = url.href; | |
return a; | |
} | |
/** | |
* @param {{value: string}} text | |
* @return {Element} | |
*/ | |
_renderText(text) { | |
const element = this._dom.createElement('div', 'lh-text'); | |
element.textContent = text.value; | |
return element; | |
} | |
/** | |
* Create small thumbnail with scaled down image asset. | |
* If the supplied details doesn't have an image/* mimeType, then an empty span is returned. | |
* @param {{value: string}} details | |
* @return {Element} | |
*/ | |
_renderThumbnail(details) { | |
const element = /** @type {HTMLImageElement}*/ (this._dom.createElement('img', 'lh-thumbnail')); | |
const strValue = details.value; | |
element.src = strValue; | |
element.title = strValue; | |
element.alt = ''; | |
return element; | |
} | |
/** | |
* @param {TableDetailsJSON} details | |
* @return {Element} | |
*/ | |
_renderTable(details) { | |
if (!details.items.length) return this._dom.createElement('span'); | |
const tableElem = this._dom.createElement('table', 'lh-table'); | |
const theadElem = this._dom.createChildOf(tableElem, 'thead'); | |
const theadTrElem = this._dom.createChildOf(theadElem, 'tr'); | |
for (const heading of details.headings) { | |
const itemType = heading.itemType || 'text'; | |
const classes = `lh-table-column--${itemType}`; | |
this._dom.createChildOf(theadTrElem, 'th', classes).appendChild(this.render({ | |
type: 'text', | |
value: heading.text || '', | |
})); | |
} | |
const tbodyElem = this._dom.createChildOf(tableElem, 'tbody'); | |
for (const row of details.items) { | |
const rowElem = this._dom.createChildOf(tbodyElem, 'tr'); | |
for (const heading of details.headings) { | |
const key = /** @type {keyof DetailsJSON} */ (heading.key); | |
// TODO(bckenny): type should be naturally inferred here. | |
const value = /** @type {number|string|DetailsJSON|undefined} */ (row[key]); | |
if (typeof value === 'undefined' || value === null) { | |
this._dom.createChildOf(rowElem, 'td', 'lh-table-column--empty'); | |
continue; | |
} | |
// handle nested types like code blocks in table rows. | |
// @ts-ignore - TODO(bckenny): narrow first | |
if (value.type) { | |
const valueAsDetails = /** @type {DetailsJSON} */ (value); | |
const classes = `lh-table-column--${valueAsDetails.type}`; | |
this._dom.createChildOf(rowElem, 'td', classes).appendChild(this.render(valueAsDetails)); | |
continue; | |
} | |
// build new details item to render | |
const item = { | |
value: /** @type {number|string} */ (value), | |
type: heading.itemType, | |
displayUnit: heading.displayUnit, | |
granularity: heading.granularity, | |
}; | |
/** @type {string|undefined} */ | |
// @ts-ignore - TODO(bckenny): handle with refactoring above | |
const valueType = value.type; | |
const classes = `lh-table-column--${valueType || heading.itemType}`; | |
this._dom.createChildOf(rowElem, 'td', classes).appendChild(this.render(item)); | |
} | |
} | |
return tableElem; | |
} | |
/** | |
* TODO(bckenny): migrate remaining table rendering to this function, then rename | |
* back to _renderTable and replace the original. | |
* @param {OpportunityDetails} details | |
* @return {Element} | |
*/ | |
_renderOpportunityTable(details) { | |
if (!details.items.length) return this._dom.createElement('span'); | |
const tableElem = this._dom.createElement('table', 'lh-table'); | |
const theadElem = this._dom.createChildOf(tableElem, 'thead'); | |
const theadTrElem = this._dom.createChildOf(theadElem, 'tr'); | |
for (const heading of details.headings) { | |
const valueType = heading.valueType || 'text'; | |
const classes = `lh-table-column--${valueType}`; | |
const labelEl = this._dom.createElement('div', 'lh-text'); | |
labelEl.textContent = heading.label; | |
this._dom.createChildOf(theadTrElem, 'th', classes).appendChild(labelEl); | |
} | |
const tbodyElem = this._dom.createChildOf(tableElem, 'tbody'); | |
for (const row of details.items) { | |
const rowElem = this._dom.createChildOf(tbodyElem, 'tr'); | |
for (const heading of details.headings) { | |
const key = /** @type {keyof LH.Result.Audit.OpportunityDetailsItem} */ (heading.key); | |
const value = row[key]; | |
if (typeof value === 'undefined' || value === null) { | |
this._dom.createChildOf(rowElem, 'td', 'lh-table-column--empty'); | |
continue; | |
} | |
const valueType = heading.valueType; | |
let itemElement; | |
// TODO(bckenny): as we add more table types, split out into _renderTableItem fn. | |
switch (valueType) { | |
case 'url': { | |
// Fall back to <pre> rendering if not actually a URL. | |
const strValue = /** @type {string} */ (value); | |
if (URL_PREFIXES.some(prefix => strValue.startsWith(prefix))) { | |
itemElement = this._renderTextURL({value: strValue}); | |
} else { | |
const codeValue = /** @type {(number|string|undefined)} */ (value); | |
itemElement = this._renderCode({value: codeValue}); | |
} | |
break; | |
} | |
case 'timespanMs': { | |
const numValue = /** @type {number} */ (value); | |
itemElement = this._renderMilliseconds({value: numValue}); | |
break; | |
} | |
case 'bytes': { | |
const numValue = /** @type {number} */ (value); | |
itemElement = this._renderBytes({value: numValue, granularity: 1}); | |
break; | |
} | |
case 'thumbnail': { | |
const strValue = /** @type {string} */ (value); | |
itemElement = this._renderThumbnail({value: strValue}); | |
break; | |
} | |
default: { | |
throw new Error(`Unknown valueType: ${valueType}`); | |
} | |
} | |
const classes = `lh-table-column--${valueType}`; | |
this._dom.createChildOf(rowElem, 'td', classes).appendChild(itemElement); | |
} | |
} | |
return tableElem; | |
} | |
/** | |
* @param {NodeDetailsJSON} item | |
* @return {Element} | |
* @protected | |
*/ | |
renderNode(item) { | |
const element = /** @type {HTMLSpanElement} */ (this._dom.createElement('span', 'lh-node')); | |
if (item.snippet) { | |
element.textContent = item.snippet; | |
} | |
if (item.selector) { | |
element.title = item.selector; | |
} | |
if (item.path) element.setAttribute('data-path', item.path); | |
if (item.selector) element.setAttribute('data-selector', item.selector); | |
if (item.snippet) element.setAttribute('data-snippet', item.snippet); | |
return element; | |
} | |
/** | |
* @param {FilmstripDetails} details | |
* @return {Element} | |
*/ | |
_renderFilmstrip(details) { | |
const filmstripEl = this._dom.createElement('div', 'lh-filmstrip'); | |
for (const thumbnail of details.items) { | |
const frameEl = this._dom.createChildOf(filmstripEl, 'div', 'lh-filmstrip__frame'); | |
this._dom.createChildOf(frameEl, 'img', 'lh-filmstrip__thumbnail', { | |
src: `data:image/jpeg;base64,${thumbnail.data}`, | |
alt: `Screenshot`, | |
}); | |
} | |
return filmstripEl; | |
} | |
/** | |
* @param {{value?: string|number}} details | |
* @return {Element} | |
*/ | |
_renderCode(details) { | |
const pre = this._dom.createElement('pre', 'lh-code'); | |
pre.textContent = /** @type {string} */ (details.value); | |
return pre; | |
} | |
} | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = DetailsRenderer; | |
} else { | |
self.DetailsRenderer = DetailsRenderer; | |
} | |
// TODO, what's the diff between DetailsJSON and NumericUnitDetailsJSON? | |
/** | |
* @typedef {{ | |
type: string, | |
value: (string|number|undefined), | |
granularity?: number, | |
displayUnit?: string | |
}} DetailsJSON | |
*/ | |
/** | |
* @typedef {{ | |
type: string, | |
value: string, | |
granularity?: number, | |
displayUnit?: string, | |
}} StringDetailsJSON | |
*/ | |
/** | |
* @typedef {{ | |
type: string, | |
value: number, | |
granularity?: number, | |
displayUnit?: string, | |
}} NumericUnitDetailsJSON | |
*/ | |
/** | |
* @typedef {{ | |
type: string, | |
path?: string, | |
selector?: string, | |
snippet?: string | |
}} NodeDetailsJSON | |
*/ | |
/** | |
* @typedef {{ | |
itemType: string, | |
key: string, | |
text?: string, | |
granularity?: number, | |
displayUnit?: string, | |
}} TableHeaderJSON | |
*/ | |
/** @typedef {{ | |
type: string, | |
items: Array<DetailsJSON>, | |
headings: Array<TableHeaderJSON> | |
}} TableDetailsJSON | |
*/ | |
/** @typedef {{ | |
type: string, | |
value: string, | |
}} ThumbnailDetails | |
*/ | |
/** @typedef {{ | |
type: string, | |
text: string, | |
url: string | |
}} LinkDetailsJSON | |
*/ | |
/** @typedef {{ | |
type: string, | |
scale: number, | |
items: Array<{timing: number, timestamp: number, data: string}>, | |
}} FilmstripDetails | |
*/ | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/** | |
* @fileoverview This file contains helpers for constructing and rendering the | |
* critical request chains network tree. | |
*/ | |
/* globals self Util */ | |
/** @typedef {import('./dom.js')} DOM */ | |
class CriticalRequestChainRenderer { | |
/** | |
* Create render context for critical-request-chain tree display. | |
* @param {LH.Audit.SimpleCriticalRequestNode} tree | |
* @return {{tree: LH.Audit.SimpleCriticalRequestNode, startTime: number, transferSize: number}} | |
*/ | |
static initTree(tree) { | |
let startTime = 0; | |
const rootNodes = Object.keys(tree); | |
if (rootNodes.length > 0) { | |
const node = tree[rootNodes[0]]; | |
startTime = node.request.startTime; | |
} | |
return {tree, startTime, transferSize: 0}; | |
} | |
/** | |
* Helper to create context for each critical-request-chain node based on its | |
* parent. Calculates if this node is the last child, whether it has any | |
* children itself and what the tree looks like all the way back up to the root, | |
* so the tree markers can be drawn correctly. | |
* @param {LH.Audit.SimpleCriticalRequestNode} parent | |
* @param {string} id | |
* @param {number} startTime | |
* @param {number} transferSize | |
* @param {Array<boolean>=} treeMarkers | |
* @param {boolean=} parentIsLastChild | |
* @return {CRCSegment} | |
*/ | |
static createSegment(parent, id, startTime, transferSize, treeMarkers, parentIsLastChild) { | |
const node = parent[id]; | |
const siblings = Object.keys(parent); | |
const isLastChild = siblings.indexOf(id) === (siblings.length - 1); | |
const hasChildren = Object.keys(node.children).length > 0; | |
// Copy the tree markers so that we don't change by reference. | |
const newTreeMarkers = Array.isArray(treeMarkers) ? treeMarkers.slice(0) : []; | |
// Add on the new entry. | |
if (typeof parentIsLastChild !== 'undefined') { | |
newTreeMarkers.push(!parentIsLastChild); | |
} | |
return { | |
node, | |
isLastChild, | |
hasChildren, | |
startTime, | |
transferSize: transferSize + node.request.transferSize, | |
treeMarkers: newTreeMarkers, | |
}; | |
} | |
/** | |
* Creates the DOM for a tree segment. | |
* @param {DOM} dom | |
* @param {DocumentFragment} tmpl | |
* @param {CRCSegment} segment | |
* @return {Node} | |
*/ | |
static createChainNode(dom, tmpl, segment) { | |
const chainsEl = dom.cloneTemplate('#tmpl-lh-crc__chains', tmpl); | |
// Hovering over request shows full URL. | |
dom.find('.crc-node', chainsEl).setAttribute('title', segment.node.request.url); | |
const treeMarkeEl = dom.find('.crc-node__tree-marker', chainsEl); | |
// Construct lines and add spacers for sub requests. | |
segment.treeMarkers.forEach(separator => { | |
if (separator) { | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker vert')); | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker')); | |
} else { | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker')); | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker')); | |
} | |
}); | |
if (segment.isLastChild) { | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker up-right')); | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker right')); | |
} else { | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker vert-right')); | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker right')); | |
} | |
if (segment.hasChildren) { | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker horiz-down')); | |
} else { | |
treeMarkeEl.appendChild(dom.createElement('span', 'tree-marker right')); | |
} | |
// 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-hostname', treevalEl).textContent = hostname ? `(${hostname})` : ''; | |
if (!segment.hasChildren) { | |
const {startTime, endTime, transferSize} = segment.node.request; | |
const span = dom.createElement('span', 'crc-node__chain-duration'); | |
span.textContent = ' - ' + Util.formatMilliseconds((endTime - startTime) * 1000) + ', '; | |
const span2 = dom.createElement('span', 'crc-node__chain-duration'); | |
span2.textContent = Util.formatBytesToKB(transferSize, 0.01); | |
treevalEl.appendChild(span); | |
treevalEl.appendChild(span2); | |
} | |
return chainsEl; | |
} | |
/** | |
* Recursively builds a tree from segments. | |
* @param {DOM} dom | |
* @param {DocumentFragment} tmpl | |
* @param {CRCSegment} segment | |
* @param {Element} elem Parent element. | |
* @param {CRCDetailsJSON} details | |
*/ | |
static buildTree(dom, tmpl, segment, elem, details) { | |
elem.appendChild(CriticalRequestChainRenderer.createChainNode(dom, tmpl, segment)); | |
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); | |
} | |
} | |
/** | |
* @param {DOM} dom | |
* @param {ParentNode} templateContext | |
* @param {CRCDetailsJSON} details | |
* @return {Element} | |
*/ | |
static render(dom, templateContext, details) { | |
const tmpl = dom.cloneTemplate('#tmpl-lh-crc', templateContext); | |
const containerEl = dom.find('.lh-crc', tmpl); | |
// Fill in top summary. | |
dom.find('.crc-initial-nav', tmpl).textContent = Util.UIStrings.crcInitialNavigation; | |
dom.find('.lh-crc__longest_duration_label', tmpl).textContent = | |
Util.UIStrings.crcLongestDurationLabel; | |
dom.find('.lh-crc__longest_duration', tmpl).textContent = | |
Util.formatMilliseconds(details.longestChain.duration); | |
// Construct visual tree. | |
const root = CriticalRequestChainRenderer.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); | |
} | |
return dom.find('.lh-crc-container', tmpl); | |
} | |
} | |
// Allow Node require()'ing. | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = CriticalRequestChainRenderer; | |
} else { | |
self.CriticalRequestChainRenderer = CriticalRequestChainRenderer; | |
} | |
/** @typedef {{ | |
type: string, | |
header: {text: string}, | |
longestChain: {duration: number, length: number, transferSize: number}, | |
chains: LH.Audit.SimpleCriticalRequestNode | |
}} CRCDetailsJSON | |
*/ | |
/** @typedef {{ | |
node: LH.Audit.SimpleCriticalRequestNode[string], | |
isLastChild: boolean, | |
hasChildren: boolean, | |
startTime: number, | |
transferSize: number, | |
treeMarkers: Array<boolean> | |
}} CRCSegment | |
*/ | |
; | |
/** | |
* @license Copyright 2017 Google Inc. All Rights Reserved. | |
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | |
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. | |
*/ | |
'use strict'; | |
/* global URL */ | |
/** | |
* @fileoverview | |
* @suppress {reportUnknownTypes} | |
*/ | |
/** | |
* Generate a filenamePrefix of hostname_YYYY-MM-DD_HH-MM-SS | |
* Date/time uses the local timezone, however Node has unreliable ICU | |
* support, so we must construct a YYYY-MM-DD date format manually. :/ | |
* @param {{finalUrl: string, fetchTime: string}} lhr | |
* @return {string} | |
*/ | |
function getFilenamePrefix(lhr) { | |
const hostname = new (getUrlConstructor())(lhr.finalUrl).hostname; | |
const date = (lhr.fetchTime && new Date(lhr.fetchTime)) || new Date(); | |
const timeStr = date.toLocaleTimeString('en-US', {hour12: false}); | |
const dateParts = date.toLocaleDateString('en-US', { | |
year: 'numeric', month: '2-digit', day: '2-digit', | |
}).split('/'); | |
// @ts-ignore - parts exists | |
dateParts.unshift(dateParts.pop()); | |
const dateStr = dateParts.join('-'); | |
const filenamePrefix = `${hostname}_${dateStr}_${timeStr}`; | |
// replace characters that are unfriendly to filenames | |
return filenamePrefix.replace(/[/?<>\\:*|":]/g, '-'); | |
} | |
function getUrlConstructor() { | |
if (typeof module !== 'undefined' && module.exports) { | |
return require('./url-shim'); | |
} else { | |
return URL; | |
} | |
} | |
// @ts-ignore - suppress `module` error for type-checking in a browser context. | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = {getFilenamePrefix}; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/** | |
* Logs messages via a UI butter. | |
*/ | |
class Logger { | |
/** | |
* @param {Element} element | |
*/ | |
constructor(element) { | |
/** @type {Element} */ | |
this.el = element; | |
this._id = undefined; | |
} | |
/** | |
* Shows a butter bar. | |
* @param {string} msg The message to show. | |
* @param {boolean=} autoHide True to hide the message after a duration. | |
* Default is true. | |
*/ | |
log(msg, autoHide = true) { | |
this._id && clearTimeout(this._id); | |
this.el.textContent = msg; | |
this.el.classList.add('show'); | |
if (autoHide) { | |
this._id = setTimeout(_ => { | |
this.el.classList.remove('show'); | |
}, 7000); | |
} | |
} | |
/** | |
* @param {string} msg | |
*/ | |
warn(msg) { | |
this.log('Warning: ' + msg); | |
} | |
/** | |
* @param {string} msg | |
*/ | |
error(msg) { | |
this.log(msg); | |
// Rethrow to make sure it's auditable as an error, but in a setTimeout so page | |
// recovers gracefully and user can try loading a report again. | |
setTimeout(_ => { | |
throw new Error(msg); | |
}, 0); | |
} | |
/** | |
* Explicitly hides the butter bar. | |
*/ | |
hide() { | |
this._id && clearTimeout(this._id); | |
this.el.classList.remove('show'); | |
} | |
} | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = Logger; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/** | |
* @fileoverview Adds export button, print, and other dynamic functionality to | |
* the report. | |
*/ | |
/* globals self URL Blob CustomEvent getFilenamePrefix window */ | |
/** @typedef {import('./dom.js')} DOM */ | |
class ReportUIFeatures { | |
/** | |
* @param {DOM} dom | |
*/ | |
constructor(dom) { | |
/** @type {LH.ReportResult} */ | |
this.json; // eslint-disable-line no-unused-expressions | |
/** @type {DOM} */ | |
this._dom = dom; | |
/** @type {Document} */ | |
this._document = this._dom.document(); | |
/** @type {boolean} */ | |
this._copyAttempt = false; | |
/** @type {HTMLElement} */ | |
this.exportButton; // eslint-disable-line no-unused-expressions | |
/** @type {HTMLElement} */ | |
this.headerSticky; // eslint-disable-line no-unused-expressions | |
/** @type {HTMLElement} */ | |
this.headerBackground; // eslint-disable-line no-unused-expressions | |
/** @type {HTMLElement} */ | |
this.lighthouseIcon; // eslint-disable-line no-unused-expressions | |
/** @type {!HTMLElement} */ | |
this.scoresWrapperBg; // eslint-disable-line no-unused-expressions | |
/** @type {!HTMLElement} */ | |
this.productInfo; // eslint-disable-line no-unused-expressions | |
/** @type {HTMLElement} */ | |
this.toolbar; // eslint-disable-line no-unused-expressions | |
/** @type {HTMLElement} */ | |
this.toolbarMetadata; // eslint-disable-line no-unused-expressions | |
/** @type {HTMLElement} */ | |
this.env; // eslint-disable-line no-unused-expressions | |
/** @type {number} */ | |
this.headerOverlap = 0; | |
/** @type {number} */ | |
this.headerHeight = 0; | |
/** @type {number} */ | |
this.latestKnownScrollY = 0; | |
/** @type {boolean} */ | |
this.isAnimatingHeader = false; | |
this.onMediaQueryChange = this.onMediaQueryChange.bind(this); | |
this.onCopy = this.onCopy.bind(this); | |
this.onExportButtonClick = this.onExportButtonClick.bind(this); | |
this.onExport = this.onExport.bind(this); | |
this.onKeyDown = this.onKeyDown.bind(this); | |
this.printShortCutDetect = this.printShortCutDetect.bind(this); | |
this.onScroll = this.onScroll.bind(this); | |
this.onChevronClick = this.onChevronClick.bind(this); | |
} | |
/** | |
* Adds export button, print, and other functionality to the report. The method | |
* should be called whenever the report needs to be re-rendered. | |
* @param {LH.ReportResult} report | |
*/ | |
initFeatures(report) { | |
if (this._dom.isDevTools()) return; | |
this.json = report; | |
this._setupMediaQueryListeners(); | |
this._setupExportButton(); | |
this._setUpCollapseDetailsAfterPrinting(); | |
this._setupHeaderAnimation(); | |
this._resetUIState(); | |
this._document.addEventListener('keydown', this.printShortCutDetect); | |
this._document.addEventListener('copy', this.onCopy); | |
} | |
/** | |
* Fires a custom DOM event on target. | |
* @param {string} name Name of the event. | |
* @param {Node=} target DOM node to fire the event on. | |
* @param {*=} detail Custom data to include. | |
*/ | |
_fireEventOn(name, target = this._document, detail) { | |
const event = new CustomEvent(name, detail ? {detail} : undefined); | |
target.dispatchEvent(event); | |
} | |
_setupMediaQueryListeners() { | |
const mediaQuery = self.matchMedia('(max-width: 600px)'); | |
mediaQuery.addListener(this.onMediaQueryChange); | |
// Ensure the handler is called on init | |
this.onMediaQueryChange(mediaQuery); | |
} | |
/** | |
* Handle media query change events. | |
* @param {MediaQueryList|MediaQueryListEvent} mql | |
*/ | |
onMediaQueryChange(mql) { | |
const root = this._dom.find('.lh-root', this._document); | |
root.classList.toggle('lh-narrow', mql.matches); | |
} | |
_setupExportButton() { | |
this.exportButton = this._dom.find('.lh-export__button', this._document); | |
this.exportButton.addEventListener('click', this.onExportButtonClick); | |
const dropdown = this._dom.find('.lh-export__dropdown', this._document); | |
dropdown.addEventListener('click', this.onExport); | |
} | |
_setupHeaderAnimation() { | |
const scoresWrapper = this._dom.find('.lh-scores-wrapper', this._document); | |
const computedMarginTop = window.getComputedStyle(scoresWrapper).marginTop; | |
this.headerOverlap = parseFloat(computedMarginTop || '0'); | |
this.headerSticky = this._dom.find('.lh-header-sticky', this._document); | |
this.headerBackground = this._dom.find('.lh-header-bg', this._document); | |
this.lighthouseIcon = this._dom.find('.lh-lighthouse', this._document); | |
this.scoresWrapperBg = this._dom.find('.lh-scores-wrapper__background', this._document); | |
this.productInfo = this._dom.find('.lh-product-info', this._document); | |
this.toolbar = this._dom.find('.lh-toolbar', this._document); | |
this.toolbarMetadata = this._dom.find('.lh-toolbar__metadata', this._document); | |
const computedHeight = window.getComputedStyle(this.headerBackground).height; | |
this.headerHeight = parseFloat(computedHeight || '0'); | |
this._document.addEventListener('scroll', this.onScroll, {passive: true}); | |
const toolbarChevron = this._dom.find('.lh-toggle-arrow', this.toolbar); | |
toolbarChevron.addEventListener('click', this.onChevronClick); | |
} | |
/** | |
* Handle copy events. | |
* @param {ClipboardEvent} e | |
*/ | |
onCopy(e) { | |
// Only handle copy button presses (e.g. ignore the user copying page text). | |
if (this._copyAttempt) { | |
// We want to write our own data to the clipboard, not the user's text selection. | |
e.preventDefault(); | |
e.clipboardData.setData('text/plain', JSON.stringify(this.json, null, 2)); | |
this._fireEventOn('lh-log', this._document, { | |
cmd: 'log', msg: 'Report JSON copied to clipboard', | |
}); | |
} | |
this._copyAttempt = false; | |
} | |
/** | |
* Copies the report JSON to the clipboard (if supported by the browser). | |
*/ | |
onCopyButtonClick() { | |
this._fireEventOn('lh-analytics', this._document, { | |
cmd: 'send', | |
fields: {hitType: 'event', eventCategory: 'report', eventAction: 'copy'}, | |
}); | |
try { | |
if (this._document.queryCommandSupported('copy')) { | |
this._copyAttempt = true; | |
// Note: In Safari 10.0.1, execCommand('copy') returns true if there's | |
// a valid text selection on the page. See http://caniuse.com/#feat=clipboard. | |
if (!this._document.execCommand('copy')) { | |
this._copyAttempt = false; // Prevent event handler from seeing this as a copy attempt. | |
this._fireEventOn('lh-log', this._document, { | |
cmd: 'warn', msg: 'Your browser does not support copy to clipboard.', | |
}); | |
} | |
} | |
} catch (/** @type {Error} */ e) { | |
this._copyAttempt = false; | |
this._fireEventOn('lh-log', this._document, {cmd: 'log', msg: e.message}); | |
} | |
} | |
onScroll() { | |
this.latestKnownScrollY = window.scrollY; | |
if (!this.isAnimatingHeader) { | |
window.requestAnimationFrame(this.animateHeader.bind(this)); | |
} | |
this.isAnimatingHeader = true; | |
} | |
onChevronClick() { | |
const toggle = this._dom.find('.lh-config__settings-toggle', this._document); | |
if (toggle.hasAttribute('open')) { | |
toggle.removeAttribute('open'); | |
} else { | |
toggle.setAttribute('open', 'true'); | |
} | |
} | |
animateHeader() { | |
const collapsedHeaderHeight = 50; | |
const heightDiff = this.headerHeight - collapsedHeaderHeight + this.headerOverlap; | |
const scrollPct = Math.min(1, | |
this.latestKnownScrollY / (this.headerHeight - collapsedHeaderHeight)); | |
const scoresContainer = /** @type {HTMLElement} */ (this.scoresWrapperBg.parentElement); | |
this.headerSticky.style.transform = `translateY(${heightDiff * scrollPct * -1}px)`; | |
this.headerBackground.style.transform = `translateY(${scrollPct * this.headerOverlap}px)`; | |
this.lighthouseIcon.style.transform = | |
`translate3d(calc(var(--report-width) / 2),` + | |
` calc(-100% - ${scrollPct * this.headerOverlap * -1}px), 0) scale(${1 - scrollPct})`; | |
this.lighthouseIcon.style.opacity = Math.max(0, 1 - scrollPct).toString(); | |
// Switch up the score background & shadows | |
this.scoresWrapperBg.style.opacity = (1 - scrollPct).toString(); | |
this.scoresWrapperBg.style.transform = `scaleY(${1 - scrollPct * 0.2})`; | |
const scoreShadow = this._dom.find('.lh-scores-wrapper__shadow', scoresContainer); | |
scoreShadow.style.opacity = scrollPct.toString(); | |
scoreShadow.style.transform = `scaleY(${1 - scrollPct * 0.2})`; | |
// Fade & move the scorescale | |
const scoreScalePositionDelta = 32; | |
const scoreScale = this._dom.find('.lh-scorescale', scoresContainer); | |
scoreScale.style.opacity = `${1 - scrollPct}`; | |
scoreScale.style.transform = `translateY(${scrollPct * -scoreScalePositionDelta}px)`; | |
// Move the toolbar & export | |
this.toolbar.style.transform = `translateY(${heightDiff * scrollPct}px)`; | |
const exportParent = this.exportButton.parentElement; | |
if (exportParent) { | |
exportParent.style.transform = `translateY(${heightDiff * scrollPct}px)`; | |
} | |
this.exportButton.style.transform = `scale(${1 - 0.2 * scrollPct})`; | |
// Start showing the productinfo when we are at the 50% mark of our animation | |
const opacity = scrollPct < 0.5 ? 0 : (scrollPct - 0.5) * 2; | |
this.productInfo.style.opacity = this.toolbarMetadata.style.opacity = opacity.toString(); | |
this.isAnimatingHeader = false; | |
} | |
closeExportDropdown() { | |
this.exportButton.classList.remove('active'); | |
} | |
/** | |
* Click handler for export button. | |
* @param {Event} e | |
*/ | |
onExportButtonClick(e) { | |
e.preventDefault(); | |
const el = /** @type {Element} */ (e.target); | |
el.classList.toggle('active'); | |
this._document.addEventListener('keydown', this.onKeyDown); | |
} | |
/** | |
* Resets the state of page before capturing the page for export. | |
* When the user opens the exported HTML page, certain UI elements should | |
* be in their closed state (not opened) and the templates should be unstamped. | |
*/ | |
_resetUIState() { | |
this.closeExportDropdown(); | |
this._dom.resetTemplates(); | |
} | |
/** | |
* Handler for "export as" button. | |
* @param {Event} e | |
*/ | |
onExport(e) { | |
e.preventDefault(); | |
const el = /** @type {?Element} */ (e.target); | |
if (!el || !el.hasAttribute('data-action')) { | |
return; | |
} | |
switch (el.getAttribute('data-action')) { | |
case 'copy': | |
this.onCopyButtonClick(); | |
break; | |
case 'print-summary': | |
this.collapseAllDetails(); | |
this.closeExportDropdown(); | |
self.print(); | |
break; | |
case 'print-expanded': | |
this.expandAllDetails(); | |
this.closeExportDropdown(); | |
self.print(); | |
break; | |
case 'save-json': { | |
const jsonStr = JSON.stringify(this.json, null, 2); | |
this._saveFile(new Blob([jsonStr], {type: 'application/json'})); | |
break; | |
} | |
case 'save-html': { | |
const htmlStr = this.getReportHtml(); | |
try { | |
this._saveFile(new Blob([htmlStr], {type: 'text/html'})); | |
} catch (/** @type {Error} */ e) { | |
this._fireEventOn('lh-log', this._document, { | |
cmd: 'error', msg: 'Could not export as HTML. ' + e.message, | |
}); | |
} | |
break; | |
} | |
case 'open-viewer': { | |
const viewerPath = '/lighthouse/viewer/'; | |
ReportUIFeatures.openTabAndSendJsonReport(this.json, viewerPath); | |
break; | |
} | |
case 'save-gist': { | |
this.saveAsGist(); | |
break; | |
} | |
} | |
this.closeExportDropdown(); | |
this._document.removeEventListener('keydown', this.onKeyDown); | |
} | |
/** | |
* Keydown handler for the document. | |
* @param {KeyboardEvent} e | |
*/ | |
onKeyDown(e) { | |
if (e.keyCode === 27) { // ESC | |
this.closeExportDropdown(); | |
} | |
} | |
/** | |
* Opens a new tab to the online viewer and sends the local page's JSON results | |
* to the online viewer using postMessage. | |
* @param {LH.ReportResult} reportJson | |
* @param {string} viewerPath | |
* @protected | |
*/ | |
static openTabAndSendJsonReport(reportJson, viewerPath) { | |
const VIEWER_ORIGIN = 'https://googlechrome.github.io'; | |
// Chrome doesn't allow us to immediately postMessage to a popup right | |
// after it's created. Normally, we could also listen for the popup window's | |
// load event, however it is cross-domain and won't fire. Instead, listen | |
// for a message from the target app saying "I'm open". | |
const json = reportJson; | |
window.addEventListener('message', function msgHandler(/** @type {Event} */ e) { | |
const messageEvent = /** @type {MessageEvent} */ (e); | |
if (messageEvent.origin !== VIEWER_ORIGIN) { | |
return; | |
} | |
if (popup && messageEvent.data.opened) { | |
popup.postMessage({lhresults: json}, VIEWER_ORIGIN); | |
window.removeEventListener('message', msgHandler); | |
} | |
}); | |
// The popup's window.name is keyed by version+url+fetchTime, so we reuse/select tabs correctly | |
// @ts-ignore - If this is a v2 LHR, use old `generatedTime`. | |
const fallbackFetchTime = /** @type {string} */ (json.generatedTime); | |
const fetchTime = json.fetchTime || fallbackFetchTime; | |
const windowName = `${json.lighthouseVersion}-${json.requestedUrl}-${fetchTime}`; | |
const popup = window.open(`${VIEWER_ORIGIN}${viewerPath}`, windowName); | |
} | |
/** | |
* Expands audit details when user prints via keyboard shortcut. | |
* @param {KeyboardEvent} e | |
*/ | |
printShortCutDetect(e) { | |
if ((e.ctrlKey || e.metaKey) && e.keyCode === 80) { // Ctrl+P | |
this.closeExportDropdown(); | |
} | |
} | |
/** | |
* Expands all audit `<details>`. | |
* Ideally, a print stylesheet could take care of this, but CSS has no way to | |
* open a `<details>` element. | |
*/ | |
expandAllDetails() { | |
const details = /** @type {Array<HTMLDetailsElement>} */ (this._dom.findAll( | |
'.lh-categories details', this._document)); | |
details.map(detail => detail.open = true); | |
} | |
/** | |
* Collapses all audit `<details>`. | |
* open a `<details>` element. | |
*/ | |
collapseAllDetails() { | |
const details = /** @type {Array<HTMLDetailsElement>} */ (this._dom.findAll( | |
'.lh-categories details', this._document)); | |
details.map(detail => detail.open = false); | |
} | |
/** | |
* Sets up listeners to collapse audit `<details>` when the user closes the | |
* print dialog, all `<details>` are collapsed. | |
*/ | |
_setUpCollapseDetailsAfterPrinting() { | |
// FF and IE implement these old events. | |
if ('onbeforeprint' in self) { | |
self.addEventListener('afterprint', this.collapseAllDetails); | |
} else { | |
const win = /** @type {Window} */ (self); | |
// Note: FF implements both window.onbeforeprint and media listeners. However, | |
// it doesn't matchMedia doesn't fire when matching 'print'. | |
win.matchMedia('print').addListener(mql => { | |
if (mql.matches) { | |
this.expandAllDetails(); | |
} else { | |
this.collapseAllDetails(); | |
} | |
}); | |
} | |
} | |
/** | |
* Returns the html that recreates this report. | |
* @return {string} | |
* @protected | |
*/ | |
getReportHtml() { | |
this._resetUIState(); | |
// @ts-ignore - technically documentElement can be null, but that's dumb - https://dom.spec.whatwg.org/#document-element | |
return this._document.documentElement.outerHTML; | |
} | |
/** | |
* Save json as a gist. Unimplemented in base UI features. | |
* @protected | |
*/ | |
saveAsGist() { | |
throw new Error('Cannot save as gist from base report'); | |
} | |
/** | |
* Downloads a file (blob) using a[download]. | |
* @param {Blob|File} blob The file to save. | |
* @private | |
*/ | |
_saveFile(blob) { | |
const filename = getFilenamePrefix({ | |
finalUrl: this.json.finalUrl, | |
fetchTime: this.json.fetchTime, | |
}); | |
const ext = blob.type.match('json') ? '.json' : '.html'; | |
const href = URL.createObjectURL(blob); | |
const a = /** @type {HTMLAnchorElement} */ (this._dom.createElement('a')); | |
a.download = `${filename}${ext}`; | |
a.href = href; | |
this._document.body.appendChild(a); // Firefox requires anchor to be in the DOM. | |
a.click(); | |
// cleanup. | |
this._document.body.removeChild(a); | |
setTimeout(_ => URL.revokeObjectURL(href), 500); | |
} | |
} | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = ReportUIFeatures; | |
} else { | |
self.ReportUIFeatures = ReportUIFeatures; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/* globals self, Util */ | |
/** @typedef {import('./dom.js')} DOM */ | |
/** @typedef {import('./report-renderer.js')} ReportRenderer */ | |
/** @typedef {import('./details-renderer.js')} DetailsRenderer */ | |
/** @typedef {import('./util.js')} Util */ | |
class CategoryRenderer { | |
/** | |
* @param {DOM} dom | |
* @param {DetailsRenderer} detailsRenderer | |
*/ | |
constructor(dom, detailsRenderer) { | |
/** @type {DOM} */ | |
this.dom = dom; | |
/** @type {DetailsRenderer} */ | |
this.detailsRenderer = detailsRenderer; | |
/** @type {ParentNode} */ | |
this.templateContext = this.dom.document(); | |
this.detailsRenderer.setTemplateContext(this.templateContext); | |
} | |
/** | |
* @param {LH.ReportResult.AuditRef} audit | |
* @param {number} index | |
* @return {Element} | |
*/ | |
renderAudit(audit, index) { | |
const tmpl = this.dom.cloneTemplate('#tmpl-lh-audit', this.templateContext); | |
return this.populateAuditValues(audit, index, tmpl); | |
} | |
/** | |
* Populate an DOM tree with audit details. Used by renderAudit and renderOpportunity | |
* @param {LH.ReportResult.AuditRef} audit | |
* @param {number} index | |
* @param {DocumentFragment} tmpl | |
* @return {Element} | |
*/ | |
populateAuditValues(audit, index, tmpl) { | |
const auditEl = this.dom.find('.lh-audit', tmpl); | |
auditEl.id = audit.result.id; | |
const scoreDisplayMode = audit.result.scoreDisplayMode; | |
if (audit.result.displayValue) { | |
const displayValue = Util.formatDisplayValue(audit.result.displayValue); | |
this.dom.find('.lh-audit__display-text', auditEl).textContent = displayValue; | |
} | |
const titleEl = this.dom.find('.lh-audit__title', auditEl); | |
titleEl.appendChild(this.dom.convertMarkdownCodeSnippets(audit.result.title)); | |
this.dom.find('.lh-audit__description', auditEl) | |
.appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description)); | |
const header = /** @type {HTMLDetailsElement} */ (this.dom.find('details', auditEl)); | |
if (audit.result.details && audit.result.details.type) { | |
const elem = this.detailsRenderer.render(audit.result.details); | |
elem.classList.add('lh-details'); | |
header.appendChild(elem); | |
} | |
this.dom.find('.lh-audit__index', auditEl).textContent = `${index + 1}`; | |
// Add chevron SVG to the end of the summary | |
this.dom.find('.lh-chevron-container', auditEl).appendChild(this._createChevron()); | |
this._setRatingClass(auditEl, audit.result.score, scoreDisplayMode); | |
if (audit.result.scoreDisplayMode === 'error') { | |
auditEl.classList.add(`lh-audit--error`); | |
const textEl = this.dom.find('.lh-audit__display-text', auditEl); | |
textEl.textContent = Util.UIStrings.errorLabel; | |
textEl.classList.add('tooltip-boundary'); | |
const tooltip = this.dom.createChildOf(textEl, 'div', 'tooltip tooltip--error'); | |
tooltip.textContent = audit.result.errorMessage || Util.UIStrings.errorMissingAuditInfo; | |
} else if (audit.result.explanation) { | |
const explEl = this.dom.createChildOf(titleEl, 'div', 'lh-audit-explanation'); | |
explEl.textContent = audit.result.explanation; | |
} | |
const warnings = audit.result.warnings; | |
if (!warnings || warnings.length === 0) return auditEl; | |
// Add list of warnings or singular warning | |
const warningsEl = this.dom.createChildOf(titleEl, 'div', 'lh-warnings'); | |
if (warnings.length === 1) { | |
warningsEl.textContent = `${Util.UIStrings.warningHeader} ${warnings.join('')}`; | |
} else { | |
warningsEl.textContent = Util.UIStrings.warningHeader; | |
const warningsUl = this.dom.createChildOf(warningsEl, 'ul'); | |
for (const warning of warnings) { | |
const item = this.dom.createChildOf(warningsUl, 'li'); | |
item.textContent = warning; | |
} | |
} | |
return auditEl; | |
} | |
/** | |
* @return {HTMLElement} | |
*/ | |
_createChevron() { | |
const chevronTmpl = this.dom.cloneTemplate('#tmpl-lh-chevron', this.templateContext); | |
const chevronEl = this.dom.find('.lh-chevron', chevronTmpl); | |
return chevronEl; | |
} | |
/** | |
* @param {Element} element DOM node to populate with values. | |
* @param {number|null} score | |
* @param {string} scoreDisplayMode | |
* @return {Element} | |
*/ | |
_setRatingClass(element, score, scoreDisplayMode) { | |
const rating = Util.calculateRating(score, scoreDisplayMode); | |
element.classList.add(`lh-audit--${rating}`, `lh-audit--${scoreDisplayMode}`); | |
return element; | |
} | |
/** | |
* @param {LH.ReportResult.Category} category | |
* @return {Element} | |
*/ | |
renderCategoryHeader(category) { | |
const tmpl = this.dom.cloneTemplate('#tmpl-lh-category-header', this.templateContext); | |
const gaugeContainerEl = this.dom.find('.lh-score__gauge', tmpl); | |
const gaugeEl = this.renderScoreGauge(category); | |
gaugeContainerEl.appendChild(gaugeEl); | |
this.dom.find('.lh-category-header__title', tmpl).appendChild( | |
this.dom.convertMarkdownCodeSnippets(category.title)); | |
if (category.description) { | |
const descEl = this.dom.convertMarkdownLinkSnippets(category.description); | |
this.dom.find('.lh-category-header__description', tmpl).appendChild(descEl); | |
} | |
return /** @type {Element} */ (tmpl.firstElementChild); | |
} | |
/** | |
* Renders the group container for a group of audits. Individual audit elements can be added | |
* directly to the returned element. | |
* @param {LH.Result.ReportGroup} group | |
* @param {{expandable: boolean, itemCount?: number}} opts | |
* @return {Element} | |
*/ | |
renderAuditGroup(group, opts) { | |
const expandable = opts.expandable; | |
const groupEl = this.dom.createElement(expandable ? 'details' : 'div', 'lh-audit-group'); | |
const summmaryEl = this.dom.createChildOf(groupEl, 'summary', 'lh-audit-group__summary'); | |
const headerEl = this.dom.createChildOf(summmaryEl, 'div', 'lh-audit-group__header'); | |
const itemCountEl = this.dom.createChildOf(summmaryEl, 'div', 'lh-audit-group__itemcount'); | |
if (expandable) { | |
const chevronEl = summmaryEl.appendChild(this._createChevron()); | |
chevronEl.title = Util.UIStrings.auditGroupExpandTooltip; | |
} | |
if (group.description) { | |
const auditGroupDescription = this.dom.createElement('div', 'lh-audit-group__description'); | |
auditGroupDescription.appendChild(this.dom.convertMarkdownLinkSnippets(group.description)); | |
groupEl.appendChild(auditGroupDescription); | |
} | |
headerEl.textContent = group.title; | |
if (opts.itemCount) { | |
// TODO(i18n): support multiple locales here | |
itemCountEl.textContent = `${opts.itemCount} audits`; | |
} | |
return groupEl; | |
} | |
/** | |
* Find the total number of audits contained within a section. | |
* Accounts for nested subsections like Accessibility. | |
* @param {Array<Element>} elements | |
* @return {number} | |
*/ | |
_getTotalAuditsLength(elements) { | |
// Create a scratch element to append sections to so we can reuse querySelectorAll(). | |
const scratch = this.dom.createElement('div'); | |
elements.forEach(function(element) { | |
scratch.appendChild(element); | |
}); | |
const subAudits = scratch.querySelectorAll('.lh-audit'); | |
if (subAudits.length) { | |
return subAudits.length; | |
} else { | |
return elements.length; | |
} | |
} | |
/** | |
* @param {Array<Element>} elements | |
* @return {Element} | |
*/ | |
_renderFailedAuditsSection(elements) { | |
const failedElem = this.dom.createElement('div'); | |
failedElem.classList.add('lh-failed-audits'); | |
elements.forEach(elem => failedElem.appendChild(elem)); | |
return failedElem; | |
} | |
/** | |
* @param {Array<Element>} elements | |
* @return {Element} | |
*/ | |
renderPassedAuditsSection(elements) { | |
const passedElem = this.renderAuditGroup({ | |
title: Util.UIStrings.passedAuditsGroupTitle, | |
}, {expandable: true, itemCount: this._getTotalAuditsLength(elements)}); | |
passedElem.classList.add('lh-passed-audits'); | |
elements.forEach(elem => passedElem.appendChild(elem)); | |
return passedElem; | |
} | |
/** | |
* @param {Array<Element>} elements | |
* @return {Element} | |
*/ | |
_renderNotApplicableAuditsSection(elements) { | |
const notApplicableElem = this.renderAuditGroup({ | |
title: Util.UIStrings.notApplicableAuditsGroupTitle, | |
}, {expandable: true, itemCount: this._getTotalAuditsLength(elements)}); | |
notApplicableElem.classList.add('lh-audit-group--not-applicable'); | |
elements.forEach(elem => notApplicableElem.appendChild(elem)); | |
return notApplicableElem; | |
} | |
/** | |
* @param {Array<LH.ReportResult.AuditRef>} manualAudits | |
* @param {string} [manualDescription] | |
* @return {Element} | |
*/ | |
_renderManualAudits(manualAudits, manualDescription) { | |
const group = {title: Util.UIStrings.manualAuditsGroupTitle, description: manualDescription}; | |
const auditGroupElem = this.renderAuditGroup(group, | |
{expandable: true, itemCount: manualAudits.length}); | |
auditGroupElem.classList.add('lh-audit-group--manual'); | |
manualAudits.forEach((audit, i) => { | |
auditGroupElem.appendChild(this.renderAudit(audit, i)); | |
}); | |
return auditGroupElem; | |
} | |
/** | |
* @param {ParentNode} context | |
*/ | |
setTemplateContext(context) { | |
this.templateContext = context; | |
this.detailsRenderer.setTemplateContext(context); | |
} | |
/** | |
* @param {LH.ReportResult.Category} category | |
* @return {DocumentFragment} | |
*/ | |
renderScoreGauge(category) { | |
const tmpl = this.dom.cloneTemplate('#tmpl-lh-gauge', this.templateContext); | |
const wrapper = /** @type {HTMLAnchorElement} */ (this.dom.find('.lh-gauge__wrapper', tmpl)); | |
wrapper.href = `#${category.id}`; | |
wrapper.classList.add(`lh-gauge__wrapper--${Util.calculateRating(category.score)}`); | |
// Cast `null` to 0 | |
const numericScore = Number(category.score); | |
const gauge = this.dom.find('.lh-gauge', tmpl); | |
// 329 is ~= 2 * Math.PI * gauge radius (53) | |
// https://codepen.io/xgad/post/svg-radial-progress-meters | |
// score of 50: `stroke-dasharray: 164.5 329`; | |
/** @type {?SVGCircleElement} */ | |
const gaugeArc = gauge.querySelector('.lh-gauge-arc'); | |
if (gaugeArc) { | |
gaugeArc.style.strokeDasharray = `${numericScore * 329} 329`; | |
} | |
const scoreOutOf100 = Math.round(numericScore * 100); | |
const percentageEl = this.dom.find('.lh-gauge__percentage', tmpl); | |
percentageEl.textContent = scoreOutOf100.toString(); | |
if (category.score === null) { | |
percentageEl.textContent = '?'; | |
percentageEl.title = Util.UIStrings.errorLabel; | |
} | |
this.dom.find('.lh-gauge__label', tmpl).textContent = category.title; | |
return tmpl; | |
} | |
/** | |
* @param {LH.ReportResult.Category} category | |
* @param {Object<string, LH.Result.ReportGroup>} [groupDefinitions] | |
* @return {Element} | |
*/ | |
render(category, groupDefinitions) { | |
const element = this.dom.createElement('div', 'lh-category'); | |
this.createPermalinkSpan(element, category.id); | |
element.appendChild(this.renderCategoryHeader(category)); | |
const auditRefs = category.auditRefs; | |
const manualAudits = auditRefs.filter(audit => audit.result.scoreDisplayMode === 'manual'); | |
const nonManualAudits = auditRefs.filter(audit => !manualAudits.includes(audit)); | |
/** @type {Object<string, {passed: Array<LH.ReportResult.AuditRef>, failed: Array<LH.ReportResult.AuditRef>, notApplicable: Array<LH.ReportResult.AuditRef>}>} */ | |
const auditsGroupedByGroup = {}; | |
const auditsUngrouped = {passed: [], failed: [], notApplicable: []}; | |
nonManualAudits.forEach(auditRef => { | |
let group; | |
if (auditRef.group) { | |
const groupId = auditRef.group; | |
if (auditsGroupedByGroup[groupId]) { | |
group = auditsGroupedByGroup[groupId]; | |
} else { | |
group = {passed: [], failed: [], notApplicable: []}; | |
auditsGroupedByGroup[groupId] = group; | |
} | |
} else { | |
group = auditsUngrouped; | |
} | |
if (auditRef.result.scoreDisplayMode === 'not-applicable') { | |
group.notApplicable.push(auditRef); | |
} else if (Util.showAsPassed(auditRef.result)) { | |
group.passed.push(auditRef); | |
} else { | |
group.failed.push(auditRef); | |
} | |
}); | |
const failedElements = /** @type {Array<Element>} */ ([]); | |
const passedElements = /** @type {Array<Element>} */ ([]); | |
const notApplicableElements = /** @type {Array<Element>} */ ([]); | |
auditsUngrouped.failed.forEach((audit, i) => failedElements.push(this.renderAudit(audit, i))); | |
auditsUngrouped.passed.forEach((audit, i) => passedElements.push(this.renderAudit(audit, i))); | |
auditsUngrouped.notApplicable.forEach((audit, i) => notApplicableElements.push( | |
this.renderAudit(audit, i))); | |
Object.keys(auditsGroupedByGroup).forEach(groupId => { | |
if (!groupDefinitions) return; // We never reach here if there aren't groups, but TSC needs convincing | |
const group = groupDefinitions[groupId]; | |
const groups = auditsGroupedByGroup[groupId]; | |
if (groups.failed.length) { | |
const auditGroupElem = this.renderAuditGroup(group, {expandable: false}); | |
groups.failed.forEach((item, i) => auditGroupElem.appendChild(this.renderAudit(item, i))); | |
auditGroupElem.classList.add('lh-audit-group--unadorned'); | |
failedElements.push(auditGroupElem); | |
} | |
if (groups.passed.length) { | |
const auditGroupElem = this.renderAuditGroup(group, {expandable: true}); | |
groups.passed.forEach((item, i) => auditGroupElem.appendChild(this.renderAudit(item, i))); | |
auditGroupElem.classList.add('lh-audit-group--unadorned'); | |
passedElements.push(auditGroupElem); | |
} | |
if (groups.notApplicable.length) { | |
const auditGroupElem = this.renderAuditGroup(group, {expandable: true}); | |
groups.notApplicable.forEach((item, i) => | |
auditGroupElem.appendChild(this.renderAudit(item, i))); | |
auditGroupElem.classList.add('lh-audit-group--unadorned'); | |
notApplicableElements.push(auditGroupElem); | |
} | |
}); | |
if (failedElements.length) { | |
const failedElem = this._renderFailedAuditsSection(failedElements); | |
element.appendChild(failedElem); | |
} | |
if (manualAudits.length) { | |
const manualEl = this._renderManualAudits(manualAudits, category.manualDescription); | |
element.appendChild(manualEl); | |
} | |
if (passedElements.length) { | |
const passedElem = this.renderPassedAuditsSection(passedElements); | |
element.appendChild(passedElem); | |
} | |
if (notApplicableElements.length) { | |
const notApplicableElem = this._renderNotApplicableAuditsSection(notApplicableElements); | |
element.appendChild(notApplicableElem); | |
} | |
return element; | |
} | |
/** | |
* Create a non-semantic span used for hash navigation of categories | |
* @param {Element} element | |
* @param {string} id | |
*/ | |
createPermalinkSpan(element, id) { | |
const permalinkEl = this.dom.createChildOf(element, 'span', 'lh-permalink'); | |
permalinkEl.id = id; | |
} | |
} | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = CategoryRenderer; | |
} else { | |
self.CategoryRenderer = CategoryRenderer; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2018 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/* globals self, Util, CategoryRenderer */ | |
/** @typedef {import('./dom.js')} DOM */ | |
/** @typedef {import('./details-renderer.js').FilmstripDetails} FilmstripDetails */ | |
/** @typedef {LH.Result.Audit.OpportunityDetails} OpportunityDetails */ | |
class PerformanceCategoryRenderer extends CategoryRenderer { | |
/** | |
* @param {LH.ReportResult.AuditRef} audit | |
* @return {Element} | |
*/ | |
_renderMetric(audit) { | |
const tmpl = this.dom.cloneTemplate('#tmpl-lh-metric', this.templateContext); | |
const element = this.dom.find('.lh-metric', tmpl); | |
element.id = audit.result.id; | |
const rating = Util.calculateRating(audit.result.score, audit.result.scoreDisplayMode); | |
element.classList.add(`lh-metric--${rating}`); | |
const titleEl = this.dom.find('.lh-metric__title', tmpl); | |
titleEl.textContent = audit.result.title; | |
const valueEl = this.dom.find('.lh-metric__value', tmpl); | |
valueEl.textContent = Util.formatDisplayValue(audit.result.displayValue); | |
const descriptionEl = this.dom.find('.lh-metric__description', tmpl); | |
descriptionEl.appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description)); | |
if (audit.result.scoreDisplayMode === 'error') { | |
descriptionEl.textContent = ''; | |
valueEl.textContent = 'Error!'; | |
const tooltip = this.dom.createChildOf(descriptionEl, 'span'); | |
tooltip.textContent = audit.result.errorMessage || 'Report error: no metric information'; | |
} | |
return element; | |
} | |
/** | |
* @param {LH.ReportResult.AuditRef} audit | |
* @param {number} index | |
* @param {number} scale | |
* @return {Element} | |
*/ | |
_renderOpportunity(audit, index, scale) { | |
const oppTmpl = this.dom.cloneTemplate('#tmpl-lh-opportunity', this.templateContext); | |
const element = this.populateAuditValues(audit, index, oppTmpl); | |
element.id = audit.result.id; | |
if (!audit.result.details || audit.result.scoreDisplayMode === 'error') { | |
return element; | |
} | |
// TODO(bckenny): remove cast when details is fully discriminated based on `type`. | |
const details = /** @type {OpportunityDetails} */ (audit.result.details); | |
if (details.type !== 'opportunity') { | |
return element; | |
} | |
// Overwrite the displayValue with opportunity's wastedMs | |
const displayEl = this.dom.find('.lh-audit__display-text', element); | |
const sparklineWidthPct = `${details.overallSavingsMs / scale * 100}%`; | |
this.dom.find('.lh-sparkline__bar', element).style.width = sparklineWidthPct; | |
displayEl.textContent = Util.formatSeconds(details.overallSavingsMs, 0.01); | |
// Set [title] tooltips | |
if (audit.result.displayValue) { | |
const displayValue = Util.formatDisplayValue(audit.result.displayValue); | |
this.dom.find('.lh-load-opportunity__sparkline', element).title = displayValue; | |
displayEl.title = displayValue; | |
} | |
return element; | |
} | |
/** | |
* Get an audit's wastedMs to sort the opportunity by, and scale the sparkline width | |
* Opportunties with an error won't have a details object, so MIN_VALUE is returned to keep any | |
* erroring opportunities last in sort order. | |
* @param {LH.ReportResult.AuditRef} audit | |
* @return {number} | |
*/ | |
_getWastedMs(audit) { | |
if (audit.result.details && audit.result.details.type === 'opportunity') { | |
// TODO(bckenny): remove cast when details is fully discriminated based on `type`. | |
const details = /** @type {OpportunityDetails} */ (audit.result.details); | |
if (typeof details.overallSavingsMs !== 'number') { | |
throw new Error('non-opportunity details passed to _getWastedMs'); | |
} | |
return details.overallSavingsMs; | |
} else { | |
return Number.MIN_VALUE; | |
} | |
} | |
/** | |
* @param {LH.ReportResult.Category} category | |
* @param {Object<string, LH.Result.ReportGroup>} groups | |
* @param {'PSI'=} environment 'PSI' and undefined are the only valid values | |
* @return {Element} | |
* @override | |
*/ | |
render(category, groups, environment) { | |
const element = this.dom.createElement('div', 'lh-category'); | |
if (environment === 'PSI') { | |
const gaugeEl = this.dom.createElement('div', 'lh-score__gauge'); | |
gaugeEl.appendChild(this.renderScoreGauge(category)); | |
element.appendChild(gaugeEl); | |
} else { | |
this.createPermalinkSpan(element, category.id); | |
element.appendChild(this.renderCategoryHeader(category)); | |
} | |
// Metrics | |
const metricAudits = category.auditRefs.filter(audit => audit.group === 'metrics'); | |
const metricAuditsEl = this.renderAuditGroup(groups.metrics, {expandable: false}); | |
const keyMetrics = metricAudits.filter(a => a.weight >= 3); | |
const otherMetrics = metricAudits.filter(a => a.weight < 3); | |
const metricsBoxesEl = this.dom.createChildOf(metricAuditsEl, 'div', 'lh-columns'); | |
const metricsColumn1El = this.dom.createChildOf(metricsBoxesEl, 'div', 'lh-column'); | |
const metricsColumn2El = this.dom.createChildOf(metricsBoxesEl, 'div', 'lh-column'); | |
keyMetrics.forEach(item => { | |
metricsColumn1El.appendChild(this._renderMetric(item)); | |
}); | |
otherMetrics.forEach(item => { | |
metricsColumn2El.appendChild(this._renderMetric(item)); | |
}); | |
// 'Values are estimated and may vary' is used as the category description for PSI | |
if (environment !== 'PSI') { | |
const estValuesEl = this.dom.createChildOf(metricsColumn2El, 'div', | |
'lh-metrics__disclaimer lh-metrics__disclaimer'); | |
estValuesEl.textContent = Util.UIStrings.varianceDisclaimer; | |
} | |
metricAuditsEl.classList.add('lh-audit-group--metrics'); | |
element.appendChild(metricAuditsEl); | |
// Filmstrip | |
const timelineEl = this.dom.createChildOf(element, 'div', 'lh-filmstrip-container'); | |
const thumbnailAudit = category.auditRefs.find(audit => audit.id === 'screenshot-thumbnails'); | |
const thumbnailResult = thumbnailAudit && thumbnailAudit.result; | |
if (thumbnailResult && thumbnailResult.details) { | |
timelineEl.id = thumbnailResult.id; | |
const filmstripEl = this.detailsRenderer.render(thumbnailResult.details); | |
timelineEl.appendChild(filmstripEl); | |
} | |
// Opportunities | |
const opportunityAudits = category.auditRefs | |
.filter(audit => audit.group === 'load-opportunities' && !Util.showAsPassed(audit.result)) | |
.sort((auditA, auditB) => this._getWastedMs(auditB) - this._getWastedMs(auditA)); | |
if (opportunityAudits.length) { | |
// Scale the sparklines relative to savings, minimum 2s to not overstate small savings | |
const minimumScale = 2000; | |
const wastedMsValues = opportunityAudits.map(audit => this._getWastedMs(audit)); | |
const maxWaste = Math.max(...wastedMsValues); | |
const scale = Math.max(Math.ceil(maxWaste / 1000) * 1000, minimumScale); | |
const groupEl = this.renderAuditGroup(groups['load-opportunities'], {expandable: false}); | |
const tmpl = this.dom.cloneTemplate('#tmpl-lh-opportunity-header', this.templateContext); | |
this.dom.find('.lh-load-opportunity__col--one', tmpl).textContent = | |
Util.UIStrings.opportunityResourceColumnLabel; | |
this.dom.find('.lh-load-opportunity__col--two', tmpl).textContent = | |
Util.UIStrings.opportunitySavingsColumnLabel; | |
const headerEl = this.dom.find('.lh-load-opportunity__header', tmpl); | |
groupEl.appendChild(headerEl); | |
opportunityAudits.forEach((item, i) => | |
groupEl.appendChild(this._renderOpportunity(item, i, scale))); | |
groupEl.classList.add('lh-audit-group--opportunities'); | |
element.appendChild(groupEl); | |
} | |
// Diagnostics | |
const diagnosticAudits = category.auditRefs | |
.filter(audit => audit.group === 'diagnostics' && !Util.showAsPassed(audit.result)) | |
.sort((a, b) => { | |
const scoreA = a.result.scoreDisplayMode === 'informative' ? 100 : Number(a.result.score); | |
const scoreB = b.result.scoreDisplayMode === 'informative' ? 100 : Number(b.result.score); | |
return scoreA - scoreB; | |
}); | |
if (diagnosticAudits.length) { | |
const groupEl = this.renderAuditGroup(groups['diagnostics'], {expandable: false}); | |
diagnosticAudits.forEach((item, i) => groupEl.appendChild(this.renderAudit(item, i))); | |
groupEl.classList.add('lh-audit-group--diagnostics'); | |
element.appendChild(groupEl); | |
} | |
// Passed audits | |
const passedElements = category.auditRefs | |
.filter(audit => (audit.group === 'load-opportunities' || audit.group === 'diagnostics') && | |
Util.showAsPassed(audit.result)) | |
.map((audit, i) => this.renderAudit(audit, i)); | |
if (!passedElements.length) return element; | |
const passedElem = this.renderPassedAuditsSection(passedElements); | |
element.appendChild(passedElem); | |
return element; | |
} | |
} | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = PerformanceCategoryRenderer; | |
} else { | |
self.PerformanceCategoryRenderer = PerformanceCategoryRenderer; | |
} | |
; | |
/** | |
* @license | |
* Copyright 2017 Google Inc. All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS-IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
'use strict'; | |
/** | |
* @fileoverview The entry point for rendering the Lighthouse report based on the JSON output. | |
* This file is injected into the report HTML along with the JSON report. | |
* | |
* Dummy text for ensuring report robustness: \u003c/script> pre$`post %%LIGHTHOUSE_JSON%% | |
*/ | |
/** @typedef {import('./dom.js')} DOM */ | |
/** @typedef {import('./details-renderer.js').DetailsJSON} DetailsJSON */ | |
/* globals self, Util, DetailsRenderer, CategoryRenderer, PerformanceCategoryRenderer */ | |
class ReportRenderer { | |
/** | |
* @param {DOM} dom | |
*/ | |
constructor(dom) { | |
/** @type {DOM} */ | |
this._dom = dom; | |
/** @type {ParentNode} */ | |
this._templateContext = this._dom.document(); | |
} | |
/** | |
* @param {LH.Result} result | |
* @param {Element} container Parent element to render the report into. | |
*/ | |
renderReport(result, container) { | |
// Mutate the UIStrings if necessary (while saving originals) | |
const originalUIStrings = JSON.parse(JSON.stringify(Util.UIStrings)); | |
const report = Util.prepareReportResult(result); | |
container.textContent = ''; // Remove previous report. | |
container.appendChild(this._renderReport(report)); | |
// put the UIStrings back into original state | |
Util.updateAllUIStrings(originalUIStrings); | |
return /** @type {Element} **/ (container); | |
} | |
/** | |
* Define a custom element for <templates> to be extracted from. For example: | |
* this.setTemplateContext(new DOMParser().parseFromString(htmlStr, 'text/html')) | |
* @param {ParentNode} context | |
*/ | |
setTemplateContext(context) { | |
this._templateContext = context; | |
} | |
/** | |
* @param {LH.ReportResult} report | |
* @return {DocumentFragment} | |
*/ | |
_renderReportHeader(report) { | |
const el = this._dom.cloneTemplate('#tmpl-lh-heading', this._templateContext); | |
const domFragment = this._dom.cloneTemplate('#tmpl-lh-scores-wrapper', this._templateContext); | |
const placeholder = this._dom.find('.lh-scores-wrapper-placeholder', el); | |
/** @type {HTMLDivElement} */ (placeholder.parentNode).replaceChild(domFragment, placeholder); | |
this._dom.find('.lh-config__timestamp', el).textContent = | |
Util.formatDateTime(report.fetchTime); | |
this._dom.find('.lh-product-info__version', el).textContent = report.lighthouseVersion; | |
const metadataUrl = /** @type {HTMLAnchorElement} */ (this._dom.find('.lh-metadata__url', el)); | |
const toolbarUrl = /** @type {HTMLAnchorElement}*/ (this._dom.find('.lh-toolbar__url', el)); | |
metadataUrl.href = metadataUrl.textContent = report.finalUrl; | |
toolbarUrl.href = toolbarUrl.textContent = report.finalUrl; | |
const emulationDescriptions = Util.getEmulationDescriptions(report.configSettings || {}); | |
this._dom.find('.lh-config__emulation', el).textContent = emulationDescriptions.summary; | |
return el; | |
} | |
/** | |
* @return {Element} | |
*/ | |
_renderReportShortHeader() { | |
const shortHeaderContainer = this._dom.createElement('div', 'lh-header-container'); | |
const wrapper = this._dom.cloneTemplate('#tmpl-lh-scores-wrapper', this._templateContext); | |
shortHeaderContainer.appendChild(wrapper); | |
return shortHeaderContainer; | |
} | |
/** | |
* @param {LH.ReportResult} report | |
* @return {DocumentFragment} | |
*/ | |
_renderReportFooter(report) { | |
const footer = this._dom.cloneTemplate('#tmpl-lh-footer', this._templateContext); | |
const env = this._dom.find('.lh-env__items', footer); | |
env.id = 'runtime-settings'; | |
const envValues = Util.getEnvironmentDisplayValues(report.configSettings || {}); | |
[ | |
{name: 'URL', description: report.finalUrl}, | |
{name: 'Fetch time', description: Util.formatDateTime(report.fetchTime)}, | |
...envValues, | |
{name: 'User agent (host)', description: report.userAgent}, | |
{name: 'User agent (network)', description: report.environment && | |
report.environment.networkUserAgent}, | |
{name: 'CPU/Memory Power', description: report.environment && | |
report.environment.benchmarkIndex.toFixed(0)}, | |
].forEach(runtime => { | |
if (!runtime.description) return; | |
const item = this._dom.cloneTemplate('#tmpl-lh-env__items', env); | |
this._dom.find('.lh-env__name', item).textContent = `${runtime.name}:`; | |
this._dom.find('.lh-env__description', item).textContent = runtime.description; | |
env.appendChild(item); | |
}); | |
this._dom.find('.lh-footer__version', footer).textContent = report.lighthouseVersion; | |
return footer; | |
} | |
/** | |
* Returns a div with a list of top-level warnings, or an empty div if no warnings. | |
* @param {LH.ReportResult} report | |
* @return {Node} | |
*/ | |
_renderReportWarnings(report) { | |
if (!report.runWarnings || report.runWarnings.length === 0) { | |
return this._dom.createElement('div'); | |
} | |
const container = this._dom.cloneTemplate('#tmpl-lh-warnings--toplevel', this._templateContext); | |
const message = this._dom.find('.lh-warnings__msg', container); | |
message.textContent = Util.UIStrings.toplevelWarningsMessage; | |
const warnings = this._dom.find('ul', container); | |
for (const warningString of report.runWarnings) { | |
const warning = warnings.appendChild(this._dom.createElement('li')); | |
warning.textContent = warningString; | |
} | |
return container; | |
} | |
/** | |
* @param {LH.ReportResult} report | |
* @return {DocumentFragment} | |
*/ | |
_renderReport(report) { | |
let header; | |
const headerContainer = this._dom.createElement('div'); | |
if (this._dom.isDevTools()) { | |
headerContainer.classList.add('lh-header-plain'); | |
header = this._renderReportShortHeader(); | |
} else { | |
headerContainer.classList.add('lh-header-sticky'); | |
header = this._renderReportHeader(report); | |
} | |
headerContainer.appendChild(header); | |
const container = this._dom.createElement('div', 'lh-container'); | |
const reportSection = container.appendChild(this._dom.createElement('div', 'lh-report')); | |
reportSection.appendChild(this._renderReportWarnings(report)); | |
let scoreHeader; | |
const isSoloCategory = report.reportCategories.length === 1; | |
if (!isSoloCategory) { | |
scoreHeader = this._dom.createElement('div', 'lh-scores-header'); | |
} else { | |
headerContainer.classList.add('lh-header--solo-category'); | |
} | |
const detailsRenderer = new DetailsRenderer(this._dom); | |
const categoryRenderer = new CategoryRenderer(this._dom, detailsRenderer); | |
categoryRenderer.setTemplateContext(this._templateContext); | |
const perfCategoryRenderer = new PerformanceCategoryRenderer(this._dom, detailsRenderer); | |
perfCategoryRenderer.setTemplateContext(this._templateContext); | |
const categories = reportSection.appendChild(this._dom.createElement('div', 'lh-categories')); | |
for (const category of report.reportCategories) { | |
if (scoreHeader) { | |
scoreHeader.appendChild(categoryRenderer.renderScoreGauge(category)); | |
} | |
let renderer = categoryRenderer; | |
if (category.id === 'performance') { | |
renderer = perfCategoryRenderer; | |
} | |
categories.appendChild(renderer.render(category, report.categoryGroups)); | |
} | |
if (scoreHeader) { | |
const scoreScale = this._dom.cloneTemplate('#tmpl-lh-scorescale', this._templateContext); | |
this._dom.find('.lh-scorescale-label', scoreScale).textContent = | |
Util.UIStrings.scorescaleLabel; | |
const scoresContainer = this._dom.find('.lh-scores-container', headerContainer); | |
scoresContainer.appendChild(scoreHeader); | |
scoresContainer.appendChild(scoreScale); | |
} | |
reportSection.appendChild(this._renderReportFooter(report)); | |
const reportFragment = this._dom.createFragment(); | |
reportFragment.appendChild(headerContainer); | |
reportFragment.appendChild(container); | |
return reportFragment; | |
} | |
} | |
/** @type {LH.I18NRendererStrings} */ | |
ReportRenderer._UIStringsStash = {}; | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = ReportRenderer; | |
} else { | |
self.ReportRenderer = ReportRenderer; | |
} | |
//# sourceURL=compiled-reportrenderer.js | |
</script> | |
<script>window.__LIGHTHOUSE_JSON__ = {"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36","lighthouseVersion":"3.0.3","fetchTime":"2018-10-19T12:46:33.253Z","requestedUrl":"https://perjerz3434.github.io/who-use-angular-in-thailand/","finalUrl":"https://perjerz3434.github.io/who-use-angular-in-thailand/","runWarnings":[],"audits":{"is-on-https":{"id":"is-on-https","title":"Uses HTTPS","description":"All sites should be protected with HTTPS, even ones that don't handle sensitive data. HTTPS prevents intruders from tampering with or passively listening in on the communications between your app and your users, and is a prerequisite for HTTP/2 and many new web platform APIs. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/https).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":"","details":{"type":"table","headings":[],"items":[]}},"redirects-http":{"id":"redirects-http","title":"Redirects HTTP traffic to HTTPS","description":"If you've already set up HTTPS, make sure that you redirect all HTTP traffic to HTTPS. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-redirects-to-https).","score":1,"scoreDisplayMode":"binary","rawValue":true},"service-worker":{"id":"service-worker","title":"Registers a service worker","description":"The service worker is the technology that enables your app to use many Progressive Web App features, such as offline, add to homescreen, and push notifications. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/registered-service-worker).","score":1,"scoreDisplayMode":"binary","rawValue":true},"works-offline":{"id":"works-offline","title":"Responds with a 200 when offline","description":"If you're building a Progressive Web App, consider using a service worker so that your app can work offline. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-200-when-offline).","score":1,"scoreDisplayMode":"binary","rawValue":true,"warnings":[]},"viewport":{"id":"viewport","title":"Has a `\u003cmeta name=\"viewport\">` tag with `width` or `initial-scale`","description":"Add a viewport meta tag to optimize your app for mobile screens. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/has-viewport-meta-tag).","score":1,"scoreDisplayMode":"binary","rawValue":true,"warnings":[]},"without-javascript":{"id":"without-javascript","title":"Contains some content when JavaScript is not available","description":"Your app should display some content when JavaScript is disabled, even if it's just a warning to the user that JavaScript is required to use the app. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/no-js).","score":1,"scoreDisplayMode":"binary","rawValue":true},"first-contentful-paint":{"id":"first-contentful-paint","title":"First Contentful Paint","description":"First contentful paint marks the time at which the first text/image is painted. [Learn more](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#first_paint_and_first_contentful_paint).","score":0.92,"scoreDisplayMode":"numeric","rawValue":2224.2035,"displayValue":["%10d ms",2224.2035]},"first-meaningful-paint":{"id":"first-meaningful-paint","title":"First Meaningful Paint","description":"First Meaningful Paint measures when the primary content of a page is visible. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint).","score":0.92,"scoreDisplayMode":"numeric","rawValue":2224.2035,"displayValue":["%10d ms",2224.2035]},"load-fast-enough-for-pwa":{"id":"load-fast-enough-for-pwa","title":"Page load is fast enough on 3G","description":"A fast page load over a 3G network ensures a good mobile user experience. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/fast-3g).","score":1,"scoreDisplayMode":"binary","rawValue":3334.7035000000005},"speed-index":{"id":"speed-index","title":"Speed Index","description":"Speed Index shows how quickly the contents of a page are visibly populated. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/speed-index).","score":0.99,"scoreDisplayMode":"numeric","rawValue":2224.2035,"displayValue":["%10d ms",2224.2035]},"screenshot-thumbnails":{"id":"screenshot-thumbnails","title":"Screenshot Thumbnails","description":"This is what the load of your site looked like.","score":null,"scoreDisplayMode":"informative","rawValue":true,"details":{"type":"filmstrip","scale":3000,"items":[{"timing":300,"timestamp":16819140546,"data":"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"},{"timing":600,"timestamp":16819440546,"data":"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"},{"timing":900,"timestamp":16819740546,"data":"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"},{"timing":1200,"timestamp":16820040546,"data":"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"},{"timing":1500,"timestamp":16820340546,"data":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRQBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFP/AABEIANUAeAMBEQACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APjWQ/bLgYUrEMDhecYx/kV/otCCwlNt/GeS/e1JSqLGIgvyAhWOefTv9Pw9RXPablzS+IvTboQhZLGdJMAqCD07f5zXXzRxUHB/ERrF36Ctm7uFUKVgXAGF5Ax/nipjBYWlr8Q23N26EzBUQxqP3e4Bjnoc9/8AP41zLnlJSl8T2/z+X6jdtkQ7HsZFkKhlOO38v1rrXLiYOMviX9XI+F3JoLOfWLsR20Dui4HyJkgY7n/E14OZ5zlnDWEliMxrqDfSTu2+lkrt/JM9zLcmzDPKsKWAoSqPulp970Xq3Y2ZPCF5b2wBRFDH7hcFjjH4fqPwr8zl4q8N+35Y4hy7yVOSivLWPM3/ANu/M+1/4hvxHTo886Ki76Lnjd+qu4r1v8kYs9ldaNcJJNFhAw5xwe+Aa/RMq4lybiSl/sGKjN2vb4ZK2l3F2dvPlttr3+NzLIszyafLjKEorvvG7/vK6v5X+RCT9ruFUDEK4GAvIGP88V9JGCwtLX4jwb+0dkTuqIpQIDHnDMeuc+/6+nqK5vflJSlu9v8AP5fqXpsiEI9hKrlQy8HOO3+c/wD166uaGIg4T+NEW5XcCRd3Crt2wjAG1ecf57VMYLC0/wC+D96VyYqigxhP3YbDHPfPv/n3rnSm5XfxF6Wt0IkV9PmV2UMhxnjtmuq8MVDlfxGVpJ3Ww6FVuIiqYiIAzz145rnqqVCfNU95GkXeOhIxjILBCmPlMOScnn8//rVjyTbspb9e3kO9hHKwx/vArgn/AFYOdvPr9K2jB1Zr2enmJu242ELcxsqYhI4OT1oqqeHnzTfMvyBNN2Q8lCdwUoFG0wgk5PP+fwrJ05y+1q9b9vl/kUWtNEMd7aLOkcsTyhTEcMACfXuBXj51GtVy3FPCNxqKlNprR3UXbX1PXyaVJZnhvrCUoe0hdPVWuuh6jBbxWybIo0hj6lUUKPyr/NqviKuJq+3rycpvdttyfq2/yP8AQihQo4emqVKmkuySS+5aHt+n/Agal+zDrvi12j/t5rkapYWpQGWXTrU+VcyKc5CBrkM3b9ynqMdtHD/7O59T8szPiWFLiOhlTXuqLjJ9FOdpRT87Qsv8Z86lUlUhlDqeCrDisqdSVJqcG7p3VtH9/TS+x9m4xnfmWnXbXZ2afyOL1mKJtRuIIVS3WPAIUAA8ZPHav794Ir4yfD2ExeYVHUnNN8z1esny6vV6Pr+B/GHF1PDUc7xGHwkFGMHayVlolfT1KnmIVOFKAcGEEnJ/z/KvuHTm3q731v2/ryPjhpZIEO8K4J4jGDt9s96uMHVkuTTzE2luNiCXMZWPEJHXkc9+/wBOtVUTw871HzIpe9sSF0IyI9oHy/Z8k5P9az9nK9r+d/0JbGFkt4v3gRwTkRgg4GeOe9aRpyqyvTdu77/15DbUVqNlgK5uIm8vHBAxkEdf1opVnf6vWBqyvEI5F8lpwo3jC46dsda0q0Ze09lzaMhSsriRRGfE820p/dAxnHXiirVVD9zT3Glze8xZrcqTcRHy8dR3B7/r9KVGs5P2FXUJKy5kIkq+U02B5gwMDjnHr/WidKXtY0oS0Y+a6uOt0dnS6lYKFIb5R6H0rPEOMYPCwV+b3XftZt/eth03JP2sXZp3+elvue59QfDv4K+IfidarcaWIooJr+HS7eSYsRNcyfOyjaGICQiSVmIwFQ4ycCv8v6WHdb0vY/vPP+JcJkX7rEaycZSt5K619ZWgt9X2uz33WfjF8G/DnjHTtLvr/wAbX1jo+lv4TeG0jtW0q7sseVOXAbzHEhG8umGO1CvQCvdVaip8j3WnkfhL4c4mxeFlja1OEZVpKrq2p81/dta0UktLNW1+753+K/wLvPhtLrc8Wp2mqaZp+oRWqTQscyW9xD59nODgKwkRZAdpIDRMMkYJ4atFwba2v/X4H6dkXEazVUqOJjyVpQbeml4uUZelpLbfVHzlrCGS/ubqJ9o8xgfXI4r/AET4Xh9VyfB4KotqcP8A0nX8Uz+TM9rvFZnisSvtTk16N3X4NFWKVRG0xUb1IGBwenr/AF+vrX0M6U/axpQlozxua6uCRGfE8xHl9doGMgdeKdSqqC9hS3BLnXMwmgKf6RCfLIOCOMgjqf1qKVeSfsKu4SikrxCOdViM2BvXAwBj9f61pVoWqex5tNxJ6XCKEznz5sbPQccZ9P6VFWvHD/uqbsJLm95jHK3Mx2LshXGdo7AVrTpxwtO7+MbfNLTYmOzywgU7MgM2en5/5Fc0XUU+a+pWmxEA1lIGOGQ4z+ddbcMRHll8ZD93XoDlbqf5QViGOg7AVMFHCwvP4wb5nZbEzIgi2KreWSNzD+VcydZz5n8T2LVrWRCFNlIGIDxnGR611e5iIuMviJd16WPcvhb8edS8JQa3a6Jfvp7azZPp91FIDh0bjcpHAcAnB6jccda/gzP/AA84h4cjWxEaftKKWsotPR6fDfmdr6tRaSu7n9hYDirhji2eFoY18tenJSjGSa95LVqVnFqVtU3q+hiaoqhYwqgDnivyOm92/n/X6H6tjOaSjJ3d3d9PufRdrX89DT8bfHTVtX+H3hnwdqNyH0rw8Jfs0EW4tIzuzbpMnB2hii9Nq5A6mv1LI+BuIOIoUpYeklSe05NRT80vjkunuxaPxvG55w9wzjsTXlUviKnLeKXM1aKVrq6Sdru8r33T6eLSyC9nJAKxA5JAr++qUYYSkm1Z9Ov5XX4n8mTcpu76krJGI9iqShI3MCPpWCdZz5pbvZDVrWRCA1lIGOGjOCfzrq9zFRcJfEiNYu/QGK3dwQo2Qgj7o6ClCEcHT5n8Q2+aWmxKwjWPYqt5ZIDMMYrmiq3NzP4v0K0I03WMqkgNGSMg/X/6xrrfLiY22l9xNuX0JIVWeLah8kgAFc4B9SfyrCpz0ZKU3dP8BpqSsSCRccrhRwYdxyTz2xz/AF/OsZU5OW9+txq3UaXEMWH2sNx/dghu/wCtXGDqT93fuJuy1Gwqs8JCEQsAAVz146/pTqKVGonNc3mJe8tCQSJjlMAcGLcck/1/r+dZOE27N77S7eRd7jGkWGEbyrruP7vhu9aQg60k4PbqLmSWo2ILcQFYz5RGAVzgH3/SqqqeHqc03e/Xt6Ci1JJP7u/+XysaS67dfZxF50hRMDyyxL5x0B/Lv2+tfB4rgbIsVmP9ozw0XU3uklG/dxWnN5n2NHi7OqOC/s9YiTp+bu0uye9vIoSSeVGfNYSZYny8hsc9M96+6pU25pUtGuvp/XQ+QnNvWTv/AF+PzuMhCzwkIfKIABU9+OT+lVUjKhUXOuZa/L+vuMkote6rfqSrIpH3eBwYcnk8/n/X86xcJt2b32l28jW9xpdYIgJNrru/1Y+bvWlODqz5qb26i5klqNhVbiEiMiFhgFc4zx1P5daurz4ea59fMSakrD967eEOB8vkZPzHn/Pv+dYulNu3Nd7836D0S1EdlghAch1Jz5YIbvx9frVRpurK8NLBflV2MnhK/wCkRfu8demc960o1+ZqjV3FKP2kJBKFiachS4IXAGD/AJ96K9Fxl7FOy3EpWjcntNJvL2S1ka2llFwR5SKpJkG7b8o6sNwI4zkgjrUVcXSw96FOST13fbV/hZ9BqLm+YiurWS3keUIbdkba8bcMrD7wI9Qe3/6q0pV1JrD1db/8P/WrBq3vIbBKEia4IUupx93Bp1KTdRUYPRiUtLkkNjPPbtfSxsbVGVS4BKgndgH0zsbAOM7Wx904zrYmnh2sLTa530Go8/vMZLCwc3EWIlBHcDB4zV0K3O1Qq6hKP2kXYdH1FNV/s5tOuP7Z+0izFgLdvtBm3bPL8vG7fu+XbjdkEYzXJUnRdNVIVEqTi5J30ta/M32tbysCbtfqTWPg/XNRfzF0e/nI2ERJayFiGyV4xwCASM43YOM4OLr5hg8KvY06iv69t/1QKEpPmZm3Nu8Y+0Rrs7hehPY47df8joNadZOX1SrJN/0/lpYJJx95GhN4e1bTNIXWLvSLyCwZ0jS7ltXSFy6llxIRtJZVYjByQpIyAaxlVo1a6wlCqm2tVdN2Ts/xauC5uXmaKkOj3s+nvq0tpN/ZqSrE1x5bGIOwYhd3QE7HwCcnY2OhrariqNGawlGS53062vHX/wAmQJOerIpLVyslzApVY+XwM7eQMnHTkgdB1H4VSqyly0KrvZL7/wDg2bCUftIbFcKqNNhS4OOnP+feqq0HzqinpuCkrXYkMJlInnwY+oHtn+VFWqqP7mnuJRc/eYjObqYImEhyBjHt/wDrq401hIc0vjG3zEkiokWxA2w/ebjg/wCcVzx53Jzk9R7HqHgP48Xnw3+Hmp+E/wDhHtP1OLUGncalclvtFvvjAi8oj7vlSBpB6lj0618hmXC+Hz3GvFyquLtFONtJdJ3/AMcVGL7W1KhN0lbpdP8AG4viv49XXjnwY+hXGk/v5y/m6kZwxnLXIlVpF2ZZ40jSGM7vkjMqgYfCrAcLQybGLGxqJ8rbS5fhspRtF30T5m5KzvZaq2te2cm2vP8AFt/qdRfftQ28gQv4NgjYSyvO8V80SpJNPdzTPGFUASK94TC8nmG38pCuSWLeFHg6rNJVMS27xteN7qKppLST35LNJx5r3eiQvaW1Ryvh/wCNieD9P1G3i8Jae0lzdXmo2+opK8M1pPcKqAoqbY/LjjUhUKZUvIVZVcrXo1+D4ZiouWJalGMYcvKuXlhFq1t9ZNy+J2Ts7vUftOS/mdP4o/aL0PXreJ7Lw5JHPdtem7sGEcFnZtNd21xH9mIyzfNanfuVSWkbbgHA8KhwVi6NZSr1opUnFppc0ppNv3tVa0XZPX79CXUTun1af3Nk3xC/aaPjvTLrR5dGvfD9lq2r/wBpand29613KsTlxJFAsmzah3FxHvCBwcBQcDXCcEuDnKFdSqKCjFOOzXI/etJ7pKL0cuSTve93rOouV+7ocdovxR0/RdF0/wAPXul3j6Fa3kFxbTrJDPc2LB0kuJLYmJCs0hTbneE2bQyOyLIPqcRk9fF1Xjozj7VRs4pSSl7rSi3zWcFeL1i3zJ2ceZxIdRq0en+aOT0rxxcWPhbVPDsMAWz1CSAzOj7CwjjnCowx8y75lkAJ+9Ch6gEdcckhRx/9qVal5tNWauo3UdVt9mFmkr2lLdGUJcq5V5L7kl+h2vh/48XXhrwXZ+HYdL821gt1s7qQXLILmJX1JijgYIBOpE8MCDCpBBOV87F8OzxmOljHNKbfNHRO1vZJ+WnsrLfST00aeymo7HSeH/2pV8Marqtxd+F59Utr+7srpRPrcolItlkURzPs/fqyyMrK4Klc8Z2sPB/1Gp4ugqMMVaS5r2p235VtzN6ON9Hu7d0KUuVa7HM/ED4/3nxK0vVtOnsJ7GK9uGdWtrzCmM3LTpDOuzMyRBtsS7l2bnPzbgF+gy3hmOSYiGJjVu4RSUeWyT5IwvF82kvdvN63Ta7i9rdcp5dIiJF5aBthOGbA4Oa+ugpynzz3I6WIwr6fKCw3xkg4I/zz1rpl7PFLe0kQk4+g6MiW3dYyIfl2sCevHP8A+usqinRnFz94tPm2JNy7c4KIODHyT9Px/wA9TWPJNzVnd9H09B9SMyiKPEgVkz/qw3PX1/zitFT9pUTpu193/Xn/AMDUXNyq0j2Sx8bfCVLmNE8LXZ026j02W9hktPngljNuLuOFzeFjHIqXUm4kPueNMqqsT+eYrKuInWjiK2Ii5U+fk2+0p8rf7vdXimrNOzd7tGqlCUUktepN4j+I3wuPiDVptB8E3dvpyaeLfS5biWUXUdz9iwJnX7Syblu0jZQAVKSzFgzFQMcBw/m9ChGlUrxvJvnsk1yOVuVNxUrODlfZ3UUmle45QTVl/Wpr6748+A+rQ6wbvwtrX23Ubi9mF/HbBWt/Na6aLy4FvVTMbSWgyTtZYXGwFtzTl+T8SYRQhh60FGHKlF2to4c3vezcrSXOmlr8NnyrlKnOm4W66fLQ8+8P+J/AUrvcap4YMDQC1RLWxaXyLhFuQ87yA3ClJGh3LlTs6gIuQ6+/iMuzjDc1GliVyWai2lde7aK0g00patWT2ad42eV4zjtrr+ZqXHjfwNfapNBPpNynhpiiravpqyXCyC2lQzjy7uIq7OYyY1k8tixbHyKK8WhkWZ4Wj/s1SKrN35teW14vlknGSezala+yd+aTWkpRtbpf/MdcePPh3M/iF7/w7qN81zql1fWQYxInkhgtpbuqMrIio0xYxSIMlBtbYpXWGQ5vD2EsFXjGUKfJs3G9m5S1VrufLZcrulvG7QOpFO8l1R1MPiD4DfZre9bw5qMFvc3VxusYC8s9tCt9HLFvL3QVg9qHgJ4ZCxb94QGPDOhxfHEOEq0Woqzm+VKTceiUW0lK7d/iaWkU7JRcW2/P9WVPEHjT4T6lLayeHdCvLHxBd6qZ7nU9dt82lokk4YbIIpWDKq7vlaNgQx4PAWv7I4ihh6uG+sL2apWhGL3kopLWUU1d3e9k7dFZilBxSMmx8WeBW8JaLom1rDXbOaLZrEmlwhTI11vme6mEsjSwpGzIEETM3koQQHaOrrZFj6+MliqcYulZ/u23/La0ErRjKXW75VdropN1JxcOXy/z/wAzyKNllhdYsQgjBGeMdevb61+lz5qM06nvGKs9iQsuwHbhQADEeTn0/wA/1rLkm5qzu+j6eg72ZH5ojjIlUOhb/V7ske2e/TrWsabnPmpaO3yJvZajZomR2nhygU9sAg9/84qqdZtewrjat8IkVwio82xd4IAHpxTqUZc6oqWlhKWlxEhacefMAEPYcZ5wf5UVKnsEqNPcUVze8xZoWRmnhBjwegIyD3/ziijV5v3NUclZcyNnw/4autdtJry2m0mIxuI/LvdVtbR87eoWWRSR/tYxkH0NcOKrxw9VYdcz0T92MpaO6+yn2BarmZfX4aavJ+/uLzw+EOOB4i08A+v/AC36cVMszoUV7Ckp386dT/5Eai3q2LJ8NNX3NPBd6DHtPI/4SLTwQe//AC3rOlm9GS9hWUv/AAXUv/6T3HKLT5ojofh3qahpjdeHtwIGP+Ej070/670p42ldU1z8v/Xuov8A2z/hwWqv1Gf8Kz1aXM893oAjPYeItPH1/wCW/SnLN8PSiqVHmv8A9e6n/wAiJQbd5Cv8NNYZ2uILzQUCn/oY9PBB7/8ALeilm1Fr2VdS/wDBdT/5AcoNLmiVdR8IXui6fNqNxcaLIIiqmO11qzuJeeOI45WY+ucHGCelVHE061aOHpcy5u8JpbN7yil0Dpc5+OJpx584+QjPHfseK9KdR4ePsKe/mSk5e8x08DRs1xBlFB6dCCOv8xU06ra9jiBOLWqEhnRQ0xRdwIAX8KqdGXOqKl7thqWlxUiM+Z5gBGccLgZGcf0NKrVWHSpU3qKK5veZGxW6mAQBIhjkL2x1q6dNYSHO9Zg3zPQmZY40Eag7TwzDnHbv/kfjXOvaSqKrfXp+uhWiIgr2Dh2UMpxzj/PvXVzQxcbfaRGsfQGIupgqDbGCBkD8KUYrCwcqj98JPm0Wxat4rUzwwTtJHaGRRPPEodo1yATtYgE47EjnjIzXh89ZYypUb97kjy30/wCfnk12LduVJHba3f8Aw4ttBv5tK0fWrLXppInto5JEe0hG2PemS+5gjLKEYg5Vzv3EKV+bwy4hxNenGvJOKS5muX+a70VtOVpbavZmi5Y9C1rMXwl231rYXni+8v4pLqG1vI4bdLSZRFItvLhtsih5BE7K2SqMy8sATphpcR0JqdenHlfI902k5JyW+to3XnLVK2pVqTutTO09fhzb+EJ49SfxTN4jeWNYzaQ2ws0GI/NLlm3k587HGP8AV5AJIp1pcSyxCnSUVHXte2ttL2taztfdvdauUoJWaJRD8NNL02XzJfFc2qeUnky27W62zMd5dXDLvAB8sA45w55G0mYy4jxjSkoR3vrrpa1teuvyt1uK1OEdO47wH/wru58cST+In1A+HIr+IW1jcwM4mtTPGrmeWB1kDrCZW/dgfMo5P3W9PMaGcUcHCGGsqsotzkpWalySaUVJNWc+VN32utm5RcfZznaWxwsyIiCGNMQiTaZBz7d+n49OOma78RCf1ig56ybdrrf3JPt3svnt3m0VpEh2vYuHZQyHHX0/z+Fe37mMi4/aXyMtYu72EZxdyqq4WIHqo/X/ACaKcI4SHPL4xt8z0JmWNF8tR8hYBn4OO3f/ACPxrmSrOftOu69OuhWiIwr2MgZ1DIcZJHbP+faup8uLjZO0l95K9z0PRI/2dvipJEQnwy8aQscAqdAu8N9f3dfCvjPIFLXHU5fN/wCRaptqyViUfs9/FUoSPhf4yCYIMbeH7w5/8h8/59TWL4vyNzv9ejr1vt5W7MtQaEb9nn4qiEb/AIYeNGGc+WPD92foM+Xz9ePxq/8AW/h72l442CffX/IOSVrWuRp+zr8VXhxH8MfGsDYwQ3h+7wx/79/rWkuMuH1UvLG0397J9nLtYkP7PfxVkjXPwt8ZeWmf3baBedSOT/q+f/rV51bibhuvPmq4qnJ932XTVbb/AHl8jEP7O/xUFsof4X+NGG7OweH7sn6Z8vJ+vH41n/b/AAnzvlxFK73fKn+aYnGSGJ+zt8VJoSqfDLxpCxABU+H7vDfX91+ta/6x8Jwn/Hov5L/L52EoyZIP2evimYsD4WeMRHg7o28P3hyf+/fP+fU1g8/4Went6Tv15V923XYrlkIf2ePimtuqv8L/ABowzkxjw/dk9Tjny+f0xWiz/hJVOb29G+mrilsrdvV/NhyyelrkSfs5/FV4Ssfwx8aQEjaQfD13hv8AyH+taPiPhSM1zYii16X2+QuSXaxPF+z58VY432fC3xkiMu14z4fvMnvz+756/pXPDiDhilUU6eIppp35rK6/BPXd+bdrD5ZMRv2efiqIBv8Ahh40cFifLXw/dt34GfL/AP1e9eouMcg9pzRx0L9d/wCvxBwlbUiT9nf4qvGfL+GPjSEngqdAu8N/5D/Wq/1zyDm1x1OXzf8AkR7JtWJv+GfPirsyPhd4yCYwYj4fvD/7T9/85NYvjDI+e/16Lfe+y7W7FcjQjfs9/FUQr5nww8asC33B4fuz3458v9ePxq/9b+H+e8cbBP5icZWP3PIOQB+tfxG3c7m7gVz6flQIAuPT8qQBtPqKADafb8qa0ANv0/KkO9hcH1FNu4N3EK59PypCALj0/KgA2n1FABtPt+VNaAG36flSGG0+o/KncHqLg+35UCG7cMOBSHcd3oEeb/Fnxz4o8HalpQ0LQZ9YsDZ3t7etb2E105MHkmOBTGwKNKHkw22Q/J8sb8ip1Wo0rnPaX8d/FOp3lxB/wqvX7XZd2UEcl0syDZMzCRnPkYBhAXfsMiZY4kIAY0lrb0/FpfrclppXKtn8fPE3iGYXej/D7UrjS4bfUmljljcSvcW93HbxwbwpWOY4nJjYFfufvFCyFXb3kv63QJ6X9PxR0V98TPEml65fRN4UvbuxGrR6dbRxWNxuEPkrI100qo6srF9oUKFUqQ8inIVLpHvcrcwLf9ojXVm0+2v/AIaa3ZXt5ayXot1jnlZIllEZyBb7i6lld1AOEIKeY7LG0Rk9Xbv+Cuvv6DcUnb0/F2LXh/46+Kdd1G0t3+FeuWCz3WmW7veSiAxrc2wnnl/eogcW5bYyoWclX+UbSKpuzt/XX/Jfeu5KXf8Arb/N/cz2emAUAFABQAUAFABQAh+8KAA9fwpgcP8AEHx3qfg3V9LS10ldSsLm3maZ9zq6Sia2jiAIVht2zSuw+9tjJAO0itqUFO6ZrGPOiqnxMu8XkV3badp8qlYreb7Y00fmOibd42IceZIAdpI2qxJGBnR0Gti3Sa2ZkwfGHWzfyWw8HTPGY0aOZbkDdK6LJsI2kKELGN3Lff2kLt8wxV9Wv9oFR8w034xa3q/haLVE8MxafcTH5LW7vHMkaG3MoLIIgd+7CeXxkh/mG3BTw2tuYfsUupu2PxKmvoSH0V7G9RmDRXlygUISAjBk38sWGU6qFYn+DeSw/K7RdxOj5kfw8+JV742a0+2+HptEe4juZljkmMskKxTLGolGxQhkVt64LAgNgkDJzqUVTV73InT5Otz0CucyCgAoAKACgAoAKAEP3hQAHr+FACPGHXaRkflVX7Am0J5S9xkeh6UrvuVditGrHJUE8fp0p3fcLsCgPUZ780rvuK7GiFFOQozRd9wuxAEX5gvPXgU9ejC6fUd5gz0IpWdibruOzxQlcq3YXOaQgoAKACgAoAQ/eFAB3FAC0AFABQAUAFAHw3+07+1v4+8D/EPxF4K0P+z9KtrMwqmoCAyXR3RJITlmKAHfj7mR65rw8XjatOcqcdLH9G8GcBZVmGX0M0xbdRzv7m0E02rPq9r7r0PGB8NfiB41+E2s/GJ9a1WfVtLuw1rctduZ2tk3i4lR87gI2KYwQAFl44FYUqdb2cq19enp3PtMxzXKcFmlHh2nThGM46xUUlzP4FLp7yve+11e6bOn+BX7a3xLXxT4Y8J6lcWHiO01DUraxa51GI/alSSRUIEiMoJ5zlwx9TXVQxU1JRlrfQ+U4i4GyieHq42hem4qUtPhfKm37vTW21l5M/SNT1r2mfzSthaQBQAUAFACH7woAO4oAWgAoAKACgAoA/Ov9tLwLeaz+05p2maRAbjU/ENlaNFF0BkLPCCSAcACIEk9ACegr5/G0nLEqMd5H9UcCZ1SwPCVXFYn4KDne270UrLzfM19x7Clx8PPDfizwx4buPilpEWiaHo1x4U1DwzLZbVv2l/d3LPMGwjPIiMeDgxn5vnY16d6cJRpc+ytY/L6+CzzH0a2YvAyc601VjPmXupLRKLTk0k9r9Fax81/Cj4QT+CP219F8EX8v2l9I1U3Ec4APmxxwtcwyEcgFlVCRzgkjtXnxp2xHL5n6bj87+vcH1MxirOUHFrzcuR/j9/kfqKmdvP6V7x/LSHUgCgAoAKAEP3hQAdxQAtABQAUAFABQB438Y/gRceNvEun+N/C2uP4a+IOkWzW1hqEiLNbPGQ4McsbowwRLIAyjI35w2AK562H55KpTdpLY+xyTiH6hRlluNpe2wlSSc4fDrpZqStLotL2dtd2fB/jT9l34t33xKGlXuhzalqeoXEkr6xC2+zfc2WlaYABeSThgG5Hy5IB8H6rVjUakrt9T+kaPGHDs8sjVpVVGEFyuL0klayikt30v2PtP4N/s461oXi+x+IHxF8SL4o8e21obGF7SJIra3hwVGSsaNM+0n53A++Rg7Vavep0Wmp1Hdn885xxIsRQqZbldP2eGk78r1bd07635dVe0bL72e/r0xXSfB6bIdSAKACgAoAQ/eFAA30zweKAOKvNR8bjW9Rt7fRtP/s1rxYbG+afLiE2okaWWPI+UTq0QCtuPmK21QhLpbhuY954u+IdnBosq+EYJZ72OVrm0jn3fZpVgaRYjIDgB2jKCRgFUyJkHoWug4q7szrGu/EESwv9hhk3XUvmRKcEQiJ9nzb/ALxkEfODw2No+8BaIVjlNU8T+P8ATbGW4XwtDcSf2xDpsUKP5hNs7ohvztc4QbmYxYDKBlnwCaqJTLk/iXxtBPfM3hqJYIzAlqQ4drh55GUFtjExrDmLzThsjey8Lgpb2IZqz3niwXdylvYWRhwfIa4cqp/euBuZWZslNj/cA4K5+b5JQ2Y2oeI/G9pptlOPDsc8lxdW0EkPljdbRySFHd1SZwfLwjsFbGH+9hCxlfG/66spdCxa6p44e81VLjR7ONbYoLK4Q/Lch13E7PMyuwjYc53FgwwAQbIbaO9oGFABQAUAFACH7woAO9AHmPiX9orwj4M1LWLXXn1HTYtMvpNOkvRp8tzC8qafFqD48kOygW8pfLhR+5k7AEiad/L/AIH+aKSbtbqJP+0f4Ht9dn019TkUQSz2slybSbYtxCheWH7mdyorkkfKCpXO75aqzbS72/Elaq6/rqdXoPxB0jxJJZiye4ZL1FktnltJYxKphSbd8yjb8ki8PtOQRjik002mB0uaQBQOwU7CuFIAoAKACgAoAKACgBD94UADf0pjR4v4s1jXIvGU9rYWjS2rapApil8LT3AkjZIElf7V8sYBQzJuOcDIJwQU6lClKG+rX4+9/kjpjTi4rv8A8OUz4lt4ohbXXga4GqLOUEo8KXIgWOJkRQGjjmy3kFwrA4ygAABFEqSUnZry183Yhwjqlt/w/wDwDO0jx/rdlrdoLbwU2mWaMI5L6Hwpdj93tY5Tb84Jkdn8rYQAzjzCxDNqqNJJPn16+pp7On3/AKuy/qHxY8fNoPhW/wD+EXu7Ce6uJzqMCaZcSfZ4lSVV3JsLkBmib/lnuKABtrsUcaVFt3kLkp7XNS5+Mmvm6uPsvhjWEgXcIkuvD96Gfah+YMo+6znIyqsAgBX95ujy9lT6SJjCPU7v4deJr/xX4aivtT0+fTL4tiW2ntpIGjJVWKbZACdm7Zv6MULDAOBzzjGMvdZlNJOyOorMgKACgAoAKACgAoAQ/eFACN3+ho2A5LVfAMN/qNxercSI891HdOrZdcoYGUKM4X5rWInAyRu7kEdKqpxSfRW/P/M6IzityO58EX93Ba2z6zOLRZDNPhnMjOHjkjZGdmK7WjxjkEMRim6kL3X9fghOUGVtN+Hd/Y3S3EnibU7p5FAuhLI22ZtysWVA22L7uAIwowz5DEgjT29P+UrngtjCu/gdd3Wn6BCvjjxHHc6KzSQXxujNNI7I6bpDLvDEB2GQAcMwJORtUa0FfQOeB0+reCtQ1b7ap8QX1nHdoyMbRmjkUFVXKtuOxhsXBUDG6UgbnDJPtY9ESpQRteFtCl8OaNb2EmoXWqGCKOL7VeyGSaTairuZjksWKliT3Y1hNxbujKTu9DXDZNQTdPYWkAZzQAUAFABQAUAIfvCgAP8ASmDPE/2jv2iLv4GN4ctbDw0fEV/rrTxW6LcGPY6eWFG0IxkJMo+UYJxgHJrjxWI+ruMYq7Z+h8JcIx4mWJqTxKpQo8rfu30kpO/xLbl1+84vwN+1l4kufjNp3ww8SeGdLudXumOdZ0O/b7IP3PmsqxurFtmGRiJPvKwA4rOGJn7RU6i1Z2YjhCj/AGPPOqFe1NX92Ufe0ly9JaX0a00UlvufRfiHxNp3hbS21DU7tLS0UhTI4J5PYAZJ4yTjoASeATXrUaNSvNQpq7Py6VWEI88tiAeN9BWGGSXWbKDzo/NRZp1jYpkgnaxBHKsOR1U+hpOhWT5VF6dhKrC12zTs9TtNQMgtbqG5MZ2uIpA2w+hx0NZSjODtO6ZcZKSuj5e+J/7ZmreGNZksdF8HXENvbTmC4utcjeEu4zkIin5eACCSSQfujv5VTGODtGOh+yZV4eRx9CNWpjEnJXSgubR6dXHW/S3zNj9nX9o658ca/wD2J4juYP7Q1ee5udLhhZWMECBWWFyvcjzCN3zfujkYZM6YfE+1laR5/FfC1PLaKxWCUnCCiptq3vS6ryVrPpdqzeoftpfH3xd8ENB8Np4TtLIza5NNbSX13CZTblVQpsXIXcdzH5gR8vQ9vVpU5VqkaUN5OyPzClTlXqRow+KTsvU+PfD/AO1N8V/BWtz6uvjeTxA0ku65sdSImtyf7ojz+7H/AFzKV9FmOSxwVOVSnXjPltdLfU+nzDIoYGjKrTxMKnK7NJ2f3a7H6YfDPxLdeM/h14X1+9jiiu9V0q1vpo4ARGrywo7BcknALHGSeO5r5g+UejOloEFABQAh+8KABv6UBe2p4b+0d8HNf+IeoeFPEHhuWzOq+GDdz2lteSGMNPIieRIrbWBaOWKNwjDa54YgZzhiKXtbSjurn3nC2d4fLIV8DjG1Rr8im4q7UIuXMu9pRfK2tUrtanmn7OvwF8anxd4V8ZeN9J0vQr7w+t/BbRWSRW8skUu5Uje3gjEKhXluZA4O5vN5Xo1c9ClUk1Vq7o+j4pz7LaeGxOWZTN1KdXlavdqNuXRSk3J3UYqz0VtOqX03428Dab4+0V9L1RXa3LB1KEZRwCAwBBUkZOMggdeoBHt4bFVcJV9tRdmfjFahCvDknsR2Hw28P6d9lMOniNrZVWPZK6L8sjyAlFIXh5HYccbuMDin9cxGvvb+S7JfkhPC0na6/FmzpOiWWhW/kWMRhh7R+YzBfYAk4HfA7knqaxrVp15c1R3ZrTpxpq0Uea/HTwj4o8Y6HNpujnRZ9Fu7OaG/ttYd4xG26No5kZVYkrtfAJUAsrHOOOOrTlUTUbWPsOG8dgstxKxWIU/axlFwcLdpJp36PR9bJNLV3PEf2cf2Zdb0H4j2/ijVkm07TdOmd7OG5VVnulZZUVnVWPlkDY5HowHPNefhsK4VHKXTY/QeLuLaWLy2GW0JKcpJe0avaLTjK0e+t12XQ9N/bH+C/iH41/DPTtO8LG0/tjTdTTUUW7lMZkRYZlMaNgjeWdMbiF45Ir26NWdGpGrTdnHVH4vSqzoVI1ab96OqPgzwB+zh48+IHiS90Sx8IXWiX0LlL651YSQ29oSFb5mKk5YMpAXcSG3AY5r1q2NwnJKUMO41Jbu91r/X+R7mIxuDcZyp4flqS3d7rXeyP1I+G/hyXwf4A8OaDO8ck2labbWLvESUZo4lQkZAOMqcZArwYpJWTufOxSSsnc6SqGFABQAh+8KAK97LcRw7rSKK4lz9yWUxjH1Ct/Ki9wKH23Wh/wAwyy/8Dn/+M0xh9u1r/oGWX/gc/wD8ZpLXYLMPt2tf9A2y/wDA5/8A41RsFhftut/9Ayy/8Dn/APjNMA+263/0DLL/AMDn/wDjNK6QCfbtaP8AzDLL/wADn/8AjVF09hB9t1v/AKBll/4HP/8AGaBh9t1r/oGWX/gc/wD8ZoWuwWAX2tH/AJhll/4HP/8AGqAsH27Wv+gZZf8Agc//AMZpiF+263/0DLL/AMDn/wDjNK6GJ9u1r/oGWX/gc/8A8aounsIPtutf9Ayy/wDA5/8A4zTGXbCa8mDG8t4bdgflEUxkz+ariiwWPw1T9ov4qTRZj+J3jKMgAHPiC6Oe5/5afrX921OGsooy9/B0mv8Ar3H/AOROFTctmTf8NG/FXaGHxM8Yqo4KNr92Wzjp/rOvFTLhjKHKywVK76+zil+Q+drqMP7R3xTRP3nxL8ZAEn5f+Egutw/8iZP+etEeGMlnO8MHS8/3cWvusiHOSjqRx/tFfFOWHMfxP8ZRsAAQ3iC6OfX/AJacfWrqcNZNQnHnwNFp6aUo7/cKMm72ZP8A8NHfFTbn/hZfjEKowVOv3ec+n+s9qyXDGT82mBpO9/8Al1G2m/Toac0u4xv2jvinGmX+JnjIDJ+X/hILrcPbPmZP+etaLhjJ6k0oYSlr/wBO426dOXzRPtJdyNP2i/ipLFmP4n+Mo2AAO7xBdHPr/wAtM/jRU4ayijJe0wVK3f2cf/kR87b0ZOf2jvipt3D4l+MVAABU6/dk59P9Z14qZcL5Q5WWCpa63VONvyGpvuMP7RnxSjTMnxM8YgZJx/wkF1u+mfMzQuF8mqVF7PB0v/BcWvyRDnLl1I0/aL+KksJ8v4n+Mo2AAOfEF0c/+RM/jTqcNZNQkufA0mn1VKP+XUIybJ/+Gjfipt3f8LM8YqqjBRtfu85/7+UlwvlClb6jS7/wo7elrlc77jG/aN+KaJ+8+JfjIAk4H/CQXW4e2fM5/wA9aceGcmqTfs8HS8/3cbf+ki9pJK9xiftF/FSaLdH8TvGUZAAIPiC6Of8AyJ+tFThvJ6M7TwdJr/r3H/5Eam5bMmP7RvxVA3f8LL8Yqo4KHX7stn0/1nXilLhjJ3Ll+pUdevso2/IfO11GN+0Z8Uo1y/xL8Y8k/KPEF1u6+vmZ/GiPC+SzqXp4Klt/z7jYlzaWrPNbn/RrkNESmQDgfSvrMJN4qPsqhnP3diS2kUt5uz5hgD8utYVVK6p30bsWtrkcTfapvnHGM7R0/wA/412S/wBnpWh5fi7f8EzXvS1PqHTP2Q7KNfHkcviAy3Gl6BfajaTCzKiOS11iazPyiXB3paP14Xz+hKAn8WnxtjPaYOjKmrVJxUn1tKjTk1tprUdn/dXS6ejirnJ3v7NK6X8UrHwmfERma4tbW4+3fYdu0zamthjZ5h+7v8zrzjb/ALQ9WjxXXqZY8U6avzSVk3aypOqvxsn3tfrY25ErB44/Zgbwj8Ol8WP4lW9xa2lybMaeYwfOMQK7vNOMeZ1xzg+vG2A4txFXFLCxppLmkr7vTm/yRlyqT1Opv/2KG0vw/petp40yby6sLYwDSsBftN6bXdnzuduN+Mc9OOteBLj7E8zoTop8t9bvsn28y1SXOkYuj/s22cNr4n+1av8Aa7uCytzaTi1KeRK+tmwMhXzCG+S3lO08fv8A1QMe2XE+OnhaFaFlzOaa01SoKolt3dvRCcVGRjv+zn5HxZ0zwdNryXIv3vLYXjWLKIjBeTWu8RiUZLGHfjdgbsc4yfV/1nrwyaWNhBJxcNPJqErbf3rfIXs1KaTO18BfslaZqXxP8c+Gr7W5ZjoVtbmCeO28tHe5spZFZk3k/u3KNgPhthBwGwPGzPi7G08uwdaMVerKXN/27NrTtdK1913NY0Y+0sN0H9lXT9L8UXVrqOrJq0Jt/EEEZa0eFo5bGF0jmBWbBJkKSbSNoCbec5rnrcU42oqdKNo8ypyb3+OcLrVPpJq6s/uVkoK9zWv/ANgsWj6E8vjjzhqe07RpG3yv9Cmuj/y3Of8AUhe33ifainx/inGtSjRS9ndLVv7cIJ6+UmTyKU0mfJ2oxiyvpfJyi5OB6cmv2XBzeKh7OoYVPcqWQQSqW8zYN2Rg/XNY1VK6p30bsWtrjIMXdypkHHHyjgdRXXWf1elaBkvelqf/2Q=="},{"timing":1800,"timestamp":16820640546,"data":"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"},{"timing":2100,"timestamp":16820940546,"data":"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"},{"timing":2400,"timestamp":16821240546,"data":"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"},{"timing":2700,"timestamp":16821540546,"data":"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"},{"timing":3000,"timestamp":16821840546,"data":"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"}]}},"estimated-input-latency":{"id":"estimated-input-latency","title":"Estimated Input Latency","description":"The score above is an estimate of how long your app takes to respond to user input, in milliseconds, during the busiest 5s window of page load. If your latency is higher than 50 ms, users may perceive your app as laggy. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/estimated-input-latency).","score":1,"scoreDisplayMode":"numeric","rawValue":12.8,"displayValue":["%d ms",12.8]},"errors-in-console":{"id":"errors-in-console","title":"No browser errors logged to the console","description":"Errors logged to the console indicate unresolved problems. They can come from network request failures and other browser concerns.","score":1,"scoreDisplayMode":"binary","rawValue":0,"details":{"type":"table","headings":[],"items":[]}},"time-to-first-byte":{"id":"time-to-first-byte","title":"Keep server response times low (TTFB)","description":"Time To First Byte identifies the time at which your server sends a response. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/ttfb).","score":1,"scoreDisplayMode":"binary","rawValue":33.050999999999995,"displayValue":"","details":{"type":"opportunity","overallSavingsMs":-566.949,"headings":[],"items":[]}},"first-cpu-idle":{"id":"first-cpu-idle","title":"First CPU Idle","description":"First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-interactive).","score":0.97,"scoreDisplayMode":"numeric","rawValue":2674.2035000000005,"displayValue":["%10d ms",2674.2035000000005]},"interactive":{"id":"interactive","title":"Time to Interactive","description":"Interactive marks the time at which the page is fully interactive. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/consistently-interactive).","score":0.94,"scoreDisplayMode":"numeric","rawValue":3334.7035000000005,"displayValue":["%10d ms",3334.7035000000005]},"user-timings":{"id":"user-timings","title":"User Timing marks and measures","description":"Consider instrumenting your app with the User Timing API to create custom, real-world measurements of key user experiences. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/user-timing).","score":null,"scoreDisplayMode":"informative","rawValue":false,"displayValue":["%d user timings",26],"details":{"type":"table","headings":[{"key":"name","itemType":"text","text":"Name"},{"key":"timingType","itemType":"text","text":"Type"},{"key":"startTime","itemType":"ms","granularity":0.01,"text":"Start Time"},{"key":"duration","itemType":"ms","granularity":0.01,"text":"Duration"}],"items":[{"name":"Zone","startTime":117.299,"duration":0.501,"timingType":"Measure"},{"name":"Zone:ZoneAwarePromise","startTime":117.8,"duration":0.3,"timingType":"Measure"},{"name":"Zone:toString","startTime":118.1,"duration":0.099,"timingType":"Measure"},{"name":"Zone:util","startTime":118.199,"duration":0.1,"timingType":"Measure"},{"name":"Zone:timers","startTime":118.299,"duration":0.201,"timingType":"Measure"},{"name":"Zone:requestAnimationFrame","startTime":118.5,"duration":0,"timingType":"Measure"},{"name":"Zone:blocking","startTime":118.5,"duration":0.099,"timingType":"Measure"},{"name":"Zone:EventTarget","startTime":118.599,"duration":17,"timingType":"Measure"},{"name":"Zone:on_property","startTime":135.599,"duration":2.201,"timingType":"Measure"},{"name":"Zone:canvas","startTime":137.8,"duration":0.199,"timingType":"Measure"},{"name":"Zone:XHR","startTime":137.999,"duration":0.101,"timingType":"Measure"},{"name":"Zone:geolocation","startTime":138.1,"duration":0.199,"timingType":"Measure"},{"name":"Zone:PromiseRejectionEvent","startTime":138.299,"duration":0.101,"timingType":"Measure"},{"name":"Zone","startTime":117.304,"timingType":"Mark"},{"name":"Zone:ZoneAwarePromise","startTime":117.813,"timingType":"Mark"},{"name":"Zone:toString","startTime":118.119,"timingType":"Mark"},{"name":"Zone:util","startTime":118.209,"timingType":"Mark"},{"name":"Zone:timers","startTime":118.252,"timingType":"Mark"},{"name":"Zone:requestAnimationFrame","startTime":118.468,"timingType":"Mark"},{"name":"Zone:blocking","startTime":118.54,"timingType":"Mark"},{"name":"Zone:EventTarget","startTime":118.616,"timingType":"Mark"},{"name":"Zone:on_property","startTime":135.574,"timingType":"Mark"},{"name":"Zone:canvas","startTime":137.838,"timingType":"Mark"},{"name":"Zone:XHR","startTime":137.977,"timingType":"Mark"},{"name":"Zone:geolocation","startTime":138.115,"timingType":"Mark"},{"name":"Zone:PromiseRejectionEvent","startTime":138.258,"timingType":"Mark"}]}},"critical-request-chains":{"id":"critical-request-chains","title":"Critical Request Chains","description":"The Critical Request Chains below show you what resources are issued with a high priority. Consider reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/critical-request-chains).","score":null,"scoreDisplayMode":"informative","rawValue":false,"displayValue":"6 chains found","details":{"type":"criticalrequestchain","header":{"type":"text","text":"View critical network waterfall:"},"chains":{"6B7BE6115518481EFA0E02A46CA02D9D":{"request":{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/","startTime":16818.843693,"endTime":16818.88122,"responseReceivedTime":16818.87774,"transferSize":837},"children":{"1000006768.57":{"request":{"url":"https://fonts.googleapis.com/icon?family=Material+Icons","startTime":16818.885507,"endTime":16818.936986,"responseReceivedTime":16818.936467,"transferSize":644},"children":{}},"1000006768.58":{"request":{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/styles.b44eed526442e2e68110.css","startTime":16818.885729,"endTime":16818.922638,"responseReceivedTime":16818.921417,"transferSize":7958},"children":{}},"1000006768.59":{"request":{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/runtime.53373c5cb328321e3e8a.js","startTime":16818.885877,"endTime":16818.922489,"responseReceivedTime":16818.921797,"transferSize":974},"children":{}},"1000006768.60":{"request":{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/polyfills.f6ae3e8b63939c618130.js","startTime":16818.886013,"endTime":16818.923644,"responseReceivedTime":16818.922792999998,"transferSize":20073},"children":{}},"1000006768.61":{"request":{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/main.7a4958a1fc014e945330.js","startTime":16818.886204,"endTime":16818.93792,"responseReceivedTime":16818.935327,"transferSize":98178},"children":{}},"1000006768.67":{"request":{"url":"https://fonts.gstatic.com/s/materialicons/v41/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2","startTime":16819.06735,"endTime":16819.143183,"responseReceivedTime":16819.092244,"transferSize":55379},"children":{}}}}},"longestChain":{"duration":299.49000000124215,"length":2,"transferSize":55379}}},"redirects":{"id":"redirects","title":"Avoid multiple page redirects","description":"Redirects introduce additional delays before the page can be loaded. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/redirects).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":["%d ms",0],"details":{"type":"table","headings":[],"items":[],"summary":{"wastedMs":0}}},"webapp-install-banner":{"id":"webapp-install-banner","title":"User can be prompted to Install the Web App","description":"Browsers can proactively prompt users to add your app to their homescreen, which can lead to higher engagement. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/install-prompt).","score":1,"scoreDisplayMode":"binary","rawValue":true,"warnings":[],"details":{"items":[{"failures":[],"isParseFailure":false,"hasStartUrl":true,"hasIconsAtLeast192px":true,"hasIconsAtLeast512px":true,"hasPWADisplayValue":true,"hasBackgroundColor":true,"hasThemeColor":true,"hasShortName":true,"shortNameLength":true,"hasName":true}]}},"splash-screen":{"id":"splash-screen","title":"Configured for a custom splash screen","description":"A themed splash screen ensures a high-quality experience when users launch your app from their homescreens. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/custom-splash-screen).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"items":[{"failures":[],"isParseFailure":false,"hasStartUrl":true,"hasIconsAtLeast192px":true,"hasIconsAtLeast512px":true,"hasPWADisplayValue":true,"hasBackgroundColor":true,"hasThemeColor":true,"hasShortName":true,"shortNameLength":true,"hasName":true}]}},"themed-omnibox":{"id":"themed-omnibox","title":"Address bar matches brand colors","description":"The browser address bar can be themed to match your site. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/address-bar).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"items":[{"failures":[],"themeColor":"#1976d2","isParseFailure":false,"hasStartUrl":true,"hasIconsAtLeast192px":true,"hasIconsAtLeast512px":true,"hasPWADisplayValue":true,"hasBackgroundColor":true,"hasThemeColor":true,"hasShortName":true,"shortNameLength":true,"hasName":true}]}},"manifest-short-name-length":{"id":"manifest-short-name-length","title":"The `short_name` won't be truncated on the homescreen","description":"Make your app's `short_name` fewer than 12 characters to ensure that it's not truncated on homescreens. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/manifest-short_name-is-not-truncated).","score":1,"scoreDisplayMode":"binary","rawValue":true},"content-width":{"id":"content-width","title":"Content is sized correctly for the viewport","description":"If the width of your app's content doesn't match the width of the viewport, your app might not be optimized for mobile screens. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/content-sized-correctly-for-viewport).","score":1,"scoreDisplayMode":"binary","rawValue":true,"explanation":""},"image-aspect-ratio":{"id":"image-aspect-ratio","title":"Displays images with correct aspect ratio","description":"Image display dimensions should match natural aspect ratio. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/aspect-ratio).","score":1,"scoreDisplayMode":"binary","rawValue":true,"warnings":[],"details":{"type":"table","headings":[],"items":[]}},"deprecations":{"id":"deprecations","title":"Avoids deprecated APIs","description":"Deprecated APIs will eventually be removed from the browser. [Learn more](https://www.chromestatus.com/features#deprecated).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":"","details":{"type":"table","headings":[],"items":[]}},"mainthread-work-breakdown":{"id":"mainthread-work-breakdown","title":"Minimizes main thread work","description":"Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this.","score":0.98,"scoreDisplayMode":"numeric","rawValue":1372.5280000000002,"displayValue":["%10d ms",1372.5280000000002],"details":{"type":"table","headings":[{"key":"groupLabel","itemType":"text","text":"Category"},{"key":"duration","itemType":"ms","granularity":1,"text":"Time Spent"}],"items":[{"group":"scriptEvaluation","groupLabel":"Script Evaluation","duration":578.3040000000004},{"group":"other","groupLabel":"Other","duration":459.788},{"group":"styleLayout","groupLabel":"Style & Layout","duration":99.85199999999996},{"group":"scriptParseCompile","groupLabel":"Script Parsing & Compilation","duration":69.716},{"group":"paintCompositeRender","groupLabel":"Rendering","duration":66.06799999999997},{"group":"garbageCollection","groupLabel":"Garbage Collection","duration":58.08},{"group":"parseHTML","groupLabel":"Parse HTML & CSS","duration":40.719999999999985}]}},"bootup-time":{"id":"bootup-time","title":"JavaScript boot-up time","description":"Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/bootup).","score":1,"scoreDisplayMode":"numeric","rawValue":439.82,"displayValue":["%10d ms",439.82],"details":{"type":"table","headings":[{"key":"url","itemType":"url","text":"URL"},{"key":"total","granularity":1,"itemType":"ms","text":"Total"},{"key":"scripting","granularity":1,"itemType":"ms","text":"Script Evaluation"},{"key":"scriptParseCompile","granularity":1,"itemType":"ms","text":"Script Parsing & Compilation"}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/main.7a4958a1fc014e945330.js","total":193.868,"scripting":191.912,"scriptParseCompile":1.956},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/polyfills.f6ae3e8b63939c618130.js","total":190.93999999999997,"scripting":161.99599999999998,"scriptParseCompile":12.576},{"url":"chrome-extension://elgalmkoelokbchhkhacckoklkejnhcd/build/content-script.js","total":55.012,"scripting":39.872,"scriptParseCompile":15.14}],"summary":{"wastedMs":439.82}}},"uses-rel-preload":{"id":"uses-rel-preload","title":"Preload key requests","description":"Consider using \u003clink rel=preload> to prioritize fetching late-discovered resources sooner. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/preload).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":["Potential savings of %10d ms",0],"details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0}},"uses-rel-preconnect":{"id":"uses-rel-preconnect","title":"Avoid multiple, costly round trips to any origin","description":"Consider adding preconnect or dns-prefetch resource hints to establish early connections to important third-party origins. [Learn more](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":["Potential savings of %10d ms",0],"details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0}},"font-display":{"id":"font-display","title":"Text is invisible while webfonts are loading","description":"Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading. [Learn more](https://developers.google.com/web/updates/2016/02/font-display).","score":0,"scoreDisplayMode":"binary","rawValue":false,"details":{"type":"table","headings":[{"key":"url","itemType":"url","text":"Font URL"},{"key":"wastedTime","itemType":"ms","granularity":1,"text":"Font download time"}],"items":[{"url":"https://fonts.gstatic.com/s/materialicons/v41/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2","wastedTime":75.83299999896553}]}},"network-requests":{"id":"network-requests","title":"Network Requests","description":"Lists the network requests that were made during page load.","score":null,"scoreDisplayMode":"informative","rawValue":16,"details":{"type":"table","headings":[{"key":"url","itemType":"url","text":"URL"},{"key":"startTime","itemType":"ms","granularity":1,"text":"Start Time"},{"key":"endTime","itemType":"ms","granularity":1,"text":"End Time"},{"key":"transferSize","itemType":"bytes","displayUnit":"kb","granularity":1,"text":"Transfer Size"},{"key":"statusCode","itemType":"text","text":"Status Code"},{"key":"mimeType","itemType":"text","text":"MIME Type"},{"key":"resourceType","itemType":"text","text":"Resource Type"}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/","startTime":0,"endTime":37.527000000409316,"transferSize":837,"statusCode":200,"mimeType":"text/html","resourceType":"Document"},{"url":"https://fonts.googleapis.com/icon?family=Material+Icons","startTime":41.81400000015856,"endTime":93.29300000172225,"transferSize":644,"statusCode":200,"mimeType":"text/css","resourceType":"Stylesheet"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/styles.b44eed526442e2e68110.css","startTime":42.03600000255392,"endTime":78.94500000111293,"transferSize":7958,"statusCode":200,"mimeType":"text/css","resourceType":"Stylesheet"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/runtime.53373c5cb328321e3e8a.js","startTime":42.18400000172551,"endTime":78.7960000016028,"transferSize":974,"statusCode":200,"mimeType":"application/javascript","resourceType":"Script"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/polyfills.f6ae3e8b63939c618130.js","startTime":42.320000000472646,"endTime":79.9509999997099,"transferSize":20073,"statusCode":200,"mimeType":"application/javascript","resourceType":"Script"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/main.7a4958a1fc014e945330.js","startTime":42.51099999964936,"endTime":94.22700000141049,"transferSize":98178,"statusCode":200,"mimeType":"application/javascript","resourceType":"Script"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/data/companies.json","startTime":206.5920000022743,"endTime":242.11800000193762,"transferSize":412,"statusCode":200,"mimeType":"application/json","resourceType":"XHR"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/icons/icon-512x512.png","startTime":215.6649999997171,"endTime":252.33900000239373,"transferSize":20759,"statusCode":200,"mimeType":"image/png","resourceType":"Image"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/thai.80a2decc6ee5cd457dca.svg","startTime":222.01900000072783,"endTime":275.48100000058184,"transferSize":208637,"statusCode":200,"mimeType":"image/svg+xml","resourceType":"Image"},{"url":"https://fonts.gstatic.com/s/materialicons/v41/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2","startTime":223.65700000227662,"endTime":299.49000000124215,"transferSize":55379,"statusCode":200,"mimeType":"font/woff2","resourceType":"Font"},{"url":"chrome-extension://elgalmkoelokbchhkhacckoklkejnhcd/build/ng-validate.js","startTime":244.33300000237068,"endTime":245.75100000220118,"transferSize":0,"statusCode":200,"mimeType":"text/javascript","resourceType":"Script"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/angular.svg","startTime":260.15800000095624,"endTime":295.48200000135694,"transferSize":697,"statusCode":200,"mimeType":"image/svg+xml","resourceType":"Image"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/ionic.svg","startTime":260.4280000014114,"endTime":295.6880000019737,"transferSize":1005,"statusCode":200,"mimeType":"image/svg+xml","resourceType":"Image"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/nest.svg","startTime":260.6130000021949,"endTime":296.30399999950896,"transferSize":5296,"statusCode":200,"mimeType":"image/svg+xml","resourceType":"Image"},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/ngrx.svg","startTime":260.7850000022154,"endTime":299.6480000001611,"transferSize":20222,"statusCode":200,"mimeType":"image/svg+xml","resourceType":"Image"},{"url":"chrome-extension://gppongmhjkpfnbhagpmjfkannfbllamg/js/inject.js","startTime":334.2320000010659,"endTime":337.8100000008999,"transferSize":0,"statusCode":200,"mimeType":"text/javascript","resourceType":"Script"}]}},"metrics":{"id":"metrics","title":"Metrics","description":"Collects all available metrics.","score":null,"scoreDisplayMode":"informative","rawValue":3334.7035000000005,"details":{"items":[{"firstContentfulPaint":2224,"firstMeaningfulPaint":2224,"firstCPUIdle":2674,"interactive":3335,"speedIndex":2224,"estimatedInputLatency":13,"observedNavigationStart":0,"observedNavigationStartTs":16818840546,"observedFirstPaint":239,"observedFirstPaintTs":16819079928,"observedFirstContentfulPaint":239,"observedFirstContentfulPaintTs":16819079928,"observedFirstMeaningfulPaint":239,"observedFirstMeaningfulPaintTs":16819079928,"observedTraceEnd":1400,"observedTraceEndTs":16820240046,"observedLoad":344,"observedLoadTs":16819184095,"observedDomContentLoaded":221,"observedDomContentLoadedTs":16819061465,"observedFirstVisualChange":239,"observedFirstVisualChangeTs":16819079546,"observedLastVisualChange":756,"observedLastVisualChangeTs":16819596546,"observedSpeedIndex":304,"observedSpeedIndexTs":16819144086}]}},"pwa-cross-browser":{"id":"pwa-cross-browser","title":"Site works cross-browser","description":"To reach the most number of users, sites should work across every major browser. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#site-works-cross-browser).","score":null,"scoreDisplayMode":"manual","rawValue":false},"pwa-page-transitions":{"id":"pwa-page-transitions","title":"Page transitions don't feel like they block on the network","description":"Transitions should feel snappy as you tap around, even on a slow network, a key to perceived performance. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#page-transitions-dont-feel-like-they-block-on-the-network).","score":null,"scoreDisplayMode":"manual","rawValue":false},"pwa-each-page-has-url":{"id":"pwa-each-page-has-url","title":"Each page has a URL","description":"Ensure individual pages are deep linkable via the URLs and that URLs are unique for the purpose of shareability on social media. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#each-page-has-a-url).","score":null,"scoreDisplayMode":"manual","rawValue":false},"accesskeys":{"id":"accesskeys","title":"`[accesskey]` values are unique","description":"Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more](https://dequeuniversity.com/rules/axe/2.2/accesskeys?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"aria-allowed-attr":{"id":"aria-allowed-attr","title":"`[aria-*]` attributes match their roles","description":"Each ARIA `role` supports a specific subset of `aria-*` attributes. Mismatching these invalidates the `aria-*` attributes. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-allowed-attr?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"aria-required-attr":{"id":"aria-required-attr","title":"`[role]`s have all required `[aria-*]` attributes","description":"Some ARIA roles have required attributes that describe the state of the element to screen readers. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-required-attr?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"aria-required-children":{"id":"aria-required-children","title":"Elements with `[role]` that require specific children `[role]`s, are present","description":"Some ARIA parent roles must contain specific child roles to perform their intended accessibility functions. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-required-children?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"aria-required-parent":{"id":"aria-required-parent","title":"`[role]`s are contained by their required parent element","description":"Some ARIA child roles must be contained by specific parent roles to properly perform their intended accessibility functions. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-required-parent?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"aria-roles":{"id":"aria-roles","title":"`[role]` values are valid","description":"ARIA roles must have valid values in order to perform their intended accessibility functions. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-roles?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"aria-valid-attr-value":{"id":"aria-valid-attr-value","title":"`[aria-*]` attributes have valid values","description":"Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid values. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-valid-attr-value?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"aria-valid-attr":{"id":"aria-valid-attr","title":"`[aria-*]` attributes are valid and not misspelled","description":"Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid names. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-valid-attr?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"audio-caption":{"id":"audio-caption","title":"`\u003caudio>` elements contain a `\u003ctrack>` element with `[kind=\"captions\"]`","description":"Captions make audio elements usable for deaf or hearing-impaired users, providing critical information such as who is talking, what they're saying, and other non-speech information. [Learn more](https://dequeuniversity.com/rules/axe/2.2/audio-caption?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"button-name":{"id":"button-name","title":"Buttons have an accessible name","description":"When a button doesn't have an accessible name, screen readers announce it as \"button\", making it unusable for users who rely on screen readers. [Learn more](https://dequeuniversity.com/rules/axe/2.2/button-name?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"bypass":{"id":"bypass","title":"The page does not contain a heading, skip link, or landmark region","description":"Adding ways to bypass repetitive content lets keyboard users navigate the page more efficiently. [Learn more](https://dequeuniversity.com/rules/axe/2.2/bypass?application=lighthouse).","score":0,"scoreDisplayMode":"binary","rawValue":false,"details":{"type":"table","headings":[{"key":"node","itemType":"node","text":"Failing Elements"}],"items":[{"node":{"type":"node","selector":"html","path":"1,HTML","snippet":"\u003chtml lang=\"en\">","explanation":"Fix any of the following:\n No valid skip link found\n Page does not have a header\n Page does not have a landmark region"}}],"impact":"serious","tags":["cat.keyboard","wcag2a","wcag241","section508","section508.22.o"]}},"color-contrast":{"id":"color-contrast","title":"Background and foreground colors have a sufficient contrast ratio","description":"Low-contrast text is difficult or impossible for many users to read. [Learn more](https://dequeuniversity.com/rules/axe/2.2/color-contrast?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"definition-list":{"id":"definition-list","title":"`\u003cdl>`'s contain only properly-ordered `\u003cdt>` and `\u003cdd>` groups, `\u003cscript>` or `\u003ctemplate>` elements.","description":"When definition lists are not properly marked up, screen readers may produce confusing or inaccurate output. [Learn more](https://dequeuniversity.com/rules/axe/2.2/definition-list?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"dlitem":{"id":"dlitem","title":"Definition list items are wrapped in `\u003cdl>` elements","description":"Definition list items (`\u003cdt>` and `\u003cdd>`) must be wrapped in a parent `\u003cdl>` element to ensure that screen readers can properly announce them. [Learn more](https://dequeuniversity.com/rules/axe/2.2/dlitem?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"document-title":{"id":"document-title","title":"Document has a `\u003ctitle>` element","description":"The title gives screen reader users an overview of the page, and search engine users rely on it heavily to determine if a page is relevant to their search. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/title).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"duplicate-id":{"id":"duplicate-id","title":"`[id]` attributes on the page are unique","description":"The value of an id attribute must be unique to prevent other instances from being overlooked by assistive technologies. [Learn more](https://dequeuniversity.com/rules/axe/2.2/duplicate-id?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"frame-title":{"id":"frame-title","title":"`\u003cframe>` or `\u003ciframe>` elements have a title","description":"Screen reader users rely on frame titles to describe the contents of frames. [Learn more](https://dequeuniversity.com/rules/axe/2.2/frame-title?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"html-has-lang":{"id":"html-has-lang","title":"`\u003chtml>` element has a `[lang]` attribute","description":"If a page doesn't specify a lang attribute, a screen reader assumes that the page is in the default language that the user chose when setting up the screen reader. If the page isn't actually in the default language, then the screen reader might not announce the page's text correctly. [Learn more](https://dequeuniversity.com/rules/axe/2.2/html-lang?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"html-lang-valid":{"id":"html-lang-valid","title":"`\u003chtml>` element has a valid value for its `[lang]` attribute","description":"Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) helps screen readers announce text properly. [Learn more](https://dequeuniversity.com/rules/axe/2.2/valid-lang?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"image-alt":{"id":"image-alt","title":"Image elements have `[alt]` attributes","description":"Informative elements should aim for short, descriptive alternate text. Decorative elements can be ignored with an empty alt attribute. [Learn more](https://dequeuniversity.com/rules/axe/2.2/image-alt?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"input-image-alt":{"id":"input-image-alt","title":"`\u003cinput type=\"image\">` elements have `[alt]` text","description":"When an image is being used as an `\u003cinput>` button, providing alternative text can help screen reader users understand the purpose of the button. [Learn more](https://dequeuniversity.com/rules/axe/2.2/input-image-alt?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"label":{"id":"label","title":"Form elements have associated labels","description":"Labels ensure that form controls are announced properly by assistive technologies, like screen readers. [Learn more](https://dequeuniversity.com/rules/axe/2.2/label?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"layout-table":{"id":"layout-table","title":"Presentational `\u003ctable>` elements avoid using `\u003cth>`, `\u003ccaption>` or the `[summary]` attribute.","description":"A table being used for layout purposes should not include data elements, such as the th or caption elements or the summary attribute, because this can create a confusing experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/2.2/layout-table?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"link-name":{"id":"link-name","title":"Links have a discernible name","description":"Link text (and alternate text for images, when used as links) that is discernible, unique, and focusable improves the navigation experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/2.2/link-name?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"list":{"id":"list","title":"Lists contain only `\u003cli>` elements and script supporting elements (`\u003cscript>` and `\u003ctemplate>`).","description":"Screen readers have a specific way of announcing lists. Ensuring proper list structure aids screen reader output. [Learn more](https://dequeuniversity.com/rules/axe/2.2/list?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"listitem":{"id":"listitem","title":"List items (`\u003cli>`) are contained within `\u003cul>` or `\u003col>` parent elements","description":"Screen readers require list items (`\u003cli>`) to be contained within a parent `\u003cul>` or `\u003col>` to be announced properly. [Learn more](https://dequeuniversity.com/rules/axe/2.2/listitem?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"meta-refresh":{"id":"meta-refresh","title":"The document does not use `\u003cmeta http-equiv=\"refresh\">`","description":"Users do not expect a page to refresh automatically, and doing so will move focus back to the top of the page. This may create a frustrating or confusing experience. [Learn more](https://dequeuniversity.com/rules/axe/2.2/meta-refresh?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"meta-viewport":{"id":"meta-viewport","title":"`[user-scalable=\"no\"]` is not used in the `\u003cmeta name=\"viewport\">` element and the `[maximum-scale]` attribute is not less than 5.","description":"Disabling zooming is problematic for users with low vision who rely on screen magnification to properly see the contents of a web page. [Learn more](https://dequeuniversity.com/rules/axe/2.2/meta-viewport?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"object-alt":{"id":"object-alt","title":"`\u003cobject>` elements have `[alt]` text","description":"Screen readers cannot translate non-text content. Adding alt text to `\u003cobject>` elements helps screen readers convey meaning to users. [Learn more](https://dequeuniversity.com/rules/axe/2.2/object-alt?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"tabindex":{"id":"tabindex","title":"No element has a `[tabindex]` value greater than 0","description":"A value greater than 0 implies an explicit navigation ordering. Although technically valid, this often creates frustrating experiences for users who rely on assistive technologies. [Learn more](https://dequeuniversity.com/rules/axe/2.2/tabindex?application=lighthouse).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"td-headers-attr":{"id":"td-headers-attr","title":"Cells in a `\u003ctable>` element that use the `[headers]` attribute only refer to other cells of that same table.","description":"Screen readers have features to make navigating tables easier. Ensuring `\u003ctd>` cells using the `[headers]` attribute only refer to other cells in the same table may improve the experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/2.2/td-headers-attr?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"th-has-data-cells":{"id":"th-has-data-cells","title":"`\u003cth>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` have data cells they describe.","description":"Screen readers have features to make navigating tables easier. Ensuring table headers always refer to some set of cells may improve the experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/2.2/th-has-data-cells?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"valid-lang":{"id":"valid-lang","title":"`[lang]` attributes have a valid value","description":"Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) on elements helps ensure that text is pronounced correctly by a screen reader. [Learn more](https://dequeuniversity.com/rules/axe/2.2/valid-lang?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"video-caption":{"id":"video-caption","title":"`\u003cvideo>` elements contain a `\u003ctrack>` element with `[kind=\"captions\"]`","description":"When a video provides a caption it is easier for deaf and hearing impaired users to access its information. [Learn more](https://dequeuniversity.com/rules/axe/2.2/video-caption?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"video-description":{"id":"video-description","title":"`\u003cvideo>` elements contain a `\u003ctrack>` element with `[kind=\"description\"]`","description":"Audio descriptions provide relevant information for videos that dialogue cannot, such as facial expressions and scenes. [Learn more](https://dequeuniversity.com/rules/axe/2.2/video-description?application=lighthouse).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"custom-controls-labels":{"id":"custom-controls-labels","title":"Custom controls have associated labels","description":"Custom interactive controls have associated labels, provided by aria-label or aria-labelledby. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).","score":null,"scoreDisplayMode":"manual","rawValue":false},"custom-controls-roles":{"id":"custom-controls-roles","title":"Custom controls have ARIA roles","description":"Custom interactive controls have appropriate ARIA roles. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).","score":null,"scoreDisplayMode":"manual","rawValue":false},"focus-traps":{"id":"focus-traps","title":"User focus is not accidentally trapped in a region","description":"A user can tab into and out of any control or region without accidentally trapping their focus. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).","score":null,"scoreDisplayMode":"manual","rawValue":false},"focusable-controls":{"id":"focusable-controls","title":"Interactive controls are keyboard focusable","description":"Custom interactive controls are keyboard focusable and display a focus indicator. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).","score":null,"scoreDisplayMode":"manual","rawValue":false},"heading-levels":{"id":"heading-levels","title":"Headings don't skip levels","description":"Headings are used to create an outline for the page and heading levels are not skipped. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).","score":null,"scoreDisplayMode":"manual","rawValue":false},"logical-tab-order":{"id":"logical-tab-order","title":"The page has a logical tab order","description":"Tabbing through the page follows the visual layout. Users cannot focus elements that are offscreen. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).","score":null,"scoreDisplayMode":"manual","rawValue":false},"managed-focus":{"id":"managed-focus","title":"The user's focus is directed to new content added to the page","description":"If new content, such as a dialog, is added to the page, the user's focus is directed to it. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).","score":null,"scoreDisplayMode":"manual","rawValue":false},"offscreen-content-hidden":{"id":"offscreen-content-hidden","title":"Offscreen content is hidden from assistive technology","description":"Offscreen content is hidden with display: none or aria-hidden=true. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).","score":null,"scoreDisplayMode":"manual","rawValue":false},"use-landmarks":{"id":"use-landmarks","title":"HTML5 landmark elements are used to improve navigation","description":"Landmark elements (\u003cmain>, \u003cnav>, etc.) are used to improve the keyboard navigation of the page for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).","score":null,"scoreDisplayMode":"manual","rawValue":false},"visual-order-follows-dom":{"id":"visual-order-follows-dom","title":"Visual order on the page follows DOM order","description":"DOM order matches the visual order, improving navigation for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).","score":null,"scoreDisplayMode":"manual","rawValue":false},"uses-long-cache-ttl":{"id":"uses-long-cache-ttl","title":"Uses inefficient cache policy on static assets","description":"A long cache lifetime can speed up repeat visits to your page. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/cache-policy).","score":0.2,"scoreDisplayMode":"numeric","rawValue":352073.35000000003,"displayValue":"11 assets found","details":{"type":"table","headings":[{"key":"url","itemType":"url","text":"URL"},{"key":"cacheLifetimeMs","itemType":"ms","text":"Cache TTL","displayUnit":"duration"},{"key":"totalBytes","itemType":"bytes","text":"Size (KB)","displayUnit":"kb","granularity":1}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/thai.80a2decc6ee5cd457dca.svg","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":208637,"wastedBytes":191250.5833333333},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/main.7a4958a1fc014e945330.js","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":98178,"wastedBytes":89996.5},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/icons/icon-512x512.png","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":20759,"wastedBytes":19029.083333333332},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/ngrx.svg","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":20222,"wastedBytes":18536.833333333332},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/polyfills.f6ae3e8b63939c618130.js","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":20073,"wastedBytes":18400.25},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/styles.b44eed526442e2e68110.css","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":7958,"wastedBytes":7294.833333333333},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/nest.svg","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":5296,"wastedBytes":4854.666666666666},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/ionic.svg","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":1005,"wastedBytes":921.25},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/runtime.53373c5cb328321e3e8a.js","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":974,"wastedBytes":892.8333333333333},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/angular.svg","cacheControl":{"max-age":600},"cacheLifetimeMs":600000,"cacheHitProbability":0.08333333333333333,"totalBytes":697,"wastedBytes":638.9166666666666},{"url":"https://fonts.googleapis.com/icon?family=Material+Icons","cacheControl":{"private":true,"max-age":86400,"stale-while-revalidate":"604800"},"cacheLifetimeMs":86400000,"cacheHitProbability":0.6,"totalBytes":644,"wastedBytes":257.6}],"summary":{"wastedBytes":352073.35000000003}}},"total-byte-weight":{"id":"total-byte-weight","title":"Avoids enormous network payloads","description":"Large network payloads cost users real money and are highly correlated with long load times. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/network-payloads).","score":1,"scoreDisplayMode":"numeric","rawValue":441071,"displayValue":["Total size was %d KB",430.7333984375],"details":{"type":"table","headings":[{"key":"url","itemType":"url","text":"URL"},{"key":"totalBytes","itemType":"bytes","displayUnit":"kb","granularity":1,"text":"Total Size"},{"key":"totalMs","itemType":"ms","text":"Transfer Time"}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/thai.80a2decc6ee5cd457dca.svg","totalBytes":208637,"totalMs":28.293907681778634},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/main.7a4958a1fc014e945330.js","totalBytes":98178,"totalMs":13.31422167871309},{"url":"https://fonts.gstatic.com/s/materialicons/v41/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2","totalBytes":55379,"totalMs":7.5101171580746415},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/icons/icon-512x512.png","totalBytes":20759,"totalMs":2.8151920779441935},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/ngrx.svg","totalBytes":20222,"totalMs":2.742367850098149},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/polyfills.f6ae3e8b63939c618130.js","totalBytes":20073,"totalMs":2.722161500099898},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/styles.b44eed526442e2e68110.css","totalBytes":7958,"totalMs":1.0792089482287148},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/nest.svg","totalBytes":5296,"totalMs":0.7182069100049351},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/images/ionic.svg","totalBytes":1005,"totalMs":0.1362911526727643},{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/runtime.53373c5cb328321e3e8a.js","totalBytes":974,"totalMs":0.1320871469684303}]}},"offscreen-images":{"id":"offscreen-images","title":"Defer offscreen images","description":"Consider lazy-loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/offscreen-images).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":"","warnings":[],"details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0,"overallSavingsBytes":0}},"render-blocking-resources":{"id":"render-blocking-resources","title":"Eliminate render-blocking resources","description":"Resources are blocking the first paint of your page. Consider delivering critical JS/CSS inline and deferring all non-critical JS/styles. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/blocking-resources).","score":0.67,"scoreDisplayMode":"numeric","rawValue":450,"displayValue":"1 resource delayed first paint by 450ms","details":{"type":"opportunity","headings":[{"key":"url","valueType":"url","label":"URL"},{"key":"totalBytes","valueType":"bytes","label":"Size (KB)"},{"key":"wastedMs","valueType":"timespanMs","label":"Download Time (ms)"}],"items":[{"url":"https://fonts.googleapis.com/icon?family=Material+Icons","totalBytes":644,"wastedMs":792}],"overallSavingsMs":450}},"unminified-css":{"id":"unminified-css","title":"Minify CSS","description":"Minifying CSS files can reduce network payload sizes. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/minify-css).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":"","details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0,"overallSavingsBytes":0}},"unminified-javascript":{"id":"unminified-javascript","title":"Minify JavaScript","description":"Minifying JavaScript files can reduce payload sizes and script parse time. [Learn more](https://developers.google.com/speed/docs/insights/MinifyResources).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":"","warnings":[],"details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0,"overallSavingsBytes":0}},"unused-css-rules":{"id":"unused-css-rules","title":"Defer unused CSS","description":"Remove unused rules from stylesheets to reduce unnecessary bytes consumed by network activity. [Learn more](https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":["Potential savings of %d KB",11],"details":{"type":"opportunity","headings":[{"key":"url","valueType":"url","label":"URL"},{"key":"totalBytes","valueType":"bytes","label":"Original"},{"key":"wastedBytes","valueType":"bytes","label":"Potential Savings"}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/styles.b44eed526442e2e68110.css","wastedBytes":7843,"wastedPercent":98.55014166287734,"totalBytes":7958},{"url":".mat-button,.mat-flat-button,.mat-icon-button,.mat-stroked-button{box-sizing:border-box; ... } ...","wastedBytes":3370,"wastedPercent":84.01894789329344,"totalBytes":4011}],"overallSavingsMs":0,"overallSavingsBytes":11213}},"uses-webp-images":{"id":"uses-webp-images","title":"Serve images in next-gen formats","description":"Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/webp).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":["Potential savings of %d KB",11],"warnings":[],"details":{"type":"opportunity","headings":[{"key":"url","valueType":"thumbnail","label":""},{"key":"url","valueType":"url","label":"URL"},{"key":"totalBytes","valueType":"bytes","label":"Original"},{"key":"wastedBytes","valueType":"bytes","label":"Potential Savings"}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/icons/icon-512x512.png","fromProtocol":true,"isCrossOrigin":false,"totalBytes":20551,"wastedBytes":10771}],"overallSavingsMs":0,"overallSavingsBytes":10771}},"uses-optimized-images":{"id":"uses-optimized-images","title":"Efficiently encode images","description":"Optimized images load faster and consume less cellular data. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/optimize-images).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":"","warnings":[],"details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0,"overallSavingsBytes":0}},"uses-text-compression":{"id":"uses-text-compression","title":"Enable text compression","description":"Text-based responses should be served with compression (gzip, deflate or brotli) to minimize total network bytes. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/text-compression).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":"","details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0,"overallSavingsBytes":0}},"uses-responsive-images":{"id":"uses-responsive-images","title":"Properly size images","description":"Serve images that are appropriately-sized to save cellular data and improve load time. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/oversized-images).","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":["Potential savings of %d KB",11],"warnings":[],"details":{"type":"opportunity","headings":[{"key":"url","valueType":"thumbnail","label":""},{"key":"url","valueType":"url","label":"URL"},{"key":"totalBytes","valueType":"bytes","label":"Original"},{"key":"wastedBytes","valueType":"bytes","label":"Potential Savings"}],"items":[{"url":"https://perjerz3434.github.io/who-use-angular-in-thailand/assets/icons/icon-512x512.png","totalBytes":20551,"wastedBytes":11700,"wastedPercent":56.93359375}],"overallSavingsMs":0,"overallSavingsBytes":11700}},"efficient-animated-content":{"id":"efficient-animated-content","title":"Use video formats for animated content","description":"Large GIFs are inefficient for delivering animated content. Consider using MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save network bytes. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/replace-animated-gifs-with-video/)","score":1,"scoreDisplayMode":"numeric","rawValue":0,"displayValue":"","details":{"type":"opportunity","headings":[],"items":[],"overallSavingsMs":0,"overallSavingsBytes":0}},"appcache-manifest":{"id":"appcache-manifest","title":"Avoids Application Cache","description":"Application Cache is deprecated. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":""},"doctype":{"id":"doctype","title":"Page has the HTML doctype","description":"Specifying a doctype prevents the browser from switching to quirks-mode.Read more on the [MDN Web Docs page](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)","score":1,"scoreDisplayMode":"binary","rawValue":true},"dom-size":{"id":"dom-size","title":"Avoids an excessive DOM size","description":"Browser engineers recommend pages contain fewer than ~1,500 DOM nodes. The sweet spot is a tree depth \u003c 32 elements and fewer than 60 children/parent element. A large DOM can increase memory usage, cause longer [style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://developers.google.com/web/tools/lighthouse/audits/dom-size).","score":1,"scoreDisplayMode":"numeric","rawValue":73,"displayValue":["%d nodes",73],"details":{"type":"table","headings":[{"key":"totalNodes","itemType":"text","text":"Total DOM Nodes"},{"key":"depth","itemType":"text","text":"Maximum DOM Depth"},{"key":"width","itemType":"text","text":"Maximum Children"}],"items":[{"totalNodes":"73","depth":"11","width":"25"},{"totalNodes":"","depth":{"type":"code","value":"\u003ca _ngcontent-c7=\"\" rel=\"noopener\" target=\"_blank\" href=\"http://example.com\">"},"width":{"type":"code","value":"\u003chead>"}}]}},"external-anchors-use-rel-noopener":{"id":"external-anchors-use-rel-noopener","title":"Links to cross-origin destinations are safe","description":"Add `rel=\"noopener\"` or `rel=\"noreferrer\"` to any external links to improve performance and prevent security vulnerabilities. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/noopener).","score":1,"scoreDisplayMode":"binary","rawValue":true,"warnings":[],"details":{"type":"table","headings":[],"items":[]}},"geolocation-on-start":{"id":"geolocation-on-start","title":"Avoids requesting the geolocation permission on page load","description":"Users are mistrustful of or confused by sites that request their location without context. Consider tying the request to user gestures instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"no-document-write":{"id":"no-document-write","title":"Avoids `document.write()`","description":"For users on slow connections, external scripts dynamically injected via `document.write()` can delay page load by tens of seconds. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"no-vulnerable-libraries":{"id":"no-vulnerable-libraries","title":"Avoids front-end JavaScript libraries with known security vulnerabilities","description":"Some third-party scripts may contain known security vulnerabilities that are easily identified and exploited by attackers. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":"","details":{"type":"table","headings":[],"items":[],"summary":{}}},"no-websql":{"id":"no-websql","title":"Avoids WebSQL DB","description":"Web SQL is deprecated. Consider using IndexedDB instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/web-sql).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":""},"notification-on-start":{"id":"notification-on-start","title":"Avoids requesting the notification permission on page load","description":"Users are mistrustful of or confused by sites that request to send notifications without context. Consider tying the request to user gestures instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/notifications-on-load).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"password-inputs-can-be-pasted-into":{"id":"password-inputs-can-be-pasted-into","title":"Allows users to paste into password fields","description":"Preventing password pasting undermines good security policy. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/password-pasting).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"uses-http2":{"id":"uses-http2","title":"Uses HTTP/2 for its own resources","description":"HTTP/2 offers many benefits over HTTP/1.1, including binary headers, multiplexing, and server push. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http2).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":"","details":{"type":"table","headings":[],"items":[]}},"uses-passive-event-listeners":{"id":"uses-passive-event-listeners","title":"Uses passive listeners to improve scrolling performance","description":"Consider marking your touch and wheel event listeners as `passive` to improve your page's scroll performance. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"meta-description":{"id":"meta-description","title":"Document has a meta description","description":"Meta descriptions may be included in search results to concisely summarize page content. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/description).","score":1,"scoreDisplayMode":"binary","rawValue":true},"http-status-code":{"id":"http-status-code","title":"Page has successful HTTP status code","description":"Pages with unsuccessful HTTP status codes may not be indexed properly. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/successful-http-code).","score":1,"scoreDisplayMode":"binary","rawValue":true},"font-size":{"id":"font-size","title":"Document uses legible font sizes","description":"Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/font-sizes).","score":1,"scoreDisplayMode":"binary","rawValue":true,"displayValue":["%.1d% legible text",100],"details":{"type":"table","headings":[{"key":"source","itemType":"url","text":"Source"},{"key":"selector","itemType":"code","text":"Selector"},{"key":"coverage","itemType":"text","text":"% of Page Text"},{"key":"fontSize","itemType":"text","text":"Font Size"}],"items":[{"source":"Legible text","selector":"","coverage":"100.00%","fontSize":"≥ 12px"}]}},"link-text":{"id":"link-text","title":"Links have descriptive text","description":"Descriptive link text helps search engines understand your content. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/descriptive-link-text).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[],"summary":{}}},"is-crawlable":{"id":"is-crawlable","title":"Page isn’t blocked from indexing","description":"Search engines are unable to include your pages in search results if they don't have permission to crawl them. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/indexing).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"robots-txt":{"id":"robots-txt","title":"robots.txt is valid","description":"If your robots.txt file is malformed, crawlers may not be able to understand how you want your website to be crawled or indexed.","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"hreflang":{"id":"hreflang","title":"Document has a valid `hreflang`","description":"hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/hreflang).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"plugins":{"id":"plugins","title":"Document avoids plugins","description":"Search engines can't index plugin content, and many devices restrict plugins or don't support them. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/plugins).","score":1,"scoreDisplayMode":"binary","rawValue":true,"details":{"type":"table","headings":[],"items":[]}},"canonical":{"id":"canonical","title":"Document has a valid `rel=canonical`","description":"Canonical links suggest which URL to show in search results. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/canonical).","score":null,"scoreDisplayMode":"not-applicable","rawValue":true},"mobile-friendly":{"id":"mobile-friendly","title":"Page is mobile friendly","description":"Take the [Mobile-Friendly Test](https://search.google.com/test/mobile-friendly) to check for audits not covered by Lighthouse, like sizing tap targets appropriately. [Learn more](https://developers.google.com/search/mobile-sites/).","score":null,"scoreDisplayMode":"manual","rawValue":false},"structured-data":{"id":"structured-data","title":"Structured data is valid","description":"Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://developers.google.com/search/docs/guides/mark-up-content).","score":null,"scoreDisplayMode":"manual","rawValue":false}},"configSettings":{"output":"json","maxWaitForLoad":45000,"throttlingMethod":"simulate","throttling":{"rttMs":150,"throughputKbps":1638.4,"requestLatencyMs":562.5,"downloadThroughputKbps":1474.5600000000002,"uploadThroughputKbps":675,"cpuSlowdownMultiplier":4},"auditMode":false,"gatherMode":false,"disableStorageReset":false,"disableDeviceEmulation":false,"blockedUrlPatterns":null,"additionalTraceCategories":null,"extraHeaders":null,"onlyAudits":null,"onlyCategories":["performance","pwa","best-practices","accessibility","seo"],"skipAudits":null},"categories":{"performance":{"title":"Performance","auditRefs":[{"id":"first-contentful-paint","weight":3,"group":"metrics"},{"id":"first-meaningful-paint","weight":1,"group":"metrics"},{"id":"speed-index","weight":4,"group":"metrics"},{"id":"interactive","weight":5,"group":"metrics"},{"id":"first-cpu-idle","weight":2,"group":"metrics"},{"id":"estimated-input-latency","weight":0,"group":"metrics"},{"id":"render-blocking-resources","weight":0,"group":"load-opportunities"},{"id":"uses-responsive-images","weight":0,"group":"load-opportunities"},{"id":"offscreen-images","weight":0,"group":"load-opportunities"},{"id":"unminified-css","weight":0,"group":"load-opportunities"},{"id":"unminified-javascript","weight":0,"group":"load-opportunities"},{"id":"unused-css-rules","weight":0,"group":"load-opportunities"},{"id":"uses-optimized-images","weight":0,"group":"load-opportunities"},{"id":"uses-webp-images","weight":0,"group":"load-opportunities"},{"id":"uses-text-compression","weight":0,"group":"load-opportunities"},{"id":"uses-rel-preconnect","weight":0,"group":"load-opportunities"},{"id":"time-to-first-byte","weight":0,"group":"load-opportunities"},{"id":"redirects","weight":0,"group":"load-opportunities"},{"id":"uses-rel-preload","weight":0,"group":"load-opportunities"},{"id":"efficient-animated-content","weight":0,"group":"load-opportunities"},{"id":"total-byte-weight","weight":0,"group":"diagnostics"},{"id":"uses-long-cache-ttl","weight":0,"group":"diagnostics"},{"id":"dom-size","weight":0,"group":"diagnostics"},{"id":"critical-request-chains","weight":0,"group":"diagnostics"},{"id":"network-requests","weight":0},{"id":"metrics","weight":0},{"id":"user-timings","weight":0,"group":"diagnostics"},{"id":"bootup-time","weight":0,"group":"diagnostics"},{"id":"screenshot-thumbnails","weight":0},{"id":"mainthread-work-breakdown","weight":0,"group":"diagnostics"},{"id":"font-display","weight":0,"group":"diagnostics"}],"id":"performance","score":0.95},"pwa":{"title":"Progressive Web App","description":"These checks validate the aspects of a Progressive Web App, as specified by the baseline [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist).","manualDescription":"These checks are required by the baseline [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) but are not automatically checked by Lighthouse. They do not affect your score but it's important that you verify them manually.","auditRefs":[{"id":"load-fast-enough-for-pwa","weight":7},{"id":"works-offline","weight":5},{"id":"webapp-install-banner","weight":3},{"id":"is-on-https","weight":2},{"id":"redirects-http","weight":2},{"id":"viewport","weight":2},{"id":"service-worker","weight":1},{"id":"without-javascript","weight":1},{"id":"splash-screen","weight":1},{"id":"themed-omnibox","weight":1},{"id":"content-width","weight":1},{"id":"manifest-short-name-length","weight":0},{"id":"pwa-cross-browser","weight":0},{"id":"pwa-page-transitions","weight":0},{"id":"pwa-each-page-has-url","weight":0}],"id":"pwa","score":1},"accessibility":{"title":"Accessibility","description":"These checks highlight opportunities to [improve the accessibility of your web app](https://developers.google.com/web/fundamentals/accessibility). Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged.","manualDescription":"These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://developers.google.com/web/fundamentals/accessibility/how-to-review).","auditRefs":[{"id":"accesskeys","weight":0,"group":"a11y-correct-attributes"},{"id":"aria-allowed-attr","weight":3,"group":"a11y-aria"},{"id":"aria-required-attr","weight":0,"group":"a11y-aria"},{"id":"aria-required-children","weight":0,"group":"a11y-aria"},{"id":"aria-required-parent","weight":0,"group":"a11y-aria"},{"id":"aria-roles","weight":0,"group":"a11y-aria"},{"id":"aria-valid-attr-value","weight":2,"group":"a11y-aria"},{"id":"aria-valid-attr","weight":5,"group":"a11y-aria"},{"id":"audio-caption","weight":0,"group":"a11y-correct-attributes"},{"id":"button-name","weight":0,"group":"a11y-element-names"},{"id":"bypass","weight":10,"group":"a11y-describe-contents"},{"id":"color-contrast","weight":6,"group":"a11y-color-contrast"},{"id":"definition-list","weight":0,"group":"a11y-well-structured"},{"id":"dlitem","weight":0,"group":"a11y-well-structured"},{"id":"document-title","weight":2,"group":"a11y-describe-contents"},{"id":"duplicate-id","weight":0,"group":"a11y-well-structured"},{"id":"frame-title","weight":0,"group":"a11y-describe-contents"},{"id":"html-has-lang","weight":4,"group":"a11y-language"},{"id":"html-lang-valid","weight":1,"group":"a11y-language"},{"id":"image-alt","weight":8,"group":"a11y-correct-attributes"},{"id":"input-image-alt","weight":0,"group":"a11y-correct-attributes"},{"id":"label","weight":0,"group":"a11y-describe-contents"},{"id":"layout-table","weight":0,"group":"a11y-describe-contents"},{"id":"link-name","weight":9,"group":"a11y-element-names"},{"id":"list","weight":0,"group":"a11y-well-structured"},{"id":"listitem","weight":0,"group":"a11y-well-structured"},{"id":"meta-refresh","weight":0,"group":"a11y-meta"},{"id":"meta-viewport","weight":3,"group":"a11y-meta"},{"id":"object-alt","weight":0,"group":"a11y-describe-contents"},{"id":"tabindex","weight":4,"group":"a11y-correct-attributes"},{"id":"td-headers-attr","weight":0,"group":"a11y-correct-attributes"},{"id":"th-has-data-cells","weight":0,"group":"a11y-correct-attributes"},{"id":"valid-lang","weight":0,"group":"a11y-language"},{"id":"video-caption","weight":0,"group":"a11y-describe-contents"},{"id":"video-description","weight":0,"group":"a11y-describe-contents"},{"id":"logical-tab-order","weight":0},{"id":"focusable-controls","weight":0},{"id":"managed-focus","weight":0},{"id":"focus-traps","weight":0},{"id":"custom-controls-labels","weight":0},{"id":"custom-controls-roles","weight":0},{"id":"visual-order-follows-dom","weight":0},{"id":"offscreen-content-hidden","weight":0},{"id":"heading-levels","weight":0},{"id":"use-landmarks","weight":0}],"id":"accessibility","score":0.82},"best-practices":{"title":"Best Practices","auditRefs":[{"id":"appcache-manifest","weight":1},{"id":"no-websql","weight":1},{"id":"is-on-https","weight":1},{"id":"uses-http2","weight":1},{"id":"uses-passive-event-listeners","weight":1},{"id":"no-document-write","weight":1},{"id":"external-anchors-use-rel-noopener","weight":1},{"id":"geolocation-on-start","weight":1},{"id":"doctype","weight":1},{"id":"no-vulnerable-libraries","weight":1},{"id":"notification-on-start","weight":1},{"id":"deprecations","weight":1},{"id":"password-inputs-can-be-pasted-into","weight":1},{"id":"errors-in-console","weight":1},{"id":"image-aspect-ratio","weight":1}],"id":"best-practices","score":1},"seo":{"title":"SEO","description":"These checks ensure that your page is optimized for search engine results ranking. There are additional factors Lighthouse does not check that may affect your search ranking. [Learn more](https://support.google.com/webmasters/answer/35769).","manualDescription":"Run these additional validators on your site to check additional SEO best practices.","auditRefs":[{"id":"viewport","weight":1,"group":"seo-mobile"},{"id":"document-title","weight":1,"group":"seo-content"},{"id":"meta-description","weight":1,"group":"seo-content"},{"id":"http-status-code","weight":1,"group":"seo-crawl"},{"id":"link-text","weight":1,"group":"seo-content"},{"id":"is-crawlable","weight":1,"group":"seo-crawl"},{"id":"robots-txt","weight":0,"group":"seo-crawl"},{"id":"hreflang","weight":1,"group":"seo-content"},{"id":"canonical","weight":0,"group":"seo-content"},{"id":"font-size","weight":1,"group":"seo-mobile"},{"id":"plugins","weight":1,"group":"seo-content"},{"id":"mobile-friendly","weight":0},{"id":"structured-data","weight":0}],"id":"seo","score":1}},"categoryGroups":{"metrics":{"title":"Metrics"},"load-opportunities":{"title":"Opportunities","description":"These are opportunities to speed up your application by optimizing the following resources."},"diagnostics":{"title":"Diagnostics","description":"More information about the performance of your application."},"a11y-color-contrast":{"title":"Color Contrast Is Satisfactory","description":"These are opportunities to improve the legibility of your content."},"a11y-describe-contents":{"title":"Elements Describe Contents Well","description":"These are opportunities to make your content easier to understand for a user of assistive technology, like a screen reader."},"a11y-well-structured":{"title":"Elements Are Well Structured","description":"These are opportunities to make sure your HTML is appropriately structured."},"a11y-aria":{"title":"ARIA Attributes Follow Best Practices","description":"These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader."},"a11y-correct-attributes":{"title":"Elements Use Attributes Correctly","description":"These are opportunities to improve the configuration of your HTML elements."},"a11y-element-names":{"title":"Elements Have Discernible Names","description":"These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader."},"a11y-language":{"title":"Page Specifies Valid Language","description":"These are opportunities to improve the interpretation of your content by users in different locales."},"a11y-meta":{"title":"Meta Tags Used Properly","description":"These are opportunities to improve the user experience of your site."},"seo-mobile":{"title":"Mobile Friendly","description":"Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn more](https://developers.google.com/search/mobile-sites/)."},"seo-content":{"title":"Content Best Practices","description":"Format your HTML in a way that enables crawlers to better understand your app’s content."},"seo-crawl":{"title":"Crawling and Indexing","description":"To appear in search results, crawlers need access to your app."}},"timing":{"total":6577}};</script> | |
<script> | |
window.addEventListener('DOMContentLoaded', _ => { | |
const dom = new DOM(document); | |
const renderer = new ReportRenderer(dom); | |
const container = document.querySelector('main'); | |
renderer.renderReport(window.__LIGHTHOUSE_JSON__, container); | |
// Hook in JS features and page-level event listeners after the report | |
// is in the document. | |
const features = new ReportUIFeatures(dom); | |
features.initFeatures(window.__LIGHTHOUSE_JSON__); | |
}); | |
document.addEventListener('lh-analytics', e => { | |
if (window.ga) { | |
ga(e.detail.cmd, e.detail.fields); | |
} | |
}); | |
document.addEventListener('lh-log', e => { | |
const logger = new Logger(document.querySelector('#lh-log')); | |
switch (e.detail.cmd) { | |
case 'log': | |
logger.log(e.detail.msg); | |
break; | |
case 'warn': | |
logger.warn(e.detail.msg); | |
break; | |
case 'error': | |
logger.error(e.detail.msg); | |
break; | |
case 'hide': | |
logger.hide(); | |
break; | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment