* Fix bug where an icons font is counted as two unused unicode ranges * Display the number of hidden chars
485 lines
28 KiB
HTML
485 lines
28 KiB
HTML
<div ng-include="'views/resultSubHeader.html'"></div>
|
|
<div class="rule board">
|
|
<div class="backToDashboard"><a href="#" ng-click="backToDashboard()">Back to dashboard</a></div>
|
|
|
|
<div ng-if="rule" class="ruleTable">
|
|
<div class="left">
|
|
<h2>{{rule.policy.label}}</h2>
|
|
<grade score="rule.score" class="score"></grade>
|
|
<div>{{rule.score}}/100</div>
|
|
</div>
|
|
<div class="right">
|
|
<h3>
|
|
Value:
|
|
<span ng-if="rule.policy.unit == 'bytes'">{{rule.value | bytes}}</span>
|
|
<span ng-if="rule.policy.unit != 'bytes'">{{rule.value}}</span>
|
|
</h3>
|
|
<div class="okThreshold" ng-if="rule.score < 100 && rule.policy.isOkThreshold !== undefined">
|
|
Have
|
|
<span ng-if="rule.policy.unit == 'bytes'">{{rule.policy.isOkThreshold | bytes}}</span>
|
|
<span ng-if="rule.policy.unit != 'bytes'">{{rule.policy.isOkThreshold}}</span>
|
|
<span ng-if="rule.policy.isOkThreshold > 0 && rule.policy.isOkThreshold < rule.policy.isBadThreshold">or less</span>
|
|
<span ng-if="rule.policy.isOkThreshold > rule.policy.isBadThreshold">or more</span>
|
|
to get the 100/100 score.
|
|
</div>
|
|
<div ng-bind-html="rule.policy.message" class="message"></div>
|
|
</div>
|
|
</div>
|
|
<div ng-if="rule.abnormal" class="warning">
|
|
<h3>Warning</h3>
|
|
<p>This rule reached the abnormality threshold, which means there is a real problem you should care about.</p>
|
|
</div>
|
|
<div class="offenders" ng-if="rule.policy.hasOffenders">
|
|
<h3 ng-if="rule.offendersObj.count >= 0"><ng-pluralize count="rule.offendersObj.count" when="{'0': 'No offenders', 'one': '1 offender', 'other': '{} offenders'}"></ng-pluralize></h3>
|
|
|
|
<div ng-if="rule.offendersObj.list" class="offendersTable">
|
|
<div ng-repeat="offender in rule.offendersObj.list track by $index">
|
|
<div ng-if="offender.parseError">
|
|
{{offender.parseError}}
|
|
</div>
|
|
<div ng-if="!offender.parseError">
|
|
|
|
<div ng-if="policyName === 'DOMidDuplicated'">
|
|
<b>{{offender.id}}</b>: {{offender.occurrences}} occurrences
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'DOMqueriesAvoidable'">
|
|
<b>{{offender.query}}</b> (in <dom-element-button obj="offender.context"></dom-element-button>) using {{offender.fn}}: <b>{{offender.count}} queries</b>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'eventsScrollBound'">
|
|
<span ng-if="offender.target == 'window'">Scroll event bound on <b>window</b></span>
|
|
<span ng-if="offender.target == '#document'">Scroll event bound on <b>document</b></span>
|
|
<span ng-if="offender.target == 'window.onscroll'"><b>window.onscroll</b> function declared</span>
|
|
<div class="offenderButton" ng-if="offender.backtrace.length == 0">no backtrace</div>
|
|
<div class="offenderButton opens" ng-if="offender.backtrace.length > 0">
|
|
backtrace
|
|
<div class="backtrace">
|
|
<div ng-repeat="obj in offender.backtrace track by $index">
|
|
<span ng-if="obj.functionName">{{obj.functionName}}()</span>
|
|
<url-link url="obj.file" max-length="60"></url-link>
|
|
line {{obj.line}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'jsErrors'">
|
|
<b>{{offender.error}}</b>
|
|
<div class="offenderButton" ng-if="offender.backtrace.length == 0">no backtrace</div>
|
|
<div class="offenderButton opens" ng-if="offender.backtrace.length > 0">
|
|
backtrace
|
|
<div class="backtrace">
|
|
<div ng-repeat="obj in offender.backtrace track by $index">
|
|
<span ng-if="obj.functionName">{{obj.functionName}}()</span>
|
|
<url-link url="obj.file" max-length="60"></url-link>
|
|
line {{obj.line}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'jQueryFunctionsUsed'">
|
|
function <b>{{offender.functionName}}</b> used {{offender.count}} times
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'documentWriteCalls'">
|
|
<b>{{offender.writeFn}}</b>
|
|
<span ng-if="offender.from">
|
|
called from
|
|
<span ng-if="offender.from.functionName">{{offender.from.functionName}}()</span>
|
|
<url-link url="offender.from.file" max-length="50"></url-link>
|
|
line {{offender.from.line}}
|
|
</span>
|
|
<span ng-if="!offender.from">
|
|
called from (no backtrace available)
|
|
</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssRules'">
|
|
<span ng-if="offender.file === 'inline CSS'">inline CSS</span>
|
|
<span ng-if="offender.file !== 'inline CSS'"><url-link url="offender.file" max-length="80"></url-link></span>
|
|
: <ng-pluralize count="offender.rules" when="{'0': '0 rule', 'one':'1 rule','other':'{} rules'}"></ng-pluralize>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'similarColors'">
|
|
<div class="similarColors checker"><div ng-style="{'background-color': offender.color1, 'color': offender.isDark ? '#FFF' : '#000'}">{{offender.color1}}</div><div ng-style="{'background-color': offender.color2, 'color': offender.isDark ? '#FFF' : '#000'}">{{offender.color2}}</div></div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssParsingErrors'">
|
|
<b>{{offender.error}}</b>
|
|
<file-and-line file="offender.file" line="offender.line" column="offender.column"></file-and-line>
|
|
<span ng-if="offender.file">(<a href="http://jigsaw.w3.org/css-validator/validator?profile=css3&usermedium=all&warning=no&uri={{offender.file | encodeURIComponent}}" target="_blank">Check on the W3C validator</a>)</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssImports'">
|
|
{{offender.css}}
|
|
<file-and-line-button file="offender.file" line="offender.line" column="offender.column"></file-and-line-button>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssDuplicatedSelectors'">
|
|
{{offender.rule}} (<b>x{{offender.occurrences}}</b>)
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssOldPropertyPrefixes'">
|
|
<b>{{offender.property}} {{offender.message}}</b>
|
|
<div ng-if="offender.rules.length" ng-click="offender.showMore = !offender.showMore" class="offenderButton">
|
|
<span ng-if="!offender.showMore">show</span>
|
|
<span ng-if="offender.showMore">hide</span>
|
|
<ng-pluralize count="offender.rules.length" when="{'one':'1 offender','other':'{} offenders'}"></ng-pluralize>
|
|
</div>
|
|
<div ng-if="offender.showMore" class="smallerOffenders">
|
|
<div ng-repeat="cssRule in offender.rules">
|
|
{{cssRule.rule}} {{'{' + offender.property}}: {{cssRule.value + '}' }}
|
|
<file-and-line-button file="cssRule.file" line="cssRule.line" column="cssRule.column"></file-and-line-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'lazyLoadableImagesBelowTheFold' || policyName === 'hiddenImages'">
|
|
<img ng-src="{{offender}}" class="smallPreview checker"></img>
|
|
<url-link url="offender" max-length="100"></url-link>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'notFound' || policyName === 'emptyRequests' || policyName === 'closedConnections' || policyName === 'multipleRequests' || policyName === 'cachingDisabled' || policyName === 'cachingNotSpecified'">
|
|
<url-link url="offender" max-length="100"></url-link>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cachingTooShort'">
|
|
<url-link url="offender.file" max-length="100"></url-link>
|
|
cached for <b>{{offender.ttlWithUnit}} {{offender.unit}}</b>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'domains'">
|
|
<b>{{offender.domain}}</b>
|
|
(<ng-pluralize count="offender.requests" when="{'one':'1 request','other':'{} requests'}"></ng-pluralize>)
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'globalVariables' || policyName === 'jQueryVersionsLoaded' || policyName === 'synchronousXHR'">
|
|
{{offender}}
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'fontsCount'">
|
|
<url-link url="offender.url" max-length="70"></url-link>
|
|
({{offender.size | bytes}})
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-repeat="fileDetails in rule.offendersObj.byFile track by $index">
|
|
<h3>
|
|
<ng-pluralize count="fileDetails.count" when="{'one': '1 offender', 'other': '{} offenders'}"></ng-pluralize>
|
|
in
|
|
<url-link ng-if="fileDetails.url !== 'Inline CSS'" url="fileDetails.url" max-length="80"></url-link>
|
|
<span ng-if="fileDetails.url === 'Inline CSS'">inline CSS</span>
|
|
</h3>
|
|
|
|
<div class="offendersTable">
|
|
<div ng-repeat="offender in fileDetails.offenders track by $index">
|
|
<div ng-if="policyName === 'cssComplexSelectors' || policyName === 'cssComplexSelectorsByAttribute' || policyName === 'cssUniversalSelectors' || policyName === 'cssRedundantBodySelectors' || policyName === 'cssRedundantChildNodesSelectors'">
|
|
<span ng-if="offender.bolded" ng-bind-html="offender.bolded"></span>
|
|
<b ng-if="!offender.bolded">{{offender.css}}</b>
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssMobileFirst'">
|
|
<b>{{offender.query}}</b> for <ng-pluralize count="offender.rules" when="{'one':'1 rule','other':'{} rules'}"></ng-pluralize>
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssDuplicatedProperties'">
|
|
Property <b>{{offender.property}}</b> duplicated in <b>{{offender.rule}} { }</b>
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssEmptyRules'">
|
|
<b>{{offender.css}} { }</b>
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssExpressions'">
|
|
{{offender.rule}} {{ '{' + offender.property}}: <b>expression(</b>{{offender.expression}}<b>)</b>}
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssImportants'">
|
|
{{offender.rule}} {{ '{' + offender.property}}: {{offender.value}} <b>!important</b>}
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssOldIEFixes'">
|
|
<span ng-if="offender.browser"><b>{{offender.browser}} fix:</b></span>
|
|
<span ng-bind-html="offender.bolded"></span>
|
|
<span ng-if="offender.line !== null && offender.column !== null"> @ {{offender.line}}:{{offender.column}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="!rule.offendersObj.list && !rule.offendersObj.byFile" class="offendersHtml">
|
|
|
|
<div ng-if="policyName === 'DOMelementMaxDepth'">
|
|
<dom-tree tree="rule.offendersObj.tree"></dom-tree>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'DOMaccessesOnScroll' && rule.offendersObj.children.length > 0">
|
|
<p>The table below shows the interactions between the JavaScript and the DOM on a scroll event.</p>
|
|
<div class="table" ng-class="{warningsFilterOn: warningsFilterOn}">
|
|
<div class="headers">
|
|
<div><!-- index --></div>
|
|
<div>Type</div>
|
|
<div>Params</div>
|
|
<div><!-- details --></div>
|
|
</div>
|
|
<profiler-line ng-repeat="node in rule.offendersObj.children" data-index="$index" node="node"></profiler-line>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssColors' && rule.offendersObj.count > 0">
|
|
<p>This is the colors palette, sized by total occurrences:</p>
|
|
<div class="colorPalette checker">
|
|
<div ng-repeat="offender in rule.offendersObj.palette" style="background-color: {{offender.color}}; width: {{offender.occurrences * 100 / rule.offendersObj.palette[0].occurrences}}%"><div>{{offender.color}} ({{offender.occurrences}} times)</div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'totalWeight'">
|
|
<h3>Weight by MIME type</h3>
|
|
<div class="totalWeightPie">
|
|
<canvas class="chart chart-doughnut" chart-data="weightData" chart-labels="weightLabels" chart-options="weightOptions" chart-colors="weightColours"></canvas>
|
|
</div>
|
|
<div ng-repeat="type in weightLabels">
|
|
<h3>{{rule.offendersObj.list.byType[type].totalWeight | bytes}} of {{type}}</h3>
|
|
<div class="offendersTable">
|
|
<div ng-repeat="request in rule.offendersObj.list.byType[type].requests | orderBy:'-weight'" ng-if="request.weight > 0">
|
|
<div><url-link url="request.url" max-length="60"></url-link></div>
|
|
<div ng-class="{offenderProblem: request.weight > 102400}">{{request.weight | bytes}}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'imageOptimization'">
|
|
<h3 ng-if="rule.value > 0">{{rule.value | bytes}} could be saved on <ng-pluralize count="rule.offendersObj.list.images.length" when="{'one': '1 image', 'other': '{} images'}"></ng-pluralize></h3>
|
|
<div class="imageOffenders">
|
|
<div ng-repeat="image in rule.offendersObj.list.images | orderBy:'-gain'">
|
|
<div>
|
|
Current file: <url-link url="image.url" max-length="50"></url-link>
|
|
<div><a href="{{image.url}}" target="_blank"><img ng-src="{{image.url}}" class="checker" /></a></div>
|
|
</div>
|
|
<div>
|
|
<p ng-if="!image.afterCompression">Current weight: {{image.original | bytes}}</p>
|
|
<p ng-if="image.afterCompression">Current weight: {{image.original | bytes}} ({{image.afterCompression | bytes}} gzipped)</p>
|
|
<p ng-if="image.lossless && image.afterOptimizationAndCompression">With a lossless optimization:<br/>{{image.afterOptimizationAndCompression | bytes}} gzipped (<b>-{{image.gain | bytes}}</b> gzipped)</p>
|
|
<p ng-if="image.lossless && !image.afterOptimizationAndCompression">With a lossless optimization:<br/>{{image.lossless | bytes}} <span ng-if="!image.lossy">(<b>-{{image.gain | bytes}}</b>)</span></p>
|
|
<p ng-if="image.lossy && image.afterOptimizationAndCompression">With a lossy optimization:<br/>{{image.afterOptimizationAndCompression | bytes}} gzipped (<b>-{{image.gain | bytes}} gzipped</b>)</p>
|
|
<p ng-if="image.lossy && !image.afterOptimizationAndCompression">With a lossy optimization:<br/>{{image.lossy | bytes}} (<b>-{{image.gain | bytes}}</b>)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'gzipCompression'">
|
|
<h3 ng-if="rule.value > 0">{{rule.value | bytes}} could be saved on <ng-pluralize count="rule.offendersObj.list.images.length" when="{'one': '1 file', 'other': '{} files'}"></ng-pluralize></h3>
|
|
<div class="table">
|
|
<div class="headers">
|
|
<div>File</div>
|
|
<div>Current weight</div>
|
|
<div>Gzipped</div>
|
|
<div>Gain</div>
|
|
</div>
|
|
<div ng-repeat="file in rule.offendersObj.list.files | orderBy:'-gain'">
|
|
<div>
|
|
<url-link url="file.url" max-length="70"></url-link>
|
|
</div>
|
|
<div>{{file.original | bytes}}</div>
|
|
<div>{{file.gzipped | bytes}}</div>
|
|
<div><b>-{{file.gain | bytes}}</b></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'fileMinification'">
|
|
<h3 ng-if="rule.value > 0">{{rule.value | bytes}} could be saved on <ng-pluralize count="rule.offendersObj.list.files.length" when="{'one': '1 file', 'other': '{} files'}"></ng-pluralize></h3>
|
|
<div class="table">
|
|
<div class="headers">
|
|
<div>File</div>
|
|
<div>Current weight</div>
|
|
<div>Minified</div>
|
|
<div>Gain</div>
|
|
</div>
|
|
<div ng-repeat="file in rule.offendersObj.list.files | orderBy:'-gain'">
|
|
<div>
|
|
<url-link url="file.url" max-length="70"></url-link>
|
|
</div>
|
|
<div ng-if="!file.afterCompression">{{file.original | bytes}} (gzipped)</div>
|
|
<div ng-if="file.afterCompression">{{file.original | bytes}} ({{file.afterCompression | bytes}} gzipped)</div>
|
|
<div ng-if="!file.afterCompression">{{file.afterOptimizationAndCompression | bytes}} (gzipped)</div>
|
|
<div ng-if="file.afterCompression">{{file.optimized | bytes}} ({{file.afterOptimizationAndCompression | bytes}} gzipped)</div>
|
|
<div><b>-{{file.gain | bytes}}</b></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'totalRequests'">
|
|
<h3>Requests by MIME type</h3>
|
|
<div ng-repeat="(type, requests) in rule.offendersObj.list.byType">
|
|
<h3><ng-pluralize count="requests.length" when="{'0': 'No ' + type + ' request', 'one': '1 ' + type + ' request', 'other': '{} ' + type + ' requests'}"></ng-pluralize></h3>
|
|
<p ng-if="type == 'css' && requests.length > 2">Reduce the number of stylesheets by concatenating them.</p>
|
|
<p ng-if="type == 'js' && requests.length > 3">Reduce the number of scripts by concatenating them.</p>
|
|
<p ng-if="type == 'image' && requests.length > 5">Reduce the number of images by lazyloading them or by spriting them.</p>
|
|
<p ng-if="type == 'webfont' && requests.length > 1">Fonts are generally loaded on the critical path of the head. Load as few as possible.</p>
|
|
<p ng-if="type == 'other' && requests.length > 0">They can be Flash, XML, music or any undetected format.</p>
|
|
<div class="offendersTable">
|
|
<div ng-repeat="request in requests track by $index">
|
|
<div><url-link url="request" max-length="100"></url-link></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'identicalFiles'">
|
|
<div ng-repeat="offender in rule.offendersObj.list track by $index">
|
|
<h4>A file of {{offender.weight | bytes}} is loaded {{offender.urls.length}} times:</h4>
|
|
<div class="offendersTable">
|
|
<div ng-repeat="url in offender.urls">
|
|
<div><url-link url="url" max-length="100"></url-link></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'smallRequests'">
|
|
<div ng-repeat="(type, requests) in rule.offendersObj.list.byType">
|
|
<h3><ng-pluralize count="requests.length" when="{'0': 'small ' + type + ' file', 'one': '1 small ' + type + ' file', 'other': '{} small ' + type + ' files'}"></ng-pluralize></h3>
|
|
<p ng-if="type == 'css' && requests.length > 0">Try to inline these styles in the head of the HTML or to merge them with other files.</p>
|
|
<p ng-if="type == 'js' && requests.length > 0">Try to inline these scripts in the HTML or merge them with other files.</p>
|
|
<p ng-if="type == 'image' && requests.length > 0">Try to inline these images (with base64 encoding for most image types except SVG that don't need base64 encoding). You can also create sprites.</p>
|
|
<div class="table">
|
|
<div class="headers">
|
|
<div ng-if="type == 'image'">Preview</div>
|
|
<div>File</div>
|
|
<div>Weight (bytes)</div>
|
|
</div>
|
|
<div ng-repeat="request in requests track by $index">
|
|
<div ng-if="type == 'image'"><img ng-src="{{request.url}}" class="smallPreview checker" /></div>
|
|
<div><url-link url="request.url" max-length="100"></url-link></div>
|
|
<div>{{request.size}}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'DOMaccesses'">
|
|
<h3>{{rule.value}} offenders</h3>
|
|
Please open the <a href="result/{{runId}}/timeline">JS timeline</a>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'queriesWithoutResults'">
|
|
<h3>{{rule.value}} offenders</h3>
|
|
Please open the <a href="result/{{runId}}/timeline#filter=queryWithoutResults">JS timeline, filtered by "Queries without results"</a>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'jQueryCallsOnEmptyObject'">
|
|
<h3>{{rule.value}} offenders</h3>
|
|
Please open the <a href="result/{{runId}}/timeline#filter=jQueryCallOnEmptyObject">JS timeline, filtered by "jQuery calls on empty object"</a>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'jQueryNotDelegatedEvents'">
|
|
<h3>{{rule.value}} offenders</h3>
|
|
Please open the <a href="result/{{runId}}/timeline#filter=eventNotDelegated">JS timeline, filtered by "Events not delegated"</a>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'cssBreakpoints'">
|
|
<div ng-if="rule.value > 0" class="cssBreakpointsGraph">
|
|
<h3>Breakpoints distribution graph</h3>
|
|
<canvas class="chart chart-line" chart-data="breakpointsData" chart-labels="breakpointsLabels" chart-options="breakpointsOptions" chart-colors="breakpointsColours" chart-series="breakpointsSeries" width="600" height="250"></canvas>
|
|
<h3>Breakpoints list</h3>
|
|
<div class="offendersTable">
|
|
<div ng-repeat="offender in rule.offendersObj | orderBy:'pixels'">
|
|
<div>Breakpoint <b>{{offender.breakpoint}}</b> involves <ng-pluralize count="offender.count" when="{'one': '1 rule', 'other': '{} rules'}"></ng-pluralize></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div ng-if="rule.value === 0">
|
|
No breakpoint
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'heavyFonts'">
|
|
<div ng-repeat="font in rule.offendersObj.fonts | orderBy:'-weight' track by $index">
|
|
<h3><url-link url="font.url" max-length="80"></url-link></h3>
|
|
<div class="offendersTable">
|
|
<div>
|
|
<div>Weight</div>
|
|
<div ng-if="font.weight <= 40960">{{font.weight | bytes}}</div>
|
|
<div ng-if="font.weight > 40960" class="offenderProblem">{{font.weight | bytes}}</div>
|
|
</div>
|
|
<div>
|
|
<div>Number of glyphs</div>
|
|
<div ng-if="font.numGlyphs <= 500">{{font.numGlyphs}}</div>
|
|
<div ng-if="font.numGlyphs > 500" class="offenderProblem">{{font.numGlyphs}} (better < 500)</div>
|
|
</div>
|
|
<div>
|
|
<div>Average glyph complexity</div>
|
|
<div ng-if="font.averageGlyphComplexity <= 35">{{font.averageGlyphComplexity}}</div>
|
|
<div ng-if="font.averageGlyphComplexity > 35" class="offenderProblem">{{font.averageGlyphComplexity}} (better < 35)</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'unusedUnicodeRanges'">
|
|
<div ng-repeat="font in rule.offendersObj.fonts | orderBy:'-compressedWeigth' track by $index">
|
|
<h3><url-link url="font.url" max-length="60"></url-link> ({{font.weight | bytes}})</h3>
|
|
<div ng-if="font.isIconFont" class="offendersTable">
|
|
<div>
|
|
<div>
|
|
This font seems to be an icon font
|
|
<span ng-if="font.numGlyphsInCommonWithPageContent / font.glyphs <= 0.05" class="offenderProblem">but only {{font.numGlyphsInCommonWithPageContent}} of its {{font.glyphs}} glyphs <ng-pluralize count="font.numGlyphsInCommonWithPageContent" when="{'one': 'is', 'other': 'are'}"></ng-pluralize> possibly used!</span>
|
|
<span ng-if="font.numGlyphsInCommonWithPageContent / font.glyphs > 0.05">and {{font.numGlyphsInCommonWithPageContent}} of its {{font.glyphs}} glyphs <ng-pluralize count="font.numGlyphsInCommonWithPageContent" when="{'one': 'is', 'other': 'are'}"></ng-pluralize> possibly used.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div ng-if="!font.isIconFont" class="offendersTable">
|
|
<div ng-repeat="range in font.unicodeRanges track by $index">
|
|
<div><b>{{range.name}}</b></div>
|
|
<div ng-if="!range.underused">{{range.numGlyphsInCommonWithPageContent}} of its {{range.charset.length}} glyphs <ng-pluralize count="range.numGlyphsInCommonWithPageContent" when="{'one': 'is', 'other': 'are'}"></ng-pluralize> possibly used</div>
|
|
<div ng-if="range.underused" class="offenderProblem">{{range.numGlyphsInCommonWithPageContent}} of its {{range.charset.length}} glyphs are used</div>
|
|
<div>
|
|
<div class="offenderButton opens">
|
|
glyphes list
|
|
<div>{{range.charset | addSpaces}}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div ng-if="font.ligaturesOrHiddenChars > 0">
|
|
<div><b>Ligatures or hidden chars</b></div>
|
|
<div ng-class="{offenderProblem: (font.ligaturesOrHiddenChars > 25)}">{{font.ligaturesOrHiddenChars}} glyphs</div>
|
|
<div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="policyName === 'http2'">
|
|
<h3>Protocols advertised by the server</h3>
|
|
<div class="offendersTable">
|
|
<div ng-repeat="protocol in rule.offendersObj.list">
|
|
<div>{{protocol}}</div>
|
|
</div>
|
|
<div ng-if="!rule.offendersObj || rule.offendersObj.count == 0">
|
|
<div>none</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-if="!rule && rule !== null" class="notFound">
|
|
<h2>404</h2>
|
|
Rule "{{policyName}}"" not found
|
|
</div>
|
|
|
|
<div class="backToDashboard"><a href="#" ng-click="backToDashboard()">Back to dashboard</a></div>
|
|
</div> |