Skip to content

Commit

Permalink
first pass
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark committed Jun 4, 2021
1 parent 761e47e commit 2b9cec9
Show file tree
Hide file tree
Showing 28 changed files with 463 additions and 258 deletions.
4 changes: 2 additions & 2 deletions build/build-dt-report-resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ function writeFile(name, content) {
fs.rmdirSync(distDir, {recursive: true});
fs.mkdirSync(distDir);

writeFile('report.js', htmlReportAssets.REPORT_JAVASCRIPT);
writeFile('report.js', htmlReportAssets.REPORT_JAVASCRIPT); // TODO remove
writeFile('report.css', htmlReportAssets.REPORT_CSS);
writeFile('template.html', htmlReportAssets.REPORT_TEMPLATE);
writeFile('templates.html', htmlReportAssets.REPORT_TEMPLATES);
writeFile('report.d.ts', 'export {}');
writeFile('report.d.ts', 'export {}'); // TODO remove
writeFile('report-generator.d.ts', 'export {}');

const pathToReportAssets = require.resolve('../clients/devtools-report-assets.js');
Expand Down
54 changes: 53 additions & 1 deletion lighthouse-core/audits/audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,59 @@

const {isUnderTest} = require('../lib/lh-env.js');
const statistics = require('../lib/statistics.js');
const Util = require('../report/html/renderer/util.js');
// const Util = require('../report/html/renderer/util.js');
class Util {
static PASS_THRESHOLD = 0.9;

/**
* Returns only lines that are near a message, or the first few lines if there are
* no line messages.
* @param {LH.Audit.Details.SnippetValue['lines']} lines
* @param {LH.Audit.Details.SnippetValue['lineMessages']} lineMessages
* @param {number} surroundingLineCount Number of lines to include before and after
* the message. If this is e.g. 2 this function might return 5 lines.
*/
static filterRelevantLines(lines, lineMessages, surroundingLineCount) {
if (lineMessages.length === 0) {
// no lines with messages, just return the first bunch of lines
return lines.slice(0, surroundingLineCount * 2 + 1);
}

const minGapSize = 3;
const lineNumbersToKeep = new Set();
// Sort messages so we can check lineNumbersToKeep to see how big the gap to
// the previous line is.
lineMessages = lineMessages.sort((a, b) => (a.lineNumber || 0) - (b.lineNumber || 0));
lineMessages.forEach(({lineNumber}) => {
let firstSurroundingLineNumber = lineNumber - surroundingLineCount;
let lastSurroundingLineNumber = lineNumber + surroundingLineCount;

while (firstSurroundingLineNumber < 1) {
// make sure we still show (surroundingLineCount * 2 + 1) lines in total
firstSurroundingLineNumber++;
lastSurroundingLineNumber++;
}
// If only a few lines would be omitted normally then we prefer to include
// extra lines to avoid the tiny gap
if (lineNumbersToKeep.has(firstSurroundingLineNumber - minGapSize - 1)) {
firstSurroundingLineNumber -= minGapSize;
}
for (let i = firstSurroundingLineNumber; i <= lastSurroundingLineNumber; i++) {
const surroundingLineNumber = i;
lineNumbersToKeep.add(surroundingLineNumber);
}
});

return lines.filter(line => lineNumbersToKeep.has(line.lineNumber));
}

/**
* @param {string} categoryId
*/
static isPluginCategory(categoryId) {
return categoryId.startsWith('lighthouse-plugin-');
}
}

const DEFAULT_PASS = 'defaultPass';

Expand Down
56 changes: 55 additions & 1 deletion lighthouse-core/computed/resource-summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,61 @@ const URL = require('../lib/url-shim.js');
const NetworkRequest = require('../lib/network-request.js');
const MainResource = require('./main-resource.js');
const Budget = require('../config/budget.js');
const Util = require('../report/html/renderer/util.js');
// const Util = require('../report/html/renderer/util.js');

// 25 most used tld plus one domains (aka public suffixes) from http archive.
// @see https://github.com/GoogleChrome/lighthouse/pull/5065#discussion_r191926212
// The canonical list is https://publicsuffix.org/learn/ but we're only using subset to conserve bytes
const listOfTlds = [
'com', 'co', 'gov', 'edu', 'ac', 'org', 'go', 'gob', 'or', 'net', 'in', 'ne', 'nic', 'gouv',
'web', 'spb', 'blog', 'jus', 'kiev', 'mil', 'wi', 'qc', 'ca', 'bel', 'on',
];
class Util {
/**
* @param {string|URL} value
* @return {!URL}
*/
static createOrReturnURL(value) {
if (value instanceof URL) {
return value;
}

return new URL(value);
}

/**
* Returns a primary domain for provided hostname (e.g. www.example.com -> example.com).
* @param {string|URL} url hostname or URL object
* @returns {string}
*/
static getRootDomain(url) {
const hostname = Util.createOrReturnURL(url).hostname;
const tld = Util.getTld(hostname);

// tld is .com or .co.uk which means we means that length is 1 to big
// .com => 2 & .co.uk => 3
const splitTld = tld.split('.');

// get TLD + root domain
return hostname.split('.').slice(-splitTld.length).join('.');
}

/**
* Gets the tld of a domain
*
* @param {string} hostname
* @return {string} tld
*/
static getTld(hostname) {
const tlds = hostname.split('.').slice(-2);

if (!listOfTlds.includes(tlds[0])) {
return `.${tlds[tlds.length - 1]}`;
}

return `.${tlds.join('.')}`;
}
}

/** @typedef {{count: number, resourceSize: number, transferSize: number}} ResourceEntry */

Expand Down
5 changes: 1 addition & 4 deletions lighthouse-core/lib/file-namer.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,4 @@ function getFilenamePrefix(lhr) {
return filenamePrefix.replace(/[/?<>\\:*|"]/g, '-');
}

// don't attempt to export in the browser.
if (typeof module !== 'undefined' && module.exports) {
module.exports = {getFilenamePrefix};
}
module.exports = {getFilenamePrefix};
126 changes: 125 additions & 1 deletion lighthouse-core/lib/url-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,131 @@
* URL shim so we keep our code DRY
*/

const Util = require('../report/html/renderer/util.js');
// const Util = require('../report/html/renderer/util.js');
const ELLIPSIS = '\u2026';
// 25 most used tld plus one domains (aka public suffixes) from http archive.
// @see https://github.com/GoogleChrome/lighthouse/pull/5065#discussion_r191926212
// The canonical list is https://publicsuffix.org/learn/ but we're only using subset to conserve bytes
const listOfTlds = [
'com', 'co', 'gov', 'edu', 'ac', 'org', 'go', 'gob', 'or', 'net', 'in', 'ne', 'nic', 'gouv',
'web', 'spb', 'blog', 'jus', 'kiev', 'mil', 'wi', 'qc', 'ca', 'bel', 'on',
];
class Util {
/**
* @param {string|URL} value
* @return {!URL}
*/
static createOrReturnURL(value) {
if (value instanceof URL) {
return value;
}

return new URL(value);
}

/**
* @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;
}

/**
* Returns a primary domain for provided hostname (e.g. www.example.com -> example.com).
* @param {string|URL} url hostname or URL object
* @returns {string}
*/
static getRootDomain(url) {
const hostname = Util.createOrReturnURL(url).hostname;
const tld = Util.getTld(hostname);

// tld is .com or .co.uk which means we means that length is 1 to big
// .com => 2 & .co.uk => 3
const splitTld = tld.split('.');

// get TLD + root domain
return hostname.split('.').slice(-splitTld.length).join('.');
}

/**
* Gets the tld of a domain
*
* @param {string} hostname
* @return {string} tld
*/
static getTld(hostname) {
const tlds = hostname.split('.').slice(-2);

if (!listOfTlds.includes(tlds[0])) {
return `.${tlds[tlds.length - 1]}`;
}

return `.${tlds.join('.')}`;
}
}

/** @typedef {import('./network-request.js')} NetworkRequest */

Expand Down
55 changes: 40 additions & 15 deletions lighthouse-core/report/html/html-report-assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,46 @@ const fs = require('fs');

const REPORT_TEMPLATE = fs.readFileSync(__dirname + '/report-template.html', 'utf8');
const REPORT_JAVASCRIPT = [
fs.readFileSync(__dirname + '/renderer/util.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/dom.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/details-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/crc-details-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/snippet-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/element-screenshot-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/../../lib/file-namer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/logger.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/report-ui-features.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/category-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/performance-category-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/pwa-category-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/report-renderer.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/i18n.js', 'utf8'),
fs.readFileSync(__dirname + '/renderer/text-encoding.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/util.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/dom.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/details-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/crc-details-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/snippet-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/element-screenshot-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/file-namer.js', 'utf8'),
// fs.readFileSync(__dirname + '/../../lib/file-namer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/logger.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/report-ui-features.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/category-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/performance-category-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/pwa-category-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/report-renderer.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/i18n.js', 'utf8'),
// fs.readFileSync(__dirname + '/renderer/text-encoding.js', 'utf8'),
].join(';\n');

/* eslint-disable max-len */
const REPORT_JAVASCRIPT_MODULES = {
'./logger.js': fs.readFileSync(__dirname + '/renderer/logger.js', 'utf8'),
'./i18n.js': fs.readFileSync(__dirname + '/renderer/i18n.js', 'utf8'),
'./text-encoding.js': fs.readFileSync(__dirname + '/renderer/text-encoding.js', 'utf8'),
'./util.js': fs.readFileSync(__dirname + '/renderer/util.js', 'utf8'),
'./dom.js': fs.readFileSync(__dirname + '/renderer/dom.js', 'utf8'),
'./crc-details-renderer.js': fs.readFileSync(__dirname + '/renderer/crc-details-renderer.js', 'utf8'),
'./snippet-renderer.js': fs.readFileSync(__dirname + '/renderer/snippet-renderer.js', 'utf8'),
'./element-screenshot-renderer.js': fs.readFileSync(__dirname + '/renderer/element-screenshot-renderer.js', 'utf8'),
'./category-renderer.js': fs.readFileSync(__dirname + '/renderer/category-renderer.js', 'utf8'),
'./performance-category-renderer.js': fs.readFileSync(__dirname + '/renderer/performance-category-renderer.js', 'utf8'),
'./pwa-category-renderer.js': fs.readFileSync(__dirname + '/renderer/pwa-category-renderer.js', 'utf8'),
'./details-renderer.js': fs.readFileSync(__dirname + '/renderer/details-renderer.js', 'utf8'),
'../../../lib/file-namer.js': fs.readFileSync(__dirname + '/../../lib/file-namer.js', 'utf8'),
'./file-namer.js': fs.readFileSync(__dirname + '/renderer/file-namer.js', 'utf8'),
'./report-ui-features.js': fs.readFileSync(__dirname + '/renderer/report-ui-features.js', 'utf8'),
'./report-renderer.js': fs.readFileSync(__dirname + '/renderer/report-renderer.js', 'utf8'),
'./main.js': fs.readFileSync(__dirname + '/renderer/main.js', 'utf8'),
};
/* eslint-enable max-len */

const REPORT_CSS = fs.readFileSync(__dirname + '/report-styles.css', 'utf8');
const REPORT_TEMPLATES = fs.readFileSync(__dirname + '/templates.html', 'utf8');

Expand All @@ -34,5 +58,6 @@ module.exports = {
REPORT_TEMPLATE,
REPORT_TEMPLATES,
REPORT_JAVASCRIPT,
REPORT_JAVASCRIPT_MODULES,
REPORT_CSS,
};
19 changes: 6 additions & 13 deletions lighthouse-core/report/html/renderer/category-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@
*/
'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 */
/** @typedef {import('./dom.js').DOM} DOM */
/** @typedef {import('./report-renderer.js').ReportRenderer} ReportRenderer */
/** @typedef {import('./details-renderer.js').DetailsRenderer} DetailsRenderer */
/** @typedef {'failed'|'warning'|'manual'|'passed'|'notApplicable'} TopLevelClumpId */

class CategoryRenderer {
import {Util} from './util.js';

export class CategoryRenderer {
/**
* @param {DOM} dom
* @param {DetailsRenderer} detailsRenderer
Expand Down Expand Up @@ -502,9 +501,3 @@ class CategoryRenderer {
permalinkEl.id = id;
}
}

if (typeof module !== 'undefined' && module.exports) {
module.exports = CategoryRenderer;
} else {
self.CategoryRenderer = CategoryRenderer;
}
Loading

0 comments on commit 2b9cec9

Please sign in to comment.