'use strict';const ELLIPSIS='\u2026';const NBSP='\xa0';const RATINGS={PASS:{label:'pass',minScore:75},AVERAGE:{label:'average',minScore:45},FAIL:{label:'fail'},};class Util{static calculateRating(score){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;} static formatNumber(number,decimalPlaces=1){return number.toLocaleString(undefined,{maximumFractionDigits:decimalPlaces});} static formatBytesToKB(size,decimalPlaces=2){const kbs=(size/1024).toLocaleString(undefined,{maximumFractionDigits:decimalPlaces});return`${kbs}${NBSP}KB`;} static formatMilliseconds(ms,granularity=10){const coarseTime=Math.round(ms/granularity)*granularity;return`${coarseTime.toLocaleString()}${NBSP}ms`;} static formatDateTime(date){const options={month:'short',day:'numeric',year:'numeric',hour:'numeric',minute:'numeric',timeZoneName:'short',};let formatter=new Intl.DateTimeFormat('en-US',options);const tz=formatter.resolvedOptions().timeZone;if(!tz||tz.toLowerCase()==='etc/unknown'){options.timeZone='UTC';formatter=new Intl.DateTimeFormat('en-US',options);} return formatter.format(new Date(date));} static formatDuration(timeInSeconds,zeroLabel='None'){if(timeInSeconds===0){return zeroLabel;} const parts=[];const unitLabels=({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(' ');} static getURLDisplayName(parsedUrl,options){options=options||{};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:'){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;name=name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g,`$1${ELLIPSIS}`);name=name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,`$1${ELLIPSIS}`);name=name.replace(/(\d{3})\d{6,}/g,`$1${ELLIPSIS}`);name=name.replace(/\u2026+/g,ELLIPSIS);if(name.length>MAX_LENGTH&&name.includes('?')){name=name.replace(/\?([^=]*)(=)?.*/,`?$1$2${ELLIPSIS}`);if(name.length>MAX_LENGTH){name=name.replace(/\?.*/,`?${ELLIPSIS}`);}} if(name.length>MAX_LENGTH){const dotIndex=name.lastIndexOf('.');if(dotIndex>=0){name=name.slice(0,MAX_LENGTH-1-(name.length-dotIndex))+`${ELLIPSIS}${name.slice(dotIndex)}`;}else{name=name.slice(0,MAX_LENGTH-1)+ELLIPSIS;}} return name;} static parseURL(url){const parsedUrl=new URL(url);return{file:Util.getURLDisplayName(parsedUrl),hostname:parsedUrl.hostname};} static chainDuration(startTime,endTime){return Util.formatNumber((endTime-startTime)*1000);}} if(typeof module!=='undefined'&&module.exports){module.exports=Util;}else{self.Util=Util;};'use strict';class DOM{constructor(document){this._document=document;} 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;} createChildOf(parentElem,elementName,className,attrs){const element=this.createElement(elementName,className,attrs);parentElem.appendChild(element);return element;} cloneTemplate(selector,context){const template=(context.querySelector(selector));if(!template){throw new Error(`Template not found: template${selector}`);} const clone=(this._document.importNode(template.content,true));if(template.hasAttribute('data-stamped')){this.findAll('style',clone).forEach(style=>style.remove());} template.setAttribute('data-stamped',true);return clone;} resetTemplates(){this.findAll('template[data-stamped]',this._document).forEach(t=>{t.removeAttribute('data-stamped');});} convertMarkdownLinkSnippets(text){const element=this.createElement('span');const parts=text.split(/\[([^\]]*?)\]\((https?:\/\/.*?)\)/g);while(parts.length){const[preambleText,linkText,linkHref]=parts.splice(0,3);element.appendChild(this._document.createTextNode(preambleText));if(linkText&&linkHref){const a=(this.createElement('a'));a.rel='noopener';a.target='_blank';a.textContent=linkText;a.href=(new URL(linkHref)).href;element.appendChild(a);}} return element;} convertMarkdownCodeSnippets(text){const element=this.createElement('span');const parts=text.split(/`(.*?)`/g);while(parts.length){const[preambleText,codeText]=parts.splice(0,2);element.appendChild(this._document.createTextNode(preambleText));if(codeText){const pre=(this.createElement('code'));pre.textContent=codeText;element.appendChild(pre);}} return element;} document(){return this._document;} find(query,context){const result=context.querySelector(query);if(result===null){throw new Error(`query ${query} not found`);} return result;} findAll(query,context){return Array.from(context.querySelectorAll(query));}} if(typeof module!=='undefined'&&module.exports){module.exports=DOM;}else{self.DOM=DOM;};'use strict';class CategoryRenderer{constructor(dom,detailsRenderer){this._dom=dom;this._detailsRenderer=detailsRenderer;this._templateContext=this._dom.document();this._detailsRenderer.setTemplateContext(this._templateContext);} _renderAuditScore(audit){const tmpl=this._dom.cloneTemplate('#tmpl-lh-audit-score',this._templateContext);const scoringMode=audit.result.scoringMode;const description=audit.result.helpText;let title=audit.result.description;if(audit.result.displayValue){title+=`: ${audit.result.displayValue}`;} if(audit.result.debugString){const debugStrEl=tmpl.appendChild(this._dom.createElement('div','lh-debug'));debugStrEl.textContent=audit.result.debugString;} const header=(this._dom.find('.lh-score__header',tmpl));if(audit.result.details){header.appendChild(this._detailsRenderer.render(audit.result.details));} const scoreEl=this._dom.find('.lh-score',tmpl);if(audit.result.informative){scoreEl.classList.add('lh-score--informative');} if(audit.result.manual){scoreEl.classList.add('lh-score--manual');} return this._populateScore(tmpl,audit.score,scoringMode,title,description);} _populateScore(element,score,scoringMode,title,description){const valueEl=this._dom.find('.lh-score__value',element);valueEl.textContent=Util.formatNumber(score);valueEl.classList.add(`lh-score__value--${Util.calculateRating(score)}`,`lh-score__value--${scoringMode}`);this._dom.find('.lh-score__title',element).appendChild(this._dom.convertMarkdownCodeSnippets(title));this._dom.find('.lh-score__description',element).appendChild(this._dom.convertMarkdownLinkSnippets(description));return(element);} _renderCategoryScore(category){const tmpl=this._dom.cloneTemplate('#tmpl-lh-category-score',this._templateContext);const score=Math.round(category.score);const gaugeContainerEl=this._dom.find('.lh-score__gauge',tmpl);const gaugeEl=this.renderScoreGauge(category);gaugeContainerEl.appendChild(gaugeEl);return this._populateScore(tmpl,score,'numeric',category.name,category.description);} _renderAudit(audit){const element=this._dom.createElement('div','lh-audit');element.appendChild(this._renderAuditScore(audit));return element;} _renderTimelineMetricAudit(audit,scale){const tmpl=this._dom.cloneTemplate('#tmpl-lh-timeline-metric',this._templateContext);const element=this._dom.find('.lh-timeline-metric',tmpl);element.classList.add(`lh-timeline-metric--${Util.calculateRating(audit.score)}`);const titleEl=this._dom.find('.lh-timeline-metric__title',tmpl);titleEl.textContent=audit.result.description;const valueEl=this._dom.find('.lh-timeline-metric__value',tmpl);valueEl.textContent=audit.result.displayValue;const descriptionEl=this._dom.find('.lh-timeline-metric__description',tmpl);descriptionEl.appendChild(this._dom.convertMarkdownLinkSnippets(audit.result.helpText));if(typeof audit.result.rawValue!=='number'){const debugStrEl=this._dom.createChildOf(element,'div','lh-debug');debugStrEl.textContent=audit.result.debugString||'Report error: no metric information';return element;} const sparklineBarEl=this._dom.find('.lh-sparkline__bar',tmpl);sparklineBarEl.style.width=`${audit.result.rawValue / scale * 100}%`;return element;} _renderPerfHintAudit(audit,scale){const extendedInfo=(audit.result.extendedInfo);const tooltipAttrs={title:audit.result.displayValue};const element=this._dom.createElement('details',['lh-perf-hint',`lh-perf-hint--${Util.calculateRating(audit.score)}`,'lh-expandable-details',].join(' '));const summary=this._dom.createChildOf(element,'summary','lh-perf-hint__summary '+'lh-expandable-details__summary');const titleEl=this._dom.createChildOf(summary,'div','lh-perf-hint__title');titleEl.textContent=audit.result.description;this._dom.createChildOf(summary,'div','lh-toggle-arrow',{title:'See resources'});if(!extendedInfo||typeof audit.result.rawValue!=='number'){const debugStrEl=this._dom.createChildOf(summary,'div','lh-debug');debugStrEl.textContent=audit.result.debugString||'Report error: no extended information';return element;} const sparklineContainerEl=this._dom.createChildOf(summary,'div','lh-perf-hint__sparkline',tooltipAttrs);const sparklineEl=this._dom.createChildOf(sparklineContainerEl,'div','lh-sparkline');const sparklineBarEl=this._dom.createChildOf(sparklineEl,'div','lh-sparkline__bar');sparklineBarEl.style.width=audit.result.rawValue/scale*100+'%';const statsEl=this._dom.createChildOf(summary,'div','lh-perf-hint__stats',tooltipAttrs);const statsMsEl=this._dom.createChildOf(statsEl,'div','lh-perf-hint__primary-stat');statsMsEl.textContent=Util.formatMilliseconds(audit.result.rawValue);if(extendedInfo.value.wastedKb){const statsKbEl=this._dom.createChildOf(statsEl,'div','lh-perf-hint__secondary-stat');statsKbEl.textContent=Util.formatNumber(extendedInfo.value.wastedKb)+' KB';} const descriptionEl=this._dom.createChildOf(element,'div','lh-perf-hint__description');descriptionEl.appendChild(this._dom.convertMarkdownLinkSnippets(audit.result.helpText));if(audit.result.debugString){const debugStrEl=this._dom.createChildOf(summary,'div','lh-debug');debugStrEl.textContent=audit.result.debugString;} if(audit.result.details){element.appendChild(this._detailsRenderer.render(audit.result.details));} return element;} _renderAuditGroup(group,opts){const expandable=opts.expandable;const element=this._dom.createElement(expandable?'details':'div','lh-audit-group');const summmaryEl=this._dom.createChildOf(element,'summary','lh-audit-group__summary');const headerEl=this._dom.createChildOf(summmaryEl,'div','lh-audit-group__header');this._dom.createChildOf(summmaryEl,'div',`lh-toggle-arrow ${expandable ? '' : ' lh-toggle-arrow-unexpandable'}`,{title:'See audits',});if(group.description){const auditGroupDescription=this._dom.createElement('div','lh-audit-group__description');auditGroupDescription.appendChild(this._dom.convertMarkdownLinkSnippets(group.description));element.appendChild(auditGroupDescription);} headerEl.textContent=group.title;return element;} _getTotalAuditsLength(elements){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;}} _renderPassedAuditsSection(elements){const passedElem=this._renderAuditGroup({title:`${this._getTotalAuditsLength(elements)} Passed Audits`,},{expandable:true});passedElem.classList.add('lh-passed-audits');elements.forEach(elem=>passedElem.appendChild(elem));return passedElem;} _renderNotApplicableAuditsSection(elements){const notApplicableElem=this._renderAuditGroup({title:`${this._getTotalAuditsLength(elements)} Not Applicable Audits`,},{expandable:true});notApplicableElem.classList.add('lh-audit-group--notapplicable');elements.forEach(elem=>notApplicableElem.appendChild(elem));return notApplicableElem;} _renderManualAudits(manualAudits,groupDefinitions,element){const auditsGroupedByGroup=({});manualAudits.forEach(audit=>{const group=auditsGroupedByGroup[audit.group]||[];group.push(audit);auditsGroupedByGroup[audit.group]=group;});Object.keys(auditsGroupedByGroup).forEach(groupId=>{const group=groupDefinitions[groupId];const auditGroupElem=this._renderAuditGroup(group,{expandable:true});auditGroupElem.classList.add('lh-audit-group--manual');auditsGroupedByGroup[groupId].forEach(audit=>{auditGroupElem.appendChild(this._renderAudit(audit));});element.appendChild(auditGroupElem);});} setTemplateContext(context){this._templateContext=context;this._detailsRenderer.setTemplateContext(context);} renderScoreGauge(category){const tmpl=this._dom.cloneTemplate('#tmpl-lh-gauge',this._templateContext);this._dom.find('.lh-gauge__wrapper',tmpl).href=`#${category.id}`;this._dom.find('.lh-gauge__label',tmpl).textContent=category.name;const score=Math.round(category.score);const fillRotation=Math.floor((score/100)*180);const gauge=this._dom.find('.lh-gauge',tmpl);gauge.setAttribute('data-progress',score);gauge.classList.add(`lh-gauge--${Util.calculateRating(score)}`);this._dom.findAll('.lh-gauge__fill',gauge).forEach(el=>{el.style.transform=`rotate(${fillRotation}deg)`;});this._dom.find('.lh-gauge__mask--full',gauge).style.transform=`rotate(${fillRotation}deg)`;this._dom.find('.lh-gauge__fill--fix',gauge).style.transform=`rotate(${fillRotation * 2}deg)`;this._dom.find('.lh-gauge__percentage',gauge).textContent=score;return tmpl;} render(category,groups){switch(category.id){case'performance':return this.renderPerformanceCategory(category,groups);case'accessibility':return this._renderAccessibilityCategory(category,groups);default:return this._renderDefaultCategory(category,groups);}} _renderDefaultCategory(category,groupDefinitions){const element=this._dom.createElement('div','lh-category');this._createPermalinkSpan(element,category.id);element.appendChild(this._renderCategoryScore(category));const manualAudits=category.audits.filter(audit=>audit.result.manual);const nonManualAudits=category.audits.filter(audit=>!manualAudits.includes(audit));const passedAudits=nonManualAudits.filter(audit=>audit.score===100&&!audit.result.debugString);const nonPassedAudits=nonManualAudits.filter(audit=>!passedAudits.includes(audit));const nonPassedElem=this._renderAuditGroup({title:`${nonPassedAudits.length} Failed Audits`,},{expandable:false});nonPassedElem.classList.add('lh-failed-audits');nonPassedAudits.forEach(audit=>nonPassedElem.appendChild(this._renderAudit(audit)));element.appendChild(nonPassedElem);if(passedAudits.length){const passedElem=this._renderPassedAuditsSection(passedAudits.map(audit=>this._renderAudit(audit)));element.appendChild(passedElem);} this._renderManualAudits(manualAudits,groupDefinitions,element);return element;} renderPerformanceCategory(category,groups){const element=this._dom.createElement('div','lh-category');this._createPermalinkSpan(element,category.id);element.appendChild(this._renderCategoryScore(category));const metricAudits=category.audits.filter(audit=>audit.group==='perf-metric');const metricAuditsEl=this._renderAuditGroup(groups['perf-metric'],{expandable:false});const timelineContainerEl=this._dom.createChildOf(metricAuditsEl,'div','lh-timeline-container');const timelineEl=this._dom.createChildOf(timelineContainerEl,'div','lh-timeline');let perfTimelineScale=0;metricAudits.forEach(audit=>{if(typeof audit.result.rawValue==='number'&&audit.result.rawValue){perfTimelineScale=Math.max(perfTimelineScale,audit.result.rawValue);}});const thumbnailAudit=category.audits.find(audit=>audit.id==='screenshot-thumbnails');const thumbnailResult=thumbnailAudit&&thumbnailAudit.result;if(thumbnailResult&&thumbnailResult.details){const thumbnailDetails=(thumbnailResult.details);perfTimelineScale=Math.max(perfTimelineScale,thumbnailDetails.scale);const filmstripEl=this._detailsRenderer.render(thumbnailDetails);timelineEl.appendChild(filmstripEl);} metricAudits.forEach(item=>{if(item.id==='speed-index-metric'||item.id==='estimated-input-latency'){return metricAuditsEl.appendChild(this._renderAudit(item));} timelineEl.appendChild(this._renderTimelineMetricAudit(item,perfTimelineScale));});metricAuditsEl.open=true;element.appendChild(metricAuditsEl);const hintAudits=category.audits.filter(audit=>audit.group==='perf-hint'&&audit.score<100).sort((auditA,auditB)=>auditB.result.rawValue-auditA.result.rawValue);if(hintAudits.length){const maxWaste=Math.max(...hintAudits.map(audit=>audit.result.rawValue));const scale=Math.ceil(maxWaste/1000)*1000;const hintAuditsEl=this._renderAuditGroup(groups['perf-hint'],{expandable:false});hintAudits.forEach(item=>hintAuditsEl.appendChild(this._renderPerfHintAudit(item,scale)));hintAuditsEl.open=true;element.appendChild(hintAuditsEl);} const infoAudits=category.audits.filter(audit=>audit.group==='perf-info'&&audit.score<100);if(infoAudits.length){const infoAuditsEl=this._renderAuditGroup(groups['perf-info'],{expandable:false});infoAudits.forEach(item=>infoAuditsEl.appendChild(this._renderAudit(item)));infoAuditsEl.open=true;element.appendChild(infoAuditsEl);} const passedElements=category.audits.filter(audit=>(audit.group==='perf-hint'||audit.group==='perf-info')&&audit.score===100).map(audit=>this._renderAudit(audit));if(!passedElements.length)return element;const passedElem=this._renderPassedAuditsSection(passedElements);element.appendChild(passedElem);return element;} _renderAccessibilityCategory(category,groupDefinitions){const element=this._dom.createElement('div','lh-category');this._createPermalinkSpan(element,category.id);element.appendChild(this._renderCategoryScore(category));const manualAudits=category.audits.filter(audit=>audit.result.manual);const nonManualAudits=category.audits.filter(audit=>!manualAudits.includes(audit));const auditsGroupedByGroup=({});nonManualAudits.forEach(audit=>{const groupId=audit.group;const groups=auditsGroupedByGroup[groupId]||{passed:[],failed:[],notApplicable:[]};if(audit.result.notApplicable){groups.notApplicable.push(audit);}else if(audit.score===100){groups.passed.push(audit);}else{groups.failed.push(audit);} auditsGroupedByGroup[groupId]=groups;});const passedElements=([]);const notApplicableElements=([]);Object.keys(auditsGroupedByGroup).forEach(groupId=>{const group=groupDefinitions[groupId];const groups=auditsGroupedByGroup[groupId];if(groups.failed.length){const auditGroupElem=this._renderAuditGroup(group,{expandable:false});groups.failed.forEach(item=>auditGroupElem.appendChild(this._renderAudit(item)));auditGroupElem.open=true;element.appendChild(auditGroupElem);} if(groups.passed.length){const auditGroupElem=this._renderAuditGroup(group,{expandable:true});groups.passed.forEach(item=>auditGroupElem.appendChild(this._renderAudit(item)));passedElements.push(auditGroupElem);} if(groups.notApplicable.length){const auditGroupElem=this._renderAuditGroup(group,{expandable:true});groups.notApplicable.forEach(item=>auditGroupElem.appendChild(this._renderAudit(item)));notApplicableElements.push(auditGroupElem);}});if(passedElements.length){const passedElem=this._renderPassedAuditsSection(passedElements);element.appendChild(passedElem);} if(notApplicableElements.length){const notApplicableElem=this._renderNotApplicableAuditsSection(notApplicableElements);element.appendChild(notApplicableElem);} this._renderManualAudits(manualAudits,groupDefinitions,element);return element;} _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;} CategoryRenderer.PerfHintExtendedInfo;;'use strict';class DetailsRenderer{constructor(dom){this._dom=dom;this._templateContext;} setTemplateContext(context){this._templateContext=context;} render(details){switch(details.type){case'text':return this._renderText(details);case'url':return this._renderTextURL(details);case'link':return this._renderLink((details));case'thumbnail':return this._renderThumbnail((details));case'filmstrip':return this._renderFilmstrip((details));case'cards':return this._renderCards((details));case'table':return this._renderTable((details));case'code':return this._renderCode(details);case'node':return this.renderNode((details));case'criticalrequestchain':return CriticalRequestChainRenderer.render(this._dom,this._templateContext,(details));case'list':return this._renderList((details));default:throw new Error(`Unknown type: ${details.type}`);}} _renderTextURL(text){const url=text.text||'';let displayedPath;let displayedHost;let title;try{const parsed=Util.parseURL(url);displayedPath=parsed.file;displayedHost=`(${parsed.hostname})`;title=url;}catch(e){if(!(e instanceof TypeError)){throw e;} displayedPath=url;} const element=this._dom.createElement('div','lh-text__url');element.appendChild(this._renderText({text:displayedPath,type:'text',}));if(displayedHost){const hostElem=this._renderText({text:displayedHost,type:'text',});hostElem.classList.add('lh-text__url-host');element.appendChild(hostElem);} if(title)element.title=url;return element;} _renderLink(details){const allowedProtocols=['https:','http:'];const url=new URL(details.url);if(!allowedProtocols.includes(url.protocol)){return this._renderText(details);} const a=(this._dom.createElement('a'));a.rel='noopener';a.target='_blank';a.textContent=details.text;a.href=url.href;return a;} _renderText(text){const element=this._dom.createElement('div','lh-text');element.textContent=text.text;return element;} _renderThumbnail(value){if(/^image/.test(value.mimeType)===false){return this._dom.createElement('span');} const element=this._dom.createElement('img','lh-thumbnail');element.src=value.url;element.alt='';element.title=value.url;return element;} _renderList(list){if(!list.items.length)return this._dom.createElement('span');const element=this._dom.createElement('details','lh-details');element.open=true;if(list.header){const summary=this._dom.createElement('summary','lh-list__header');summary.textContent=list.header.text;element.appendChild(summary);} const itemsElem=this._dom.createChildOf(element,'div','lh-list__items');for(const item of list.items){const itemElem=this._dom.createChildOf(itemsElem,'span','lh-list__item');itemElem.appendChild(this.render(item));} return element;} _renderTable(details){if(!details.items.length)return this._dom.createElement('span');const element=this._dom.createElement('details','lh-details');element.open=true;if(details.header){element.appendChild(this._dom.createElement('summary')).textContent=details.header;} const tableElem=this._dom.createChildOf(element,'table','lh-table');const theadElem=this._dom.createChildOf(tableElem,'thead');const theadTrElem=this._dom.createChildOf(theadElem,'tr');for(const heading of details.itemHeaders){const itemType=heading.itemType||'text';const classes=`lh-table-column--${itemType}`;this._dom.createChildOf(theadTrElem,'th',classes).appendChild(this.render(heading));} const tbodyElem=this._dom.createChildOf(tableElem,'tbody');for(const row of details.items){const rowElem=this._dom.createChildOf(tbodyElem,'tr');for(const columnItem of row){const classes=`lh-table-column--${columnItem.type}`;this._dom.createChildOf(rowElem,'td',classes).appendChild(this.render(columnItem));}} return element;} renderNode(item){const element=this._dom.createElement('span','lh-node');element.textContent=item.snippet;element.title=item.selector;if(item.text)element.setAttribute('data-text',item.text);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;} _renderCards(details){const element=this._dom.createElement('details','lh-details');element.open=true;if(details.header){element.appendChild(this._dom.createElement('summary')).textContent=details.header.text;} const cardsParent=this._dom.createElement('div','lh-scorecards');for(const item of details.items){const card=cardsParent.appendChild(this._dom.createElement('div','lh-scorecard',{title:item.snippet}));const titleEl=this._dom.createElement('div','lh-scorecard__title');const valueEl=this._dom.createElement('div','lh-scorecard__value');const targetEl=this._dom.createElement('div','lh-scorecard__target');card.appendChild(titleEl).textContent=item.title;card.appendChild(valueEl).textContent=item.value;if(item.target){card.appendChild(targetEl).textContent=`target: ${item.target}`;}} element.appendChild(cardsParent);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');let timing=Util.formatMilliseconds(thumbnail.timing,1);if(thumbnail.timing>1000){timing=Util.formatNumber(thumbnail.timing/1000)+' s';} const timingEl=this._dom.createChildOf(frameEl,'div','lh-filmstrip__timestamp');timingEl.textContent=timing;const base64data=thumbnail.data;this._dom.createChildOf(frameEl,'img','lh-filmstrip__thumbnail',{src:`data:image/jpeg;base64,${base64data}`,alt:`Screenshot at ${timing}`,});} return filmstripEl;} _renderCode(details){const pre=this._dom.createElement('pre','lh-code');pre.textContent=details.text;return pre;}} if(typeof module!=='undefined'&&module.exports){module.exports=DetailsRenderer;}else{self.DetailsRenderer=DetailsRenderer;} DetailsRenderer.DetailsJSON;DetailsRenderer.ListDetailsJSON;DetailsRenderer.NodeDetailsJSON;DetailsRenderer.CardsDetailsJSON;DetailsRenderer.TableHeaderJSON;DetailsRenderer.NodeDetailsJSON;DetailsRenderer.TableDetailsJSON;DetailsRenderer.ThumbnailDetails;DetailsRenderer.LinkDetailsJSON;DetailsRenderer.FilmstripDetails;;'use strict';class CriticalRequestChainRenderer{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};} 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;const newTreeMarkers=Array.isArray(treeMarkers)?treeMarkers.slice(0):[];if(typeof parentIsLastChild!=='undefined'){newTreeMarkers.push(!parentIsLastChild);} return{node,isLastChild,hasChildren,startTime,transferSize:transferSize+node.request.transferSize,treeMarkers:newTreeMarkers,};} static createChainNode(dom,tmpl,segment){const chainsEl=dom.cloneTemplate('#tmpl-lh-crc__chains',tmpl);dom.find('.crc-node',chainsEl).setAttribute('title',segment.node.request.url);const treeMarkeEl=dom.find('.crc-node__tree-marker',chainsEl);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'));} 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})`;if(!segment.hasChildren){const span=dom.createElement('span','crc-node__chain-duration');span.textContent=' - '+Util.chainDuration(segment.node.request.startTime,segment.node.request.endTime)+'ms, ';const span2=dom.createElement('span','crc-node__chain-duration');span2.textContent=Util.formatBytesToKB(segment.node.request.transferSize);treevalEl.appendChild(span);treevalEl.appendChild(span2);} return chainsEl;} static buildTree(dom,tmpl,segment,detailsEl,details){detailsEl.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,detailsEl,details);}} static render(dom,templateContext,details){const tmpl=dom.cloneTemplate('#tmpl-lh-crc',templateContext);dom.find('.lh-crc__longest_duration',tmpl).textContent=Util.formatNumber(details.longestChain.duration)+'ms';dom.find('.lh-crc__longest_length',tmpl).textContent=details.longestChain.length;dom.find('.lh-crc__longest_transfersize',tmpl).textContent=Util.formatBytesToKB(details.longestChain.transferSize);const detailsEl=dom.find('.lh-details',tmpl);detailsEl.open=true;dom.find('.lh-details > summary',tmpl).textContent=details.header.text;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,detailsEl,details);} return tmpl;}} if(typeof module!=='undefined'&&module.exports){module.exports=CriticalRequestChainRenderer;}else{self.CriticalRequestChainRenderer=CriticalRequestChainRenderer;} CriticalRequestChainRenderer.CRCDetailsJSON;CriticalRequestChainRenderer.CRCRequest;CriticalRequestChainRenderer.CRCNode=function(){};CriticalRequestChainRenderer.CRCNode.prototype.children;CriticalRequestChainRenderer.CRCNode.prototype.request;CriticalRequestChainRenderer.CRCSegment;;'use strict';class ReportRenderer{constructor(dom,categoryRenderer){this._dom=dom;this._categoryRenderer=categoryRenderer;this._templateContext=this._dom.document();} renderReport(report,container){container.textContent='';const element=container.appendChild(this._renderReport(report));return(element);} setTemplateContext(context){this._templateContext=context;this._categoryRenderer.setTemplateContext(context);} _renderReportHeader(report){const header=this._dom.cloneTemplate('#tmpl-lh-heading',this._templateContext);this._dom.find('.lh-config__timestamp',header).textContent=Util.formatDateTime(report.generatedTime);const url=this._dom.find('.lh-metadata__url',header);url.href=report.url;url.textContent=report.url;this._dom.find('.lh-env__item__ua',header).textContent=report.userAgent;const env=this._dom.find('.lh-env__items',header);report.runtimeConfig.environment.forEach(runtime=>{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;this._dom.find('.lh-env__enabled',item).textContent=runtime.enabled?'Enabled':'Disabled';env.appendChild(item);});return header;} _renderReportFooter(report){const footer=this._dom.cloneTemplate('#tmpl-lh-footer',this._templateContext);this._dom.find('.lh-footer__version',footer).textContent=report.lighthouseVersion;this._dom.find('.lh-footer__timestamp',footer).textContent=Util.formatDateTime(report.generatedTime);return footer;} _renderReportNav(report){const leftNav=this._dom.cloneTemplate('#tmpl-lh-leftnav',this._templateContext);this._dom.find('.leftnav__header__version',leftNav).textContent=`Version: ${report.lighthouseVersion}`;const nav=this._dom.find('.lh-leftnav',leftNav);for(const category of report.reportCategories){const itemsTmpl=this._dom.cloneTemplate('#tmpl-lh-leftnav__items',leftNav);const navItem=this._dom.find('.lh-leftnav__item',itemsTmpl);navItem.href=`#${category.id}`;this._dom.find('.leftnav-item__category',navItem).textContent=category.name;const score=this._dom.find('.leftnav-item__score',navItem);score.classList.add(`lh-score__value--${Util.calculateRating(category.score)}`);score.textContent=Math.round(category.score);nav.appendChild(navItem);} return leftNav;} _renderReportWarnings(report){if(!report.runWarnings||report.runWarnings.length===0){return this._dom.createElement('div');} const container=this._dom.cloneTemplate('#tmpl-lh-run-warnings',this._templateContext);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;} _renderReport(report){const container=this._dom.createElement('div','lh-container');container.appendChild(this._renderReportHeader(report));container.appendChild(this._renderReportNav(report));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=reportSection.appendChild(this._dom.createElement('div','lh-scores-header'));} const categories=reportSection.appendChild(this._dom.createElement('div','lh-categories'));for(const category of report.reportCategories){if(scoreHeader){scoreHeader.appendChild(this._categoryRenderer.renderScoreGauge(category));} categories.appendChild(this._categoryRenderer.render(category,report.reportGroups));} reportSection.appendChild(this._renderReportFooter(report));return container;}} if(typeof module!=='undefined'&&module.exports){module.exports=ReportRenderer;}else{self.ReportRenderer=ReportRenderer;} ReportRenderer.AuditJSON;ReportRenderer.CategoryJSON;ReportRenderer.GroupJSON;ReportRenderer.ReportJSON;;Audits2.RadioSetting=class{constructor(options,setting){this._setting=setting;this._options=options;this.element=createElement('div','audits2-radio-group');this._radioElements=[];for(const option of this._options){const fragment=UI.Fragment.build` `;this.element.appendChild(fragment.element());const radioElement=fragment.$('input');radioElement.addEventListener('change',this._valueChanged.bind(this));this._radioElements.push(radioElement);} this._ignoreChangeEvents=false;this._selectedIndex=-1;setting.addChangeListener(this._settingChanged,this);this._settingChanged();} _updateUI(){this._ignoreChangeEvents=true;this._radioElements[this._selectedIndex].checked=true;this._ignoreChangeEvents=false;} _settingChanged(){const value=this._setting.get();this._selectedIndex=this._options.findIndex(option=>option.value===value);this._updateUI();} _valueChanged(event){if(this._ignoreChangeEvents) return;const selectedRadio=this._radioElements.find(radio=>radio.checked);this._setting.set(selectedRadio.value);}};;Audits2.Audits2Panel=class extends UI.Panel{constructor(){super('audits2');this.registerRequiredCSS('audits2/lighthouse/report-styles.css');this.registerRequiredCSS('audits2/audits2Panel.css');this._protocolService=new Audits2.ProtocolService();this._controller=new Audits2.AuditController(this._protocolService);this._startView=new Audits2.StartView(this._controller);this._statusView=new Audits2.StatusView(this._controller);this._unauditableExplanation=null;this._cachedRenderedReports=new Map();this._dropTarget=new UI.DropTarget(this.contentElement,[UI.DropTarget.Type.File],Common.UIString('Drop audit file here'),this._handleDrop.bind(this));this._controller.addEventListener(Audits2.Events.PageAuditabilityChanged,this._refreshStartAuditUI.bind(this));this._controller.addEventListener(Audits2.Events.AuditProgressChanged,this._refreshStatusUI.bind(this));this._controller.addEventListener(Audits2.Events.RequestAuditStart,this._startAudit.bind(this));this._controller.addEventListener(Audits2.Events.RequestAuditCancel,this._cancelAudit.bind(this));this._renderToolbar();this.contentElement.createChild('div','audits2-dialog-overlay');this._auditResultsElement=this.contentElement.createChild('div','audits2-results-container');this._renderStartView();this._controller.recomputePageAuditability();} _refreshStartAuditUI(evt){this._unauditableExplanation=evt.data.helpText;this._startView.setUnauditableExplanation(evt.data.helpText);this._startView.setStartButtonEnabled(!evt.data.helpText);} _refreshStatusUI(evt){this._statusView.updateStatus(evt.data.message);} _refreshToolbarUI(){this._downloadButton.setEnabled(this._reportSelector.hasCurrentSelection());this._clearButton.setEnabled(this._reportSelector.hasItems());} _clearAll(){this._reportSelector.clearAll();this._renderStartView();this._refreshToolbarUI();} _downloadSelected(){this._reportSelector.downloadSelected();} _renderToolbar(){const toolbar=new UI.Toolbar('',this.element);this._newButton=new UI.ToolbarButton(Common.UIString('Perform an audit\u2026'),'largeicon-add');toolbar.appendToolbarItem(this._newButton);this._newButton.addEventListener(UI.ToolbarButton.Events.Click,this._renderStartView.bind(this));this._downloadButton=new UI.ToolbarButton(Common.UIString('Download report'),'largeicon-download');toolbar.appendToolbarItem(this._downloadButton);this._downloadButton.addEventListener(UI.ToolbarButton.Events.Click,this._downloadSelected.bind(this));toolbar.appendSeparator();this._reportSelector=new Audits2.ReportSelector(()=>this._renderStartView());toolbar.appendToolbarItem(this._reportSelector.comboBox());this._clearButton=new UI.ToolbarButton(Common.UIString('Clear all'),'largeicon-clear');toolbar.appendToolbarItem(this._clearButton);this._clearButton.addEventListener(UI.ToolbarButton.Events.Click,this._clearAll.bind(this));this._refreshToolbarUI();} _renderStartView(){this._auditResultsElement.removeChildren();this._statusView.hide();this._reportSelector.selectNewAudit();this.contentElement.classList.toggle('in-progress',false);this._startView.show(this.contentElement);this._startView.setUnauditableExplanation(this._unauditableExplanation);this._startView.setStartButtonEnabled(!this._unauditableExplanation);this._newButton.setEnabled(false);this._refreshToolbarUI();this.setDefaultFocusedChild(this._startView);} _renderStatusView(inspectedURL){this.contentElement.classList.toggle('in-progress',true);this._statusView.setInspectedURL(inspectedURL);this._statusView.show(this.contentElement);} _renderReport(lighthouseResult){this.contentElement.classList.toggle('in-progress',false);this._startView.hideWidget();this._statusView.hide();this._auditResultsElement.removeChildren();this._newButton.setEnabled(true);this._refreshToolbarUI();const cachedRenderedReport=this._cachedRenderedReports.get(lighthouseResult);if(cachedRenderedReport){this._auditResultsElement.appendChild(cachedRenderedReport);return;} const reportContainer=this._auditResultsElement.createChild('div','lh-vars lh-root lh-devtools');const dom=new DOM((this._auditResultsElement.ownerDocument));const detailsRenderer=new Audits2.DetailsRenderer(dom);const categoryRenderer=new Audits2.CategoryRenderer(dom,detailsRenderer);categoryRenderer.setTraceArtifact(lighthouseResult);const renderer=new Audits2.ReportRenderer(dom,categoryRenderer);const templatesHTML=Runtime.cachedResources['audits2/lighthouse/templates.html'];const templatesDOM=new DOMParser().parseFromString(templatesHTML,'text/html');if(!templatesDOM) return;renderer.setTemplateContext(templatesDOM);renderer.renderReport(lighthouseResult,reportContainer);this._cachedRenderedReports.set(lighthouseResult,reportContainer);} _buildReportUI(lighthouseResult){if(lighthouseResult===null) return;const optionElement=new Audits2.ReportSelector.Item(lighthouseResult,()=>this._renderReport(lighthouseResult),this._renderStartView.bind(this));this._reportSelector.prepend(optionElement);this._refreshToolbarUI();this._renderReport(lighthouseResult);} _handleDrop(dataTransfer){const items=dataTransfer.items;if(!items.length) return;const item=items[0];if(item.kind==='file'){const entry=items[0].webkitGetAsEntry();if(!entry.isFile) return;entry.file(file=>{const reader=new FileReader();reader.onload=()=>this._loadedFromFile((reader.result));reader.readAsText(file);});}} _loadedFromFile(report){const data=JSON.parse(report);if(!data['lighthouseVersion']) return;this._buildReportUI((data));} async _startAudit(){Host.userMetrics.actionTaken(Host.UserMetrics.Action.Audits2Started);try{const inspectedURL=await this._controller.getInspectedURL({force:true});const categoryIDs=this._controller.getCategoryIDs();const flags=this._controller.getFlags();await this._setupEmulationAndProtocolConnection();this._renderStatusView(inspectedURL);const lighthouseResult=await this._protocolService.startLighthouse(inspectedURL,categoryIDs,flags);if(lighthouseResult&&lighthouseResult.fatal){const error=new Error(lighthouseResult.message);error.stack=lighthouseResult.stack;throw error;} if(!lighthouseResult) throw new Error('Auditing failed to produce a result');Host.userMetrics.actionTaken(Host.UserMetrics.Action.Audits2Finished);await this._resetEmulationAndProtocolConnection();this._buildReportUI(lighthouseResult);}catch(err){if(err instanceof Error) this._statusView.renderBugReport(err);}} async _cancelAudit(){this._statusView.updateStatus(ls`Cancelling`);await this._resetEmulationAndProtocolConnection();this._renderStartView();} async _setupEmulationAndProtocolConnection(){const flags=this._controller.getFlags();const emulationModel=self.singleton(Emulation.DeviceModeModel);this._emulationEnabledBefore=emulationModel.enabledSetting().get();this._emulationOutlineEnabledBefore=emulationModel.deviceOutlineSetting().get();emulationModel.toolbarControlsEnabledSetting().set(false);if(flags.disableDeviceEmulation){emulationModel.enabledSetting().set(false);emulationModel.deviceOutlineSetting().set(false);emulationModel.emulate(Emulation.DeviceModeModel.Type.None,null,null);}else{emulationModel.enabledSetting().set(true);emulationModel.deviceOutlineSetting().set(true);for(const device of Emulation.EmulatedDevicesList.instance().standard()){if(device.title==='Nexus 5X') emulationModel.emulate(Emulation.DeviceModeModel.Type.Device,device,device.modes[0],1);}} await this._protocolService.attach();this._isLHAttached=true;} async _resetEmulationAndProtocolConnection(){if(!this._isLHAttached) return;this._isLHAttached=false;await this._protocolService.detach();const emulationModel=self.singleton(Emulation.DeviceModeModel);emulationModel.enabledSetting().set(this._emulationEnabledBefore);emulationModel.deviceOutlineSetting().set(this._emulationOutlineEnabledBefore);emulationModel.toolbarControlsEnabledSetting().set(true);Emulation.InspectedPagePlaceholder.instance().update(true);const resourceTreeModel=SDK.targetManager.mainTarget().model(SDK.ResourceTreeModel);const inspectedURL=await this._controller.getInspectedURL();await resourceTreeModel.navigate(inspectedURL);}};;Audits2.AuditController=class extends Common.Object{constructor(protocolService){super();protocolService.registerStatusCallback(message=>this.dispatchEventToListeners(Audits2.Events.AuditProgressChanged,{message}));for(const preset of Audits2.Presets) preset.setting.addChangeListener(this.recomputePageAuditability.bind(this));SDK.targetManager.observeModels(SDK.ServiceWorkerManager,this);SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged,this.recomputePageAuditability,this);} modelAdded(serviceWorkerManager){if(this._manager) return;this._manager=serviceWorkerManager;this._serviceWorkerListeners=[this._manager.addEventListener(SDK.ServiceWorkerManager.Events.RegistrationUpdated,this.recomputePageAuditability,this),this._manager.addEventListener(SDK.ServiceWorkerManager.Events.RegistrationDeleted,this.recomputePageAuditability,this),];this.recomputePageAuditability();} modelRemoved(serviceWorkerManager){if(this._manager!==serviceWorkerManager) return;Common.EventTarget.removeEventListeners(this._serviceWorkerListeners);this._manager=null;this.recomputePageAuditability();} _hasActiveServiceWorker(){if(!this._manager) return false;const mainTarget=this._manager.target();if(!mainTarget) return false;const inspectedURL=mainTarget.inspectedURL().asParsedURL();const inspectedOrigin=inspectedURL&&inspectedURL.securityOrigin();for(const registration of this._manager.registrations().values()){if(registration.securityOrigin!==inspectedOrigin) continue;for(const version of registration.versions.values()){if(version.controlledClients.length>1) return true;}} return false;} _hasAtLeastOneCategory(){return Audits2.Presets.some(preset=>preset.setting.get());} _unauditablePageMessage(){if(!this._manager) return null;const mainTarget=this._manager.target();const inspectedURL=mainTarget&&mainTarget.inspectedURL();if(inspectedURL&&!/^(http|chrome-extension)/.test(inspectedURL)){return Common.UIString('Can only audit HTTP/HTTPS pages and Chrome extensions. '+'Navigate to a different page to start an audit.');} if(!Host.isUnderTest()&&!Runtime.queryParam('can_dock')) return Common.UIString('Can only audit tabs. Navigate to this page in a separate tab to start an audit.');return null;} async _evaluateInspectedURL(){const mainTarget=this._manager.target();const runtimeModel=mainTarget.model(SDK.RuntimeModel);const executionContext=runtimeModel&&runtimeModel.defaultExecutionContext();let inspectedURL=mainTarget.inspectedURL();if(!executionContext) return inspectedURL;try{const result=await executionContext.evaluate({expression:'window.location.href',objectGroup:'audits',includeCommandLineAPI:false,silent:false,returnByValue:true,generatePreview:false},false,false);if(!result.exceptionDetails&&result.object){inspectedURL=result.object.value;result.object.release();}}catch(err){console.error(err);} return inspectedURL;} getFlags(){const flags={};for(const runtimeSetting of Audits2.RuntimeSettings) runtimeSetting.setFlags(flags,runtimeSetting.setting.get());return flags;} getCategoryIDs(){const categoryIDs=[];for(const preset of Audits2.Presets){if(preset.setting.get()) categoryIDs.push(preset.configID);} return categoryIDs;} async getInspectedURL(options){if(options&&options.force||!this._inspectedURL) this._inspectedURL=await this._evaluateInspectedURL();return this._inspectedURL;} recomputePageAuditability(){const hasActiveServiceWorker=this._hasActiveServiceWorker();const hasAtLeastOneCategory=this._hasAtLeastOneCategory();const unauditablePageMessage=this._unauditablePageMessage();let helpText='';if(hasActiveServiceWorker){helpText=Common.UIString('Multiple tabs are being controlled by the same service worker. '+'Close your other tabs on the same origin to audit this page.');}else if(!hasAtLeastOneCategory){helpText=Common.UIString('At least one category must be selected.');}else if(unauditablePageMessage){helpText=unauditablePageMessage;} this.dispatchEventToListeners(Audits2.Events.PageAuditabilityChanged,{helpText});}};Audits2.Preset;Audits2.Presets=[{setting:Common.settings.createSetting('audits2.cat_perf',true),configID:'performance',title:'Performance',description:'How long does this app take to show content and become usable'},{setting:Common.settings.createSetting('audits2.cat_pwa',true),configID:'pwa',title:'Progressive Web App',description:'Does this page meet the standard of a Progressive Web App'},{setting:Common.settings.createSetting('audits2.cat_best_practices',true),configID:'best-practices',title:'Best practices',description:'Does this page follow best practices for modern web development'},{setting:Common.settings.createSetting('audits2.cat_a11y',true),configID:'accessibility',title:'Accessibility',description:'Is this page usable by people with disabilities or impairments'},{setting:Common.settings.createSetting('audits2.cat_seo',true),configID:'seo',title:'SEO',description:'Is this page optimized for search engine results ranking'},];Audits2.RuntimeSetting;Audits2.RuntimeSettings=[{setting:Common.settings.createSetting('audits2.device_type','mobile'),description:ls`Apply mobile emulation during auditing`,setFlags:(flags,value)=>{flags.disableDeviceEmulation=value==='desktop';},options:[{label:ls`Mobile`,value:'mobile'},{label:ls`Desktop`,value:'desktop'},],},{setting:Common.settings.createSetting('audits2.throttling','default'),description:ls`Apply network and CPU throttling during performance auditing`,setFlags:(flags,value)=>{flags.disableNetworkThrottling=value==='off';flags.disableCpuThrottling=value==='off';},options:[{label:ls`Fast 3G with 4x CPU Slowdown`,value:'default'},{label:ls`No throttling`,value:'off'},],},{setting:Common.settings.createSetting('audits2.clear_storage',true),title:ls`Clear storage`,description:ls`Reset storage (localStorage, IndexedDB, etc) to a clean baseline before auditing`,setFlags:(flags,value)=>{flags.disableStorageReset=!value;},},];Audits2.Events={PageAuditabilityChanged:Symbol('PageAuditabilityChanged'),AuditProgressChanged:Symbol('AuditProgressChanged'),RequestAuditStart:Symbol('RequestAuditStart'),RequestAuditCancel:Symbol('RequestAuditCancel'),};;Audits2.ReportSelector=class{constructor(renderNewAuditView){this._renderNewAuditView=renderNewAuditView;this._newAuditItem=createElement('option');this._comboBox=new UI.ToolbarComboBox(this._handleChange.bind(this),'audits2-report');this._comboBox.setMaxWidth(180);this._comboBox.setMinWidth(140);this._itemByOptionElement=new Map();this._setEmptyState();} _setEmptyState(){this._comboBox.selectElement().removeChildren();this._comboBox.setEnabled(false);this._newAuditItem=createElement('option');this._newAuditItem.label=Common.UIString('(new audit)');this._comboBox.selectElement().appendChild(this._newAuditItem);this._comboBox.select(this._newAuditItem);} _handleChange(event){const item=this._selectedItem();if(item) item.select();else this._renderNewAuditView();} _selectedItem(){const option=this._comboBox.selectedOption();return this._itemByOptionElement.get(option);} hasCurrentSelection(){return!!this._selectedItem();} hasItems(){return this._itemByOptionElement.size>0;} comboBox(){return this._comboBox;} prepend(item){const optionEl=item.optionElement();const selectEl=this._comboBox.selectElement();this._itemByOptionElement.set(optionEl,item);selectEl.insertBefore(optionEl,selectEl.firstElementChild);this._comboBox.setEnabled(true);this._comboBox.select(optionEl);item.select();} clearAll(){for(const elem of this._comboBox.options()){if(elem===this._newAuditItem) continue;this._itemByOptionElement.get(elem).delete();this._itemByOptionElement.delete(elem);} this._setEmptyState();} downloadSelected(){const item=this._selectedItem();if(item) item.download();} selectNewAudit(){this._comboBox.select(this._newAuditItem);}};Audits2.ReportSelector.Item=class{constructor(lighthouseResult,renderReport,showLandingCallback){this._lighthouseResult=lighthouseResult;this._renderReport=renderReport;this._showLandingCallback=showLandingCallback;const url=new Common.ParsedURL(lighthouseResult.url);const timestamp=lighthouseResult.generatedTime;this._element=createElement('option');this._element.label=`${new Date(timestamp).toLocaleTimeString()} - ${url.domain()}`;} select(){this._renderReport();} optionElement(){return this._element;} delete(){if(this._element) this._element.remove();this._showLandingCallback();} download(){const url=new Common.ParsedURL(this._lighthouseResult.url).domain();const timestamp=this._lighthouseResult.generatedTime;const fileName=`${url}-${new Date(timestamp).toISO8601Compact()}.json`;Workspace.fileManager.save(fileName,JSON.stringify(this._lighthouseResult),true);}};;Audits2.ReportRenderer=class extends ReportRenderer{_renderReportNav(){return createDocumentFragment();} _renderReportHeader(report){return createDocumentFragment();}};class ReportUIFeatures{initFeatures(report){}} Audits2.CategoryRenderer=class extends CategoryRenderer{constructor(dom,detailsRenderer){super(dom,detailsRenderer);this._defaultPassTrace=null;} setTraceArtifact(lhr){if(!lhr.artifacts||!lhr.artifacts.traces||!lhr.artifacts.traces.defaultPass) return;this._defaultPassTrace=lhr.artifacts.traces.defaultPass;} renderPerformanceCategory(category,groups){const defaultPassTrace=this._defaultPassTrace;const element=super.renderPerformanceCategory(category,groups);if(!defaultPassTrace) return element;const timelineButton=UI.createTextButton(Common.UIString('View Trace'),onViewTraceClick,'view-trace');element.querySelector('.lh-audit-group').prepend(timelineButton);return element;async function onViewTraceClick(){await UI.inspectorView.showPanel('timeline');Timeline.TimelinePanel.instance().loadFromEvents(defaultPassTrace.traceEvents);}}};Audits2.DetailsRenderer=class extends DetailsRenderer{constructor(dom){super(dom);this._onLoadPromise=null;} renderNode(item){const element=super.renderNode(item);this._replaceWithDeferredNodeBlock(element,item);return element;} async _replaceWithDeferredNodeBlock(origElement,detailsItem){const mainTarget=SDK.targetManager.mainTarget();if(!this._onLoadPromise){const resourceTreeModel=mainTarget.model(SDK.ResourceTreeModel);this._onLoadPromise=resourceTreeModel.once(SDK.ResourceTreeModel.Events.Load);} await this._onLoadPromise;const domModel=mainTarget.model(SDK.DOMModel);if(!detailsItem.path) return;const nodeId=await domModel.pushNodeByPathToFrontend(detailsItem.path);if(!nodeId) return;const node=domModel.nodeForId(nodeId);if(!node) return;const element=await Common.Linkifier.linkify(node,({title:detailsItem.snippet}));origElement.title='';origElement.textContent='';origElement.appendChild(element);}};;Audits2.StartView=class extends UI.Widget{constructor(controller){super();this.registerRequiredCSS('audits2/audits2StartView.css');this._controller=controller;this._render();} _populateRuntimeSettingAsRadio(settingName,parentElement){const runtimeSetting=Audits2.RuntimeSettings.find(item=>item.setting.name===settingName);if(!runtimeSetting||!runtimeSetting.options) throw new Error(`${settingName} is not a setting with options`);const control=new Audits2.RadioSetting(runtimeSetting.options,runtimeSetting.setting);control.element.title=runtimeSetting.description;parentElement.appendChild(control.element);} _populateRuntimeSettingAsCheckbox(settingName,parentElement){const runtimeSetting=Audits2.RuntimeSettings.find(item=>item.setting.name===settingName);if(!runtimeSetting||!runtimeSetting.title) throw new Error(`${settingName} is not a setting with a title`);runtimeSetting.setting.setTitle(runtimeSetting.title);const control=new UI.ToolbarSettingCheckbox(runtimeSetting.setting,runtimeSetting.description);parentElement.appendChild(control.element);} _populateFormControls(fragment){const deviceTypeFormElements=fragment.$('device-type-form-elements');this._populateRuntimeSettingAsRadio('audits2.device_type',deviceTypeFormElements);const categoryFormElements=fragment.$('categories-form-elements');for(const preset of Audits2.Presets){preset.setting.setTitle(preset.title);const checkbox=new UI.ToolbarSettingCheckbox(preset.setting);const row=categoryFormElements.createChild('div','vbox audits2-launcher-row');row.title=preset.description;row.appendChild(checkbox.element);} const throttlingFormElements=fragment.$('throttling-form-elements');this._populateRuntimeSettingAsRadio('audits2.throttling',throttlingFormElements);const otherFormElements=fragment.$('other-form-elements');this._populateRuntimeSettingAsCheckbox('audits2.clear_storage',otherFormElements);} _render(){this._startButton=UI.createTextButton(ls`Run audits`,()=>this._controller.dispatchEventToListeners(Audits2.Events.RequestAuditStart),'audits2-start-button',true);this.setDefaultFocusedElement(this._startButton);const deviceIcon=UI.Icon.create('largeicon-phone');const categoriesIcon=UI.Icon.create('largeicon-checkmark');const throttlingIcon=UI.Icon.create('largeicon-settings-gear');const fragment=UI.Fragment.build`
Identify and fix common problems that affect your site's performance, accessibility, and user experience. Learn more