diff --git a/src/third_party/LIGHTHOUSE_MCP_BUNDLE_THIRD_PARTY_NOTICES b/src/third_party/LIGHTHOUSE_MCP_BUNDLE_THIRD_PARTY_NOTICES index c99dde397..67318f8c4 100644 --- a/src/third_party/LIGHTHOUSE_MCP_BUNDLE_THIRD_PARTY_NOTICES +++ b/src/third_party/LIGHTHOUSE_MCP_BUNDLE_THIRD_PARTY_NOTICES @@ -1023,11 +1023,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - --------------------- DEPENDENCY DIVIDER -------------------- - -Name: lighthouse-plugin-soft-navigation -URL: N/A -Version: 1.1.0 -License: ISC \ No newline at end of file diff --git a/src/third_party/lighthouse-devtools-mcp-bundle.js b/src/third_party/lighthouse-devtools-mcp-bundle.js index ea30c6836..c4523eea9 100644 --- a/src/third_party/lighthouse-devtools-mcp-bundle.js +++ b/src/third_party/lighthouse-devtools-mcp-bundle.js @@ -1,5 +1,5 @@ /** - * Lighthouse v13.0.3-4-ga9dfea556 (Feb 23 2026) + * Lighthouse v13.0.3-3-g565cfd0f2 (Mar 02 2026) * * Automated auditing, performance metrics, and best practices for the web. * @@ -3613,80 +3613,6 @@ var init_audit = __esm({ } }); -// core/scoring.js -var clampTo2Decimals2, ReportScoring; -var init_scoring = __esm({ - "core/scoring.js"() { - "use strict"; - init_process_global(); - init_audit(); - /** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - clampTo2Decimals2 = /* @__PURE__ */ __name((val) => Math.round(val * 100) / 100, "clampTo2Decimals"); - ReportScoring = class _ReportScoring { - static { - __name(this, "ReportScoring"); - } - /** - * Computes the weighted-average of the score of the list of items. - * @param {Array<{score: number|null, weight: number}>} items - * @return {number|null} - */ - static arithmeticMean(items) { - items = items.filter((item) => item.weight > 0); - if (items.some((item) => item.score === null)) return null; - const results = items.reduce( - (result, item) => { - const score = item.score; - const weight = item.weight; - return { - weight: result.weight + weight, - sum: result.sum + /** @type {number} */ - score * weight - }; - }, - { weight: 0, sum: 0 } - ); - return clampTo2Decimals2(results.sum / results.weight || 0); - } - /** - * Returns the report JSON object with computed scores. - * @param {Object} configCategories - * @param {Object>} resultsByAuditId - * @return {Object>} - */ - static scoreAllCategories(configCategories, resultsByAuditId) { - const scoredCategories = {}; - for (const [categoryId, configCategory] of Object.entries(configCategories)) { - const auditRefs = configCategory.auditRefs.map((configMember) => { - const member = { ...configMember }; - const result = resultsByAuditId[member.id]; - if (result.scoreDisplayMode === Audit.SCORING_MODES.NOT_APPLICABLE || result.scoreDisplayMode === Audit.SCORING_MODES.INFORMATIVE || result.scoreDisplayMode === Audit.SCORING_MODES.MANUAL) { - member.weight = 0; - } - return member; - }); - const scores = auditRefs.map((auditRef) => ({ - score: resultsByAuditId[auditRef.id].score, - weight: auditRef.weight - })); - const score = _ReportScoring.arithmeticMean(scores); - scoredCategories[categoryId] = { - ...configCategory, - auditRefs, - id: categoryId, - score - }; - } - return scoredCategories; - } - }; - } -}); - // node_modules/intl-messageformat/node_modules/tslib/tslib.es6.mjs var tslib_es6_exports = {}; __export(tslib_es6_exports, { @@ -10084,126 +10010,6 @@ var init_i18n = __esm({ } }); -// core/lib/stack-packs.js -function getStackPacks(pageStacks) { - if (!pageStacks) return []; - const packs = []; - for (const pageStack of pageStacks) { - const stackPackToIncl = stackPacksToInclude.find((stackPackToIncl2) => stackPackToIncl2.requiredStacks.includes(`${pageStack.detector}:${pageStack.id}`)); - if (!stackPackToIncl) { - continue; - } - const matchedPack = import_lighthouse_stack_packs.default.find((pack) => pack.id === stackPackToIncl.packId); - if (!matchedPack) { - lighthouse_logger_default.warn( - "StackPacks", - `'${stackPackToIncl.packId}' stack pack was matched but is not found in stack-packs lib` - ); - continue; - } - const str_105 = createIcuMessageFn( - `node_modules/lighthouse-stack-packs/packs/${matchedPack.id}.js`, - matchedPack.UIStrings - ); - const descriptions = {}; - const UIStrings125 = matchedPack.UIStrings; - for (const key in UIStrings125) { - if (UIStrings125[key]) { - descriptions[key] = str_105(UIStrings125[key]); - } - } - packs.push({ - id: matchedPack.id, - title: matchedPack.title, - iconDataURL: matchedPack.icon, - descriptions - }); - } - return packs.sort((a, b) => { - const aVal = stackPacksToInclude.findIndex((p) => p.packId === a.id); - const bVal = stackPacksToInclude.findIndex((p) => p.packId === b.id); - return aVal - bVal; - }); -} -var import_lighthouse_stack_packs, stackPacksToInclude; -var init_stack_packs = __esm({ - "core/lib/stack-packs.js"() { - "use strict"; - init_process_global(); - init_lighthouse_logger(); - import_lighthouse_stack_packs = __toESM(require_lighthouse_stack_packs(), 1); - init_i18n(); - /** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - stackPacksToInclude = [ - { - packId: "gatsby", - requiredStacks: ["js:gatsby"] - }, - { - packId: "wordpress", - requiredStacks: ["js:wordpress"] - }, - { - packId: "wix", - requiredStacks: ["js:wix"] - }, - { - packId: "wp-rocket", - requiredStacks: ["js:wp-rocket"] - }, - { - packId: "ezoic", - requiredStacks: ["js:ezoic"] - }, - { - packId: "drupal", - requiredStacks: ["js:drupal"] - }, - { - packId: "nitropack", - requiredStacks: ["js:nitropack"] - }, - { - packId: "amp", - requiredStacks: ["js:amp"] - }, - { - packId: "magento", - requiredStacks: ["js:magento"] - }, - { - packId: "octobercms", - requiredStacks: ["js:octobercms"] - }, - { - packId: "joomla", - requiredStacks: ["js:joomla"] - }, - { - packId: "next.js", - requiredStacks: ["js:next"] - }, - { - packId: "nuxt", - requiredStacks: ["js:nuxt"] - }, - { - packId: "angular", - requiredStacks: ["js:angular"] - }, - { - packId: "react", - requiredStacks: ["js:react"] - } - ]; - __name(getStackPacks, "getStackPacks"); - } -}); - // node_modules/@paulirish/trace_engine/models/trace/lantern/core/LanternError.js var LanternError; var init_LanternError = __esm({ @@ -30133,19 +29939,6 @@ var init_lantern2 = __esm({ } }); -// core/lib/lantern-trace-saver.js -var init_lantern_trace_saver = __esm({ - "core/lib/lantern-trace-saver.js"() { - "use strict"; - init_process_global(); - /** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - } -}); - // core/lib/tracehouse/trace-processor.js var ACCEPTABLE_NAVIGATION_URL_REGEX, BASE_RESPONSE_LATENCY, SCHEDULABLE_TASK_TITLE_LH2, SCHEDULABLE_TASK_TITLE_ALT12, SCHEDULABLE_TASK_TITLE_ALT22, SCHEDULABLE_TASK_TITLE_ALT32, TraceProcessor2; var init_trace_processor = __esm({ @@ -30889,21 +30682,6 @@ var init_trace_processor = __esm({ } }); -// core/lib/traces/metric-trace-events.js -var init_metric_trace_events = __esm({ - "core/lib/traces/metric-trace-events.js"() { - "use strict"; - init_process_global(); - init_lighthouse_logger(); - init_trace_processor(); - /** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - } -}); - // core/lib/arbitrary-equality-map.js var ArbitraryEqualityMap; var init_arbitrary_equality_map = __esm({ @@ -33085,1617 +32863,16 @@ var init_network_records = __esm({ } }); -// core/computed/network-analysis.js -var NetworkAnalysis, NetworkAnalysisComputed; -var init_network_analysis = __esm({ - "core/computed/network-analysis.js"() { - "use strict"; - init_process_global(); - init_lighthouse_logger(); - init_lantern2(); - init_computed_artifact(); - init_network_records(); - /** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - NetworkAnalysis = class { - static { - __name(this, "NetworkAnalysis"); - } - /** - * @param {LH.DevtoolsLog} devtoolsLog - * @param {LH.Artifacts.ComputedContext} context - * @return {Promise} - */ - static async compute_(devtoolsLog, context) { - const records = await NetworkRecordsComputed.request(devtoolsLog, context); - const analysis = core_exports.NetworkAnalyzer.analyze(records); - if (!analysis) { - lighthouse_logger_default.error("NetworkAnalysis", "Network analysis failed due to lack of transfer data"); - return { - throughput: 0, - rtt: Number.POSITIVE_INFINITY, - additionalRttByOrigin: /* @__PURE__ */ new Map(), - serverResponseTimeByOrigin: /* @__PURE__ */ new Map() - }; - } - return analysis; - } - }; - NetworkAnalysisComputed = makeComputedArtifact(NetworkAnalysis, null); - } -}); - -// core/computed/load-simulator.js -var LoadSimulator, LoadSimulatorComputed; -var init_load_simulator = __esm({ - "core/computed/load-simulator.js"() { - "use strict"; - init_process_global(); - init_computed_artifact(); - init_lantern2(); - init_network_analysis(); - /** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - LoadSimulator = class { - static { - __name(this, "LoadSimulator"); - } - /** - * @param {{devtoolsLog: LH.DevtoolsLog, settings: LH.Audit.Context['settings']}} data - * @param {LH.Artifacts.ComputedContext} context - * @return {Promise} - */ - static async compute_(data31, context) { - const networkAnalysis = await NetworkAnalysisComputed.request(data31.devtoolsLog, context); - return simulation_exports.Simulator.createSimulator({ ...data31.settings, networkAnalysis }); - } - /** - * @param {LH.Artifacts.NetworkAnalysis} networkAnalysis - * @return {LH.PrecomputedLanternData} - */ - static convertAnalysisToSaveableLanternData(networkAnalysis) { - const lanternData = { additionalRttByOrigin: {}, serverResponseTimeByOrigin: {} }; - for (const [origin, value] of networkAnalysis.additionalRttByOrigin.entries()) { - if (origin.startsWith("http")) lanternData.additionalRttByOrigin[origin] = value; - } - for (const [origin, value] of networkAnalysis.serverResponseTimeByOrigin.entries()) { - if (origin.startsWith("http")) lanternData.serverResponseTimeByOrigin[origin] = value; - } - return lanternData; - } - }; - LoadSimulatorComputed = makeComputedArtifact(LoadSimulator, ["devtoolsLog", "settings"]); - } -}); - -// core/lib/asset-saver.js -import fs from "fs"; -import path3 from "path"; -import stream from "stream"; -import { createGzip, gunzipSync } from "zlib"; -async function writeJson(contents, path7, gzip) { - const writeStream = fs.createWriteStream(gzip ? path7 + ".gz" : path7); - if (gzip) { - await stream.promises.pipeline(contents, createGzip(), writeStream); - } else { - await stream.promises.pipeline(contents, writeStream); - } -} -function readJson(filename, reviver) { - if (fs.existsSync(filename + ".gz")) { - filename = filename + ".gz"; - } - if (!filename.endsWith(".json.gz")) { - return JSON.parse(fs.readFileSync(filename, "utf8"), reviver); - } - const buffer = gunzipSync(fs.readFileSync(filename)); - return JSON.parse(buffer.toString("utf8"), reviver); -} -function endsWithSuffix(filename, suffix) { - return filename.endsWith(suffix) || filename.endsWith(suffix + ".gz"); -} -function loadArtifacts(basePath) { - lighthouse_logger_default.log("Reading artifacts from disk:", basePath); - if (!fs.existsSync(basePath)) { - throw new Error("No saved artifacts found at " + basePath); - } - const artifacts = readJson(path3.join(basePath, artifactsFilename), LighthouseError.parseReviver); - const filenames = fs.readdirSync(basePath); - filenames.filter((f) => endsWithSuffix(f, devtoolsFilename)).forEach((filename) => { - const devtoolsLog = readJson(path3.join(basePath, filename)); - if (filename.startsWith(devtoolsFilename)) { - artifacts.DevtoolsLog = devtoolsLog; - } else if (filename.startsWith(errorPrefix)) { - artifacts.DevtoolsLogError = devtoolsLog; - } - }); - filenames.filter((f) => endsWithSuffix(f, traceFilename)).forEach((filename) => { - let trace = readJson(path3.join(basePath, filename)); - if (Array.isArray(trace)) { - trace = { traceEvents: trace }; - } - if (filename.startsWith(traceFilename)) { - artifacts.Trace = trace; - } else if (filename.startsWith(errorPrefix)) { - artifacts.TraceError = trace; - } - }); - if (Array.isArray(artifacts.Timing)) { - artifacts.Timing.forEach((entry) => entry.gather = true); - } - return artifacts; -} -function stringifyReplacer(key, value) { - if (value instanceof Error) { - return LighthouseError.stringifyReplacer(value); - } - return value; -} -async function saveArtifacts(artifacts, basePath, options = {}) { - const status = { msg: "Saving artifacts", id: "lh:assetSaver:saveArtifacts" }; - lighthouse_logger_default.time(status); - fs.mkdirSync(basePath, { recursive: true }); - const filenames = fs.readdirSync(basePath); - for (const filename of filenames) { - const isPreviousFile = filename.endsWith(traceFilename) || filename.endsWith(devtoolsFilename) || filename.endsWith(traceFilename + ".gz") || filename.endsWith(devtoolsFilename + ".gz") || filename === artifactsFilename || filename === artifactsFilename + ".gz"; - if (isPreviousFile) { - fs.unlinkSync(`${basePath}/${filename}`); - } - } - const { - DevtoolsLog: DevtoolsLog2, - Trace, - DevtoolsLogError, - TraceError, - ...restArtifacts - } = artifacts; - if (Trace) { - await saveTrace(Trace, `${basePath}/${traceFilename}`, options); - } - if (TraceError) { - await saveTrace(TraceError, `${basePath}/${errorPrefix}${traceFilename}`, options); - } - if (DevtoolsLog2) { - await saveDevtoolsLog( - DevtoolsLog2, - `${basePath}/${devtoolsFilename}`, - options - ); - } - if (DevtoolsLogError) { - await saveDevtoolsLog( - DevtoolsLogError, - `${basePath}/${errorPrefix}${devtoolsFilename}`, - options - ); - } - const restArtifactsString = JSON.stringify(restArtifacts, stringifyReplacer, 2); - await writeJson(function* () { - yield restArtifactsString; - yield "\n"; - }, `${basePath}/${artifactsFilename}`, !!options.gzip); - lighthouse_logger_default.log("Artifacts saved to disk in folder:", basePath); - lighthouse_logger_default.timeEnd(status); -} -function saveLhr(lhr, basePath) { - fs.writeFileSync(`${basePath}/lhr.report.json`, JSON.stringify(lhr, null, 2)); -} -function* arrayOfObjectsJsonGenerator(arrayOfObjects) { - const ITEMS_PER_ITERATION = 500; - yield "[\n"; - if (arrayOfObjects.length > 0) { - const itemsIterator = arrayOfObjects[Symbol.iterator](); - const firstItem = itemsIterator.next().value; - yield ` ${JSON.stringify(firstItem)}`; - let itemsRemaining = ITEMS_PER_ITERATION; - let itemsJSON = ""; - for (const item of itemsIterator) { - itemsJSON += `, - ${JSON.stringify(item)}`; - itemsRemaining--; - if (itemsRemaining === 0) { - yield itemsJSON; - itemsRemaining = ITEMS_PER_ITERATION; - itemsJSON = ""; - } - } - yield itemsJSON; - } - yield "\n]"; -} -function* traceJsonGenerator(traceData) { - const { traceEvents, ...rest } = traceData; - yield "{\n"; - yield '"traceEvents": '; - yield* arrayOfObjectsJsonGenerator(traceEvents); - for (const [key, value] of Object.entries(rest)) { - yield `, -"${key}": ${JSON.stringify(value, null, 2)}`; - } - yield "}\n"; -} -function saveTrace(traceData, traceFilename2, options = {}) { - const traceIter = traceJsonGenerator(traceData); - return writeJson(traceIter, traceFilename2, !!options.gzip); -} -function saveDevtoolsLog(devtoolsLog, devtoolLogFilename, options = {}) { - return writeJson(function* () { - yield* arrayOfObjectsJsonGenerator(devtoolsLog); - yield "\n"; - }, devtoolLogFilename, !!options.gzip); -} -var artifactsFilename, traceFilename, devtoolsFilename, errorPrefix; -var init_asset_saver = __esm({ - "core/lib/asset-saver.js"() { - "use strict"; - init_process_global(); - init_url(); - init_lighthouse_logger(); - init_lantern2(); - init_lantern_trace_saver(); - init_metric_trace_events(); - init_network_analysis(); - init_load_simulator(); - init_lh_error(); - init_root2(); - /** - * @license - * Copyright 2016 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - artifactsFilename = "artifacts.json"; - traceFilename = "trace.json"; - devtoolsFilename = "devtoolslog.json"; - errorPrefix = "pageLoadError."; - __name(writeJson, "writeJson"); - __name(readJson, "readJson"); - __name(endsWithSuffix, "endsWithSuffix"); - __name(loadArtifacts, "loadArtifacts"); - __name(stringifyReplacer, "stringifyReplacer"); - __name(saveArtifacts, "saveArtifacts"); - __name(saveLhr, "saveLhr"); - __name(arrayOfObjectsJsonGenerator, "arrayOfObjectsJsonGenerator"); - __name(traceJsonGenerator, "traceJsonGenerator"); - __name(saveTrace, "saveTrace"); - __name(saveDevtoolsLog, "saveDevtoolsLog"); - } -}); - -// core/config/constants.js -var constants_exports = {}; -__export(constants_exports, { - defaultSettings: () => defaultSettings, - nonSimulatedSettingsOverrides: () => nonSimulatedSettingsOverrides, - screenEmulationMetrics: () => screenEmulationMetrics, - throttling: () => throttling2, - userAgents: () => userAgents -}); -var throttling2, MOTOGPOWER_EMULATION_METRICS, DESKTOP_EMULATION_METRICS, screenEmulationMetrics, MOTOG4_USERAGENT, DESKTOP_USERAGENT, userAgents, defaultSettings, nonSimulatedSettingsOverrides; -var init_constants = __esm({ - "core/config/constants.js"() { - "use strict"; - init_process_global(); - init_lantern2(); - /** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - throttling2 = simulation_exports.Constants.throttling; - MOTOGPOWER_EMULATION_METRICS = { - mobile: true, - width: 412, - height: 823, - // This value has some interesting ramifications for image-size-responsive, see: - // https://github.com/GoogleChrome/lighthouse/issues/10741#issuecomment-626903508 - deviceScaleFactor: 1.75, - disabled: false - }; - DESKTOP_EMULATION_METRICS = { - mobile: false, - width: 1350, - height: 940, - deviceScaleFactor: 1, - disabled: false - }; - screenEmulationMetrics = { - mobile: MOTOGPOWER_EMULATION_METRICS, - desktop: DESKTOP_EMULATION_METRICS - }; - MOTOG4_USERAGENT = "Mozilla/5.0 (Linux; Android 11; moto g power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Mobile Safari/537.36"; - DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"; - userAgents = { - mobile: MOTOG4_USERAGENT, - desktop: DESKTOP_USERAGENT - }; - defaultSettings = { - output: "json", - maxWaitForFcp: 30 * 1e3, - maxWaitForLoad: 45 * 1e3, - pauseAfterFcpMs: 1e3, - pauseAfterLoadMs: 1e3, - networkQuietThresholdMs: 1e3, - cpuQuietThresholdMs: 1e3, - formFactor: "mobile", - throttling: throttling2.mobileSlow4G, - throttlingMethod: "simulate", - screenEmulation: screenEmulationMetrics.mobile, - emulatedUserAgent: userAgents.mobile, - auditMode: false, - gatherMode: false, - clearStorageTypes: ["file_systems", "shader_cache", "service_workers", "cache_storage"], - disableStorageReset: false, - debugNavigation: false, - channel: "node", - usePassiveGathering: false, - disableFullPageScreenshot: false, - skipAboutBlank: false, - blankPage: "about:blank", - ignoreStatusCode: false, - // the following settings have no defaults but we still want ensure that `key in settings` - // in config will work in a typechecked way - locale: "en-US", - // actual default determined by Config using lib/i18n - blockedUrlPatterns: null, - additionalTraceCategories: null, - extraHeaders: null, - precomputedLanternData: null, - onlyAudits: null, - onlyCategories: null, - skipAudits: null - }; - nonSimulatedSettingsOverrides = { - pauseAfterFcpMs: 5250, - pauseAfterLoadMs: 5250, - networkQuietThresholdMs: 5250, - cpuQuietThresholdMs: 5250 - }; - } -}); - -// core/config/default-config.js -var UIStrings21, str_2, defaultConfig, default_config_default; -var init_default_config = __esm({ - "core/config/default-config.js"() { +// core/lib/axe.js +var require2, axeSource; +var init_axe = __esm({ + "core/lib/axe.js"() { "use strict"; init_process_global(); - init_lh(); - init_constants(); - init_i18n(); + init_module(); /** * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - UIStrings21 = { - /** Title of the Performance category of audits. Equivalent to 'Web performance', this term is inclusive of all web page speed and loading optimization topics. Also used as a label of a score gauge; try to limit to 20 characters. */ - performanceCategoryTitle: "Performance", - /** Title of the speed metrics section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. */ - metricGroupTitle: "Metrics", - /** Title of the insights section of the Performance category. Within this section are various insights to give developers tips on how to improve the performance of their page. */ - insightsGroupTitle: "Insights", - /** Description of the insights section of the Performance category. Within this section are various insights to give developers tips on how to improve the performance of their page. */ - insightsGroupDescription: "These insights are also available in the Chrome DevTools Performance Panel - [record a trace](https://developer.chrome.com/docs/devtools/performance/reference) to view more detailed information.", - /** Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage. */ - firstPaintImprovementsGroupTitle: "First Paint Improvements", - /** Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage. */ - firstPaintImprovementsGroupDescription: "The most critical aspect of performance is how quickly pixels are rendered onscreen. Key metrics: First Contentful Paint, First Meaningful Paint", - /** Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the overall loading performance of their web page. */ - overallImprovementsGroupTitle: "Overall Improvements", - /** Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the overall loading performance of their web page. */ - overallImprovementsGroupDescription: "Enhance the overall loading experience, so the page is responsive and ready to use as soon as possible. Key metrics: Time to Interactive, Speed Index", - /** Title of the diagnostics section of the Performance category. Within this section are audits with non-imperative titles that provide more detail on the page's page load performance characteristics. Whereas the 'Opportunities' suggest an action along with expected time savings, diagnostics do not. Within this section, the user may read the details and deduce additional actions they could take. */ - diagnosticsGroupTitle: "Diagnostics", - /** Description of the diagnostics section of the Performance category. Within this section are audits with non-imperative titles that provide more detail on a web page's load performance characteristics. Within this section, the user may read the details and deduce additional actions they could take to improve performance. */ - diagnosticsGroupDescription: "More information about the performance of your application. These numbers don't [directly affect](https://developer.chrome.com/docs/lighthouse/performance/performance-scoring/) the Performance score.", - /** Title of the Accessibility category of audits. This section contains audits focused on making web content accessible to all users. Also used as a label of a score gauge; try to limit to 20 characters. */ - a11yCategoryTitle: "Accessibility", - /** Description of the Accessibility category. This is displayed at the top of a list of audits focused on making web content accessible to all users. No character length limits. 'improve the accessibility of your web app' and 'manual testing' become link texts to additional documentation. */ - a11yCategoryDescription: "These checks highlight opportunities to [improve the accessibility of your web app](https://developer.chrome.com/docs/lighthouse/accessibility/). Automatic detection can only detect a subset of issues and does not guarantee the accessibility of your web app, so [manual testing](https://web.dev/articles/how-to-review) is also encouraged.", - /** Description of the Accessibility manual checks category. This description is displayed above a list of accessibility audits that currently have no automated test and so must be verified manually by the user. No character length limits. 'conducting an accessibility review' becomes link text to additional documentation. */ - a11yCategoryManualDescription: "These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://web.dev/articles/how-to-review).", - /** Title of the best practices section of the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices. */ - a11yBestPracticesGroupTitle: "Best practices", - /** Description of the best practices section within the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices. */ - a11yBestPracticesGroupDescription: "These items highlight common accessibility best practices.", - /** Title of the color contrast section within the Accessibility category. Within this section are audits with descriptive titles that highlight the color and vision aspects of the page's accessibility that are passing or failing. */ - a11yColorContrastGroupTitle: "Contrast", - /** Description of the color contrast section within the Accessibility category. Within this section are audits with descriptive titles that highlight the color and vision aspects of the page's accessibility that are passing or failing. */ - a11yColorContrastGroupDescription: "These are opportunities to improve the legibility of your content.", - /** Title of the HTML element naming section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the non-textual HTML elements on the page have names discernible by a screen reader. */ - a11yNamesLabelsGroupTitle: "Names and labels", - /** Description of the HTML element naming section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the non-textual HTML elements on the page have names discernible by a screen reader. */ - a11yNamesLabelsGroupDescription: "These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader.", - /** Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve keyboard navigation. */ - a11yNavigationGroupTitle: "Navigation", - /** Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve keyboard navigation. */ - a11yNavigationGroupDescription: "These are opportunities to improve keyboard navigation in your application.", - /** Title of the ARIA validity section within the Accessibility category. Within this section are audits with descriptive titles that highlight if whether all the aria-* HTML attributes have been used properly. */ - a11yAriaGroupTitle: "ARIA", - /** Description of the ARIA validity section within the Accessibility category. Within this section are audits with descriptive titles that highlight if whether all the aria-* HTML attributes have been used properly. */ - a11yAriaGroupDescription: "These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader.", - /** Title of the language section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the language has been annotated in the correct HTML attributes on the page. */ - a11yLanguageGroupTitle: "Internationalization and localization", - /** Description of the language section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the language has been annotated in the correct HTML attributes on the page. */ - a11yLanguageGroupDescription: "These are opportunities to improve the interpretation of your content by users in different locales.", - /** Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to provide alternative content for audio and video. */ - a11yAudioVideoGroupTitle: "Audio and video", - /** Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to provide alternative content for audio and video. */ - a11yAudioVideoGroupDescription: "These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments.", - /** Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve the experience of reading tabular or list data using assistive technology. */ - a11yTablesListsVideoGroupTitle: "Tables and lists", - /** Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve the experience of reading tabular or list data using assistive technology. */ - a11yTablesListsVideoGroupDescription: "These are opportunities to improve the experience of reading tabular or list data using assistive technology, like a screen reader.", - /** Title of the Search Engine Optimization (SEO) category of audits. This is displayed at the top of a list of audits focused on topics related to optimizing a website for indexing by search engines. Also used as a label of a score gauge; try to limit to 20 characters. */ - seoCategoryTitle: "SEO", - /** Description of the Search Engine Optimization (SEO) category. This is displayed at the top of a list of audits focused on optimizing a website for indexing by search engines. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */ - seoCategoryDescription: "These checks ensure that your page is following basic search engine optimization advice. There are many additional factors Lighthouse does not score here that may affect your search ranking, including performance on [Core Web Vitals](https://web.dev/explore/vitals). [Learn more about Google Search Essentials](https://support.google.com/webmasters/answer/35769).", - /** Description of the Search Engine Optimization (SEO) manual checks category, the additional validators must be run by hand in order to check all SEO best practices. This is displayed at the top of a list of manually run audits focused on optimizing a website for indexing by search engines. No character length limits. */ - seoCategoryManualDescription: "Run these additional validators on your site to check additional SEO best practices.", - /** Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight opportunities to make a page more usable on mobile devices. */ - seoMobileGroupTitle: "Mobile Friendly", - /** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight opportunities to make a page more usable on mobile devices. */ - seoMobileGroupDescription: "Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn how to make pages mobile-friendly](https://developers.google.com/search/mobile-sites/).", - /** Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website content more easily understood by search engine crawler bots. */ - seoContentGroupTitle: "Content Best Practices", - /** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website content more easily understood by search engine crawler bots. */ - seoContentGroupDescription: "Format your HTML in a way that enables crawlers to better understand your app’s content.", - /** Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers. */ - seoCrawlingGroupTitle: "Crawling and Indexing", - /** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers. */ - seoCrawlingGroupDescription: "To appear in search results, crawlers need access to your app.", - /** Title of the Best Practices category of audits. This is displayed at the top of a list of audits focused on topics related to following web development best practices and accepted guidelines. Also used as a label of a score gauge; try to limit to 20 characters. */ - bestPracticesCategoryTitle: "Best Practices", - /** Title of the Trust & Safety group of audits. This is displayed at the top of a list of audits focused on maintaining user trust and protecting security in web development. */ - bestPracticesTrustSafetyGroupTitle: "Trust and Safety", - /** Title of the User Experience group of the Best Practices category. Within this section are the audits related to the end user's experience of the webpage. */ - bestPracticesUXGroupTitle: "User Experience", - /** Title of the Browser Compatibility group of the Best Practices category. Within this section are the audits related to whether the page is interpreted consistently by browsers. */ - bestPracticesBrowserCompatGroupTitle: "Browser Compatibility", - /** Title of the General group of the Best Practices category. Within this section are the audits that don't belong to a specific group but are of general interest. */ - bestPracticesGeneralGroupTitle: "General" - }; - str_2 = createIcuMessageFn({ url: "core/config/default-config.js" }.url, UIStrings21); - defaultConfig = { - settings: defaultSettings, - artifacts: [ - // Artifacts which can be depended on come first. - { id: "DevtoolsLog", gatherer: "devtools-log" }, - { id: "Trace", gatherer: "trace" }, - { id: "Accessibility", gatherer: "accessibility" }, - { id: "AnchorElements", gatherer: "anchor-elements" }, - { id: "ConsoleMessages", gatherer: "console-messages" }, - { id: "CSSUsage", gatherer: "css-usage" }, - { id: "Doctype", gatherer: "dobetterweb/doctype" }, - { id: "Inputs", gatherer: "inputs" }, - { id: "IFrameElements", gatherer: "iframe-elements" }, - { id: "ImageElements", gatherer: "image-elements" }, - { id: "InspectorIssues", gatherer: "inspector-issues" }, - { id: "JsUsage", gatherer: "js-usage" }, - { id: "LinkElements", gatherer: "link-elements" }, - { id: "MainDocumentContent", gatherer: "main-document-content" }, - { id: "MetaElements", gatherer: "meta-elements" }, - { id: "NetworkUserAgent", gatherer: "network-user-agent" }, - { id: "RobotsTxt", gatherer: "seo/robots-txt" }, - { id: "Scripts", gatherer: "scripts" }, - { id: "SourceMaps", gatherer: "source-maps" }, - { id: "Stacks", gatherer: "stacks" }, - { id: "Stylesheets", gatherer: "stylesheets" }, - { id: "TraceElements", gatherer: "trace-elements" }, - { id: "ViewportDimensions", gatherer: "viewport-dimensions" }, - // FullPageScreenshot comes at the end so all other node analysis is captured. - { id: "FullPageScreenshot", gatherer: "full-page-screenshot" }, - // BFCacheFailures comes at the very end because it can perform a page navigation. - { id: "BFCacheFailures", gatherer: "bf-cache-failures" } - ], - audits: [ - "is-on-https", - "redirects-http", - "metrics/first-contentful-paint", - "metrics/largest-contentful-paint", - "metrics/speed-index", - "screenshot-thumbnails", - "final-screenshot", - "metrics/total-blocking-time", - "metrics/max-potential-fid", - "metrics/cumulative-layout-shift", - "metrics/interaction-to-next-paint", - "errors-in-console", - "server-response-time", - "metrics/interactive", - "user-timings", - "redirects", - "image-aspect-ratio", - "image-size-responsive", - "deprecations", - "third-party-cookies", - "mainthread-work-breakdown", - "bootup-time", - "diagnostics", - "network-requests", - "network-rtt", - "network-server-latency", - "main-thread-tasks", - "metrics", - "resource-summary", - "layout-shifts", - "long-tasks", - "non-composited-animations", - "unsized-images", - "valid-source-maps", - "csp-xss", - "has-hsts", - "origin-isolation", - "clickjacking-mitigation", - "trusted-types-xss", - "script-treemap-data", - "accessibility/accesskeys", - "accessibility/aria-allowed-attr", - "accessibility/aria-allowed-role", - "accessibility/aria-command-name", - "accessibility/aria-conditional-attr", - "accessibility/aria-deprecated-role", - "accessibility/aria-dialog-name", - "accessibility/aria-hidden-body", - "accessibility/aria-hidden-focus", - "accessibility/aria-input-field-name", - "accessibility/aria-meter-name", - "accessibility/aria-progressbar-name", - "accessibility/aria-prohibited-attr", - "accessibility/aria-required-attr", - "accessibility/aria-required-children", - "accessibility/aria-required-parent", - "accessibility/aria-roles", - "accessibility/aria-text", - "accessibility/aria-toggle-field-name", - "accessibility/aria-tooltip-name", - "accessibility/aria-treeitem-name", - "accessibility/aria-valid-attr-value", - "accessibility/aria-valid-attr", - "accessibility/button-name", - "accessibility/bypass", - "accessibility/color-contrast", - "accessibility/definition-list", - "accessibility/dlitem", - "accessibility/document-title", - "accessibility/duplicate-id-aria", - "accessibility/empty-heading", - "accessibility/form-field-multiple-labels", - "accessibility/frame-title", - "accessibility/heading-order", - "accessibility/html-has-lang", - "accessibility/html-lang-valid", - "accessibility/html-xml-lang-mismatch", - "accessibility/identical-links-same-purpose", - "accessibility/image-alt", - "accessibility/image-redundant-alt", - "accessibility/input-button-name", - "accessibility/input-image-alt", - "accessibility/label-content-name-mismatch", - "accessibility/label", - "accessibility/landmark-one-main", - "accessibility/link-name", - "accessibility/link-in-text-block", - "accessibility/list", - "accessibility/listitem", - "accessibility/meta-refresh", - "accessibility/meta-viewport", - "accessibility/object-alt", - "accessibility/select-name", - "accessibility/skip-link", - "accessibility/tabindex", - "accessibility/table-duplicate-name", - "accessibility/table-fake-caption", - "accessibility/target-size", - "accessibility/td-has-header", - "accessibility/td-headers-attr", - "accessibility/th-has-data-cells", - "accessibility/valid-lang", - "accessibility/video-caption", - "accessibility/manual/custom-controls-labels", - "accessibility/manual/custom-controls-roles", - "accessibility/manual/focus-traps", - "accessibility/manual/focusable-controls", - "accessibility/manual/interactive-element-affordance", - "accessibility/manual/logical-tab-order", - "accessibility/manual/managed-focus", - "accessibility/manual/offscreen-content-hidden", - "accessibility/manual/use-landmarks", - "accessibility/manual/visual-order-follows-dom", - "byte-efficiency/total-byte-weight", - "byte-efficiency/unminified-css", - "byte-efficiency/unminified-javascript", - "byte-efficiency/unused-css-rules", - "byte-efficiency/unused-javascript", - "dobetterweb/doctype", - "dobetterweb/charset", - "dobetterweb/geolocation-on-start", - "dobetterweb/inspector-issues", - "dobetterweb/js-libraries", - "dobetterweb/notification-on-start", - "dobetterweb/paste-preventing-inputs", - "seo/meta-description", - "seo/http-status-code", - "seo/link-text", - "seo/crawlable-anchors", - "seo/is-crawlable", - "seo/robots-txt", - "seo/hreflang", - "seo/canonical", - "seo/manual/structured-data", - "bf-cache", - "insights/cache-insight", - "insights/cls-culprits-insight", - "insights/document-latency-insight", - "insights/dom-size-insight", - "insights/duplicated-javascript-insight", - "insights/font-display-insight", - "insights/forced-reflow-insight", - "insights/image-delivery-insight", - "insights/inp-breakdown-insight", - "insights/lcp-breakdown-insight", - "insights/lcp-discovery-insight", - "insights/legacy-javascript-insight", - "insights/modern-http-insight", - "insights/network-dependency-tree-insight", - "insights/render-blocking-insight", - "insights/third-parties-insight", - "insights/viewport-insight" - ], - groups: { - "metrics": { - title: str_2(UIStrings21.metricGroupTitle) - }, - "insights": { - title: str_2(UIStrings21.insightsGroupTitle), - description: str_2(UIStrings21.insightsGroupDescription) - }, - "diagnostics": { - title: str_2(UIStrings21.diagnosticsGroupTitle), - description: str_2(UIStrings21.diagnosticsGroupDescription) - }, - "a11y-best-practices": { - title: str_2(UIStrings21.a11yBestPracticesGroupTitle), - description: str_2(UIStrings21.a11yBestPracticesGroupDescription) - }, - "a11y-color-contrast": { - title: str_2(UIStrings21.a11yColorContrastGroupTitle), - description: str_2(UIStrings21.a11yColorContrastGroupDescription) - }, - "a11y-names-labels": { - title: str_2(UIStrings21.a11yNamesLabelsGroupTitle), - description: str_2(UIStrings21.a11yNamesLabelsGroupDescription) - }, - "a11y-navigation": { - title: str_2(UIStrings21.a11yNavigationGroupTitle), - description: str_2(UIStrings21.a11yNavigationGroupDescription) - }, - "a11y-aria": { - title: str_2(UIStrings21.a11yAriaGroupTitle), - description: str_2(UIStrings21.a11yAriaGroupDescription) - }, - "a11y-language": { - title: str_2(UIStrings21.a11yLanguageGroupTitle), - description: str_2(UIStrings21.a11yLanguageGroupDescription) - }, - "a11y-audio-video": { - title: str_2(UIStrings21.a11yAudioVideoGroupTitle), - description: str_2(UIStrings21.a11yAudioVideoGroupDescription) - }, - "a11y-tables-lists": { - title: str_2(UIStrings21.a11yTablesListsVideoGroupTitle), - description: str_2(UIStrings21.a11yTablesListsVideoGroupDescription) - }, - "seo-mobile": { - title: str_2(UIStrings21.seoMobileGroupTitle), - description: str_2(UIStrings21.seoMobileGroupDescription) - }, - "seo-content": { - title: str_2(UIStrings21.seoContentGroupTitle), - description: str_2(UIStrings21.seoContentGroupDescription) - }, - "seo-crawl": { - title: str_2(UIStrings21.seoCrawlingGroupTitle), - description: str_2(UIStrings21.seoCrawlingGroupDescription) - }, - "best-practices-trust-safety": { - title: str_2(UIStrings21.bestPracticesTrustSafetyGroupTitle) - }, - "best-practices-ux": { - title: str_2(UIStrings21.bestPracticesUXGroupTitle) - }, - "best-practices-browser-compat": { - title: str_2(UIStrings21.bestPracticesBrowserCompatGroupTitle) - }, - "best-practices-general": { - title: str_2(UIStrings21.bestPracticesGeneralGroupTitle) - }, - // Group for audits that should not be displayed. - "hidden": { title: "" } - }, - categories: { - "performance": { - title: str_2(UIStrings21.performanceCategoryTitle), - supportedModes: ["navigation", "timespan", "snapshot"], - auditRefs: [ - { id: "first-contentful-paint", weight: 10, group: "metrics", acronym: "FCP" }, - { id: "largest-contentful-paint", weight: 25, group: "metrics", acronym: "LCP" }, - { id: "total-blocking-time", weight: 30, group: "metrics", acronym: "TBT" }, - { id: "cumulative-layout-shift", weight: 25, group: "metrics", acronym: "CLS" }, - { id: "speed-index", weight: 10, group: "metrics", acronym: "SI" }, - { id: "interaction-to-next-paint", weight: 0, group: "metrics", acronym: "INP" }, - // Insight audits. - { id: "cache-insight", weight: 0, group: "insights" }, - { id: "cls-culprits-insight", weight: 0, group: "insights" }, - { id: "document-latency-insight", weight: 0, group: "insights" }, - { id: "dom-size-insight", weight: 0, group: "insights" }, - { id: "duplicated-javascript-insight", weight: 0, group: "insights" }, - { id: "font-display-insight", weight: 0, group: "insights" }, - { id: "forced-reflow-insight", weight: 0, group: "insights" }, - { id: "image-delivery-insight", weight: 0, group: "insights" }, - { id: "inp-breakdown-insight", weight: 0, group: "insights" }, - { id: "lcp-breakdown-insight", weight: 0, group: "insights" }, - { id: "lcp-discovery-insight", weight: 0, group: "insights" }, - { id: "legacy-javascript-insight", weight: 0, group: "insights" }, - { id: "modern-http-insight", weight: 0, group: "insights" }, - { id: "network-dependency-tree-insight", weight: 0, group: "insights" }, - { id: "render-blocking-insight", weight: 0, group: "insights" }, - { id: "third-parties-insight", weight: 0, group: "insights" }, - { id: "viewport-insight", weight: 0, group: "insights" }, - // These are our "invisible" metrics. Not displayed, but still in the LHR. - { id: "interactive", weight: 0, group: "hidden", acronym: "TTI" }, - { id: "max-potential-fid", weight: 0, group: "hidden" }, - { id: "unminified-css", weight: 0, group: "diagnostics" }, - { id: "unminified-javascript", weight: 0, group: "diagnostics" }, - { id: "unused-css-rules", weight: 0, group: "diagnostics" }, - { id: "unused-javascript", weight: 0, group: "diagnostics" }, - { id: "total-byte-weight", weight: 0, group: "diagnostics" }, - { id: "user-timings", weight: 0, group: "diagnostics" }, - { id: "bootup-time", weight: 0, group: "diagnostics" }, - { id: "mainthread-work-breakdown", weight: 0, group: "diagnostics" }, - { id: "long-tasks", weight: 0, group: "diagnostics" }, - { id: "non-composited-animations", weight: 0, group: "diagnostics" }, - { id: "unsized-images", weight: 0, group: "diagnostics" }, - { id: "bf-cache", weight: 0, group: "diagnostics" }, - // Audits past this point contain useful data but are not displayed with other audits. - { id: "network-requests", weight: 0, group: "hidden" }, - { id: "network-rtt", weight: 0, group: "hidden" }, - { id: "network-server-latency", weight: 0, group: "hidden" }, - { id: "main-thread-tasks", weight: 0, group: "hidden" }, - { id: "diagnostics", weight: 0, group: "hidden" }, - { id: "metrics", weight: 0, group: "hidden" }, - { id: "screenshot-thumbnails", weight: 0, group: "hidden" }, - { id: "final-screenshot", weight: 0, group: "hidden" }, - { id: "script-treemap-data", weight: 0, group: "hidden" }, - { id: "resource-summary", weight: 0, group: "hidden" }, - { id: "redirects", weight: 0, group: "hidden" }, - { id: "server-response-time", weight: 0, group: "hidden" }, - { id: "layout-shifts", weight: 0, group: "hidden" } - ] - }, - "accessibility": { - title: str_2(UIStrings21.a11yCategoryTitle), - description: str_2(UIStrings21.a11yCategoryDescription), - manualDescription: str_2(UIStrings21.a11yCategoryManualDescription), - supportedModes: ["navigation", "snapshot"], - // Audit weights weights are derived from the axe-core "Impact", - // with adjustments based on axe-core "Tags": - // - // ┌────────────┬───────────────────────────────────────────────┐ - // │ Impact │ Weight Based on Tags │ - // │ ├──────────────┬─────────────────┬──────────────┤ - // │ │ wcag A+AA │ best-practice │ experimental │ - // │ │ (ex: wcag2aa)│ (w/o wcag tag) │ │ - // ├────────────┼──────────────┼─────────────────┼──────────────┤ - // │ Minor │ 1 │ 0 │ 0 │ - // │ Moderate │ 3 │ 3 │ 0 │ - // │ Serious │ 7 │ 7 │ 0 │ - // │ Critical │ 10 │ 10 │ 0 │ - // └────────────┴──────────────┴─────────────────┴──────────────┘ - // - // Notes: - // • Experimental rules always have weight 0 - // • Best practice rules only affect scores when tagged with wcagA+AA - // and are moderate, serious, or critical. - // - // To find the latest axe-core Impact and Tag values: - // 1. Browse to https://dequeuniversity.com/rules/axe/html. - // 2. Click on the latest rule set (ex: https://dequeuniversity.com/rules/axe/html/4.10) - // 3. Review the tables - auditRefs: [ - { id: "accesskeys", weight: 7, group: "a11y-navigation" }, - // Serious, best-practice - { id: "aria-allowed-attr", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-command-name", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-conditional-attr", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-deprecated-role", weight: 1, group: "a11y-aria" }, - // Minor, wcag2a - { id: "aria-dialog-name", weight: 7, group: "a11y-aria" }, - // Serious, best-practice - { id: "aria-hidden-body", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-hidden-focus", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-input-field-name", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-meter-name", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-progressbar-name", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-prohibited-attr", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-required-attr", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-required-children", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-required-parent", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-roles", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-text", weight: 7, group: "a11y-aria" }, - // Serious, best-practice - { id: "aria-toggle-field-name", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-tooltip-name", weight: 7, group: "a11y-aria" }, - // Serious, wcag2a - { id: "aria-treeitem-name", weight: 7, group: "a11y-aria" }, - // Serious, best-practice - { id: "aria-valid-attr-value", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "aria-valid-attr", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "button-name", weight: 10, group: "a11y-names-labels" }, - // Critical, wcag2a - { id: "bypass", weight: 7, group: "a11y-navigation" }, - // Serious, wcag2a - { id: "color-contrast", weight: 7, group: "a11y-color-contrast" }, - // Serious, wcag2aa - { id: "definition-list", weight: 7, group: "a11y-tables-lists" }, - // Serious, wcag2a - { id: "dlitem", weight: 7, group: "a11y-tables-lists" }, - // Serious, wcag2a - { id: "document-title", weight: 7, group: "a11y-names-labels" }, - // Serious, wcag2a - { id: "duplicate-id-aria", weight: 10, group: "a11y-aria" }, - // Critical, wcag2a - { id: "form-field-multiple-labels", weight: 3, group: "a11y-names-labels" }, - // Moderate, wcag2a - { id: "frame-title", weight: 7, group: "a11y-names-labels" }, - // Serious, wcag2a - { id: "heading-order", weight: 3, group: "a11y-navigation" }, - // Moderate, best-practice - { id: "html-has-lang", weight: 7, group: "a11y-language" }, - // Serious, wcag2a - { id: "html-lang-valid", weight: 7, group: "a11y-language" }, - // Serious, wcag2a - { id: "html-xml-lang-mismatch", weight: 3, group: "a11y-language" }, - // Moderate, wcag2a - { id: "image-alt", weight: 10, group: "a11y-names-labels" }, - // Critical, wcag2a - { id: "input-button-name", weight: 10, group: "a11y-names-labels" }, - // Critical, wcag2a - { id: "input-image-alt", weight: 10, group: "a11y-names-labels" }, - // Critical, wcag2a - { id: "label", weight: 10, group: "a11y-names-labels" }, - // Critical, wcag2a - { id: "link-in-text-block", weight: 7, group: "a11y-color-contrast" }, - // Serious, wcag2a - { id: "link-name", weight: 7, group: "a11y-names-labels" }, - // Serious, wcag2a - { id: "list", weight: 7, group: "a11y-tables-lists" }, - // Serious, wcag2a - { id: "listitem", weight: 7, group: "a11y-tables-lists" }, - // Serious, wcag2a - { id: "meta-refresh", weight: 10, group: "a11y-best-practices" }, - // Critical, wcag2a - { id: "meta-viewport", weight: 10, group: "a11y-best-practices" }, - // Critical, wcag2aa - { id: "object-alt", weight: 7, group: "a11y-names-labels" }, - // Serious, wcag2a - { id: "select-name", weight: 10, group: "a11y-names-labels" }, - // Critical, wcag2a - { id: "skip-link", weight: 3, group: "a11y-names-labels" }, - // Moderate, best-practice - { id: "tabindex", weight: 7, group: "a11y-navigation" }, - // Serious, best-practice - { id: "target-size", weight: 7, group: "a11y-best-practices" }, - // Serious, wcag22aa - { id: "td-headers-attr", weight: 7, group: "a11y-tables-lists" }, - // Serious, wcag2a - { id: "th-has-data-cells", weight: 7, group: "a11y-tables-lists" }, - // Serious, wcag2a - { id: "valid-lang", weight: 7, group: "a11y-language" }, - // Serious, wcag2aa - { id: "video-caption", weight: 10, group: "a11y-audio-video" }, - // Critical, wcag2a - { id: "landmark-one-main", weight: 3, group: "a11y-best-practices" }, - // Moderate, best-practice - // Manual audits - { id: "focusable-controls", weight: 0 }, - { id: "interactive-element-affordance", weight: 0 }, - { id: "logical-tab-order", weight: 0 }, - { id: "visual-order-follows-dom", weight: 0 }, - { id: "focus-traps", weight: 0 }, - { id: "managed-focus", weight: 0 }, - { id: "use-landmarks", weight: 0 }, - { id: "offscreen-content-hidden", weight: 0 }, - { id: "custom-controls-labels", weight: 0 }, - { id: "custom-controls-roles", weight: 0 }, - // Low-impact best-practices - { id: "table-duplicate-name", weight: 0, group: "a11y-best-practices" }, - // Minor, best-practice - { id: "empty-heading", weight: 0, group: "a11y-best-practices" }, - // Minor, best-practice - { id: "aria-allowed-role", weight: 0, group: "a11y-best-practices" }, - // Minor, best-practice - { id: "image-redundant-alt", weight: 0, group: "a11y-names-labels" }, - // Minor, best-practice - // WCAG AAA - { id: "identical-links-same-purpose", weight: 0, group: "a11y-best-practices" }, - // Minor, wcag2aaa - // Hidden audits (ie. experimental) - { id: "label-content-name-mismatch", weight: 0, group: "hidden" }, - // Serious, experimental - { id: "table-fake-caption", weight: 0, group: "hidden" }, - // Serious, experimental - { id: "td-has-header", weight: 0, group: "hidden" } - // Critical, experimental - ] - }, - "best-practices": { - title: str_2(UIStrings21.bestPracticesCategoryTitle), - supportedModes: ["navigation", "timespan", "snapshot"], - auditRefs: [ - // Trust & Safety - { id: "is-on-https", weight: 5, group: "best-practices-trust-safety" }, - { id: "redirects-http", weight: 1, group: "best-practices-trust-safety" }, - { id: "geolocation-on-start", weight: 1, group: "best-practices-trust-safety" }, - { id: "notification-on-start", weight: 1, group: "best-practices-trust-safety" }, - { id: "csp-xss", weight: 0, group: "best-practices-trust-safety" }, - { id: "has-hsts", weight: 0, group: "best-practices-trust-safety" }, - { id: "origin-isolation", weight: 0, group: "best-practices-trust-safety" }, - { id: "clickjacking-mitigation", weight: 0, group: "best-practices-trust-safety" }, - { id: "trusted-types-xss", weight: 0, group: "best-practices-trust-safety" }, - // User Experience - { id: "paste-preventing-inputs", weight: 3, group: "best-practices-ux" }, - { id: "image-aspect-ratio", weight: 1, group: "best-practices-ux" }, - { id: "image-size-responsive", weight: 1, group: "best-practices-ux" }, - // Browser Compatibility - { id: "doctype", weight: 1, group: "best-practices-browser-compat" }, - { id: "charset", weight: 1, group: "best-practices-browser-compat" }, - // General Group - { id: "js-libraries", weight: 0, group: "best-practices-general" }, - { id: "deprecations", weight: 5, group: "best-practices-general" }, - { id: "third-party-cookies", weight: 5, group: "best-practices-general" }, - { id: "errors-in-console", weight: 1, group: "best-practices-general" }, - { id: "valid-source-maps", weight: 0, group: "best-practices-general" }, - { id: "inspector-issues", weight: 1, group: "best-practices-general" } - ] - }, - "seo": { - title: str_2(UIStrings21.seoCategoryTitle), - description: str_2(UIStrings21.seoCategoryDescription), - manualDescription: str_2(UIStrings21.seoCategoryManualDescription), - supportedModes: ["navigation", "snapshot"], - auditRefs: [ - // Should be at least 31% of the score, such that this audit failing - // results in the SEO category failing. - // Solve for w: - // w / (w + T) >= 0.31 - // where T is the sum of all the other weights. - { id: "is-crawlable", weight: 93 / 23, group: "seo-crawl" }, - { id: "document-title", weight: 1, group: "seo-content" }, - { id: "meta-description", weight: 1, group: "seo-content" }, - { id: "http-status-code", weight: 1, group: "seo-crawl" }, - { id: "link-text", weight: 1, group: "seo-content" }, - { id: "crawlable-anchors", weight: 1, group: "seo-crawl" }, - { id: "robots-txt", weight: 1, group: "seo-crawl" }, - { id: "image-alt", weight: 1, group: "seo-content" }, - { id: "hreflang", weight: 1, group: "seo-content" }, - { id: "canonical", weight: 1, group: "seo-content" }, - // Manual audits - { id: "structured-data", weight: 0 } - ] - } - } - }; - Object.defineProperty(defaultConfig, "UIStrings", { - enumerable: false, - get: /* @__PURE__ */ __name(() => UIStrings21, "get") - }); - default_config_default = defaultConfig; - } -}); - -// core/config/validation.js -function isValidArtifactDependency(dependent, dependency) { - const levels = { timespan: 0, snapshot: 1, navigation: 2 }; - const dependentLevel = Math.min(...dependent.instance.meta.supportedModes.map((l) => levels[l])); - const dependencyLevel = Math.min(...dependency.instance.meta.supportedModes.map((l) => levels[l])); - if (dependentLevel === levels.timespan) return dependencyLevel === levels.timespan; - if (dependentLevel === levels.snapshot) return dependencyLevel === levels.snapshot; - return true; -} -function assertValidPluginName(config3, pluginName) { - const parts = pluginName.split("/"); - if (parts.length === 2) { - pluginName = parts[1]; - } - if (!pluginName.startsWith("lighthouse-plugin-")) { - throw new Error(`plugin name '${pluginName}' does not start with 'lighthouse-plugin-'`); - } - if (config3.categories?.[pluginName]) { - throw new Error(`plugin name '${pluginName}' not allowed because it is the id of a category already found in config`); - } -} -function assertValidArtifact(artifactDefn) { - const gatherer = artifactDefn.gatherer.instance; - if (typeof gatherer.meta !== "object") { - throw new Error(`Gatherer for ${artifactDefn.id} did not provide a meta object.`); - } - if (gatherer.meta.supportedModes.length === 0) { - throw new Error(`Gatherer for ${artifactDefn.id} did not support any gather modes.`); - } - if (typeof gatherer.getArtifact !== "function" || gatherer.getArtifact === base_gatherer_default.prototype.getArtifact) { - throw new Error(`Gatherer for ${artifactDefn.id} did not define a "getArtifact" method.`); - } -} -function assertValidAudit(auditDefinition) { - const { implementation, path: auditPath } = auditDefinition; - const auditName = auditPath || implementation?.meta?.id || "Unknown audit"; - if (typeof implementation.audit !== "function" || implementation.audit === Audit.audit) { - throw new Error(`${auditName} has no audit() method.`); - } - if (typeof implementation.meta.id !== "string") { - throw new Error(`${auditName} has no meta.id property, or the property is not a string.`); - } - if (!isStringOrIcuMessage(implementation.meta.title)) { - throw new Error(`${auditName} has no meta.title property, or the property is not a string.`); - } - const scoreDisplayMode = implementation.meta.scoreDisplayMode || Audit.SCORING_MODES.BINARY; - if (!isStringOrIcuMessage(implementation.meta.failureTitle) && scoreDisplayMode === Audit.SCORING_MODES.BINARY) { - throw new Error(`${auditName} has no meta.failureTitle and should.`); - } - if (!isStringOrIcuMessage(implementation.meta.description)) { - throw new Error( - `${auditName} has no meta.description property, or the property is not a string.` - ); - } else if (implementation.meta.description === "") { - throw new Error( - `${auditName} has an empty meta.description string. Please add a description for the UI.` - ); - } - if (!Array.isArray(implementation.meta.requiredArtifacts)) { - throw new Error( - `${auditName} has no meta.requiredArtifacts property, or the property is not an array.` - ); - } -} -function assertValidCategories(categories, audits, groups) { - if (!categories) { - return; - } - const auditsKeyedById = new Map((audits || []).map((audit) => { - return [audit.implementation.meta.id, audit]; - })); - Object.keys(categories).forEach((categoryId) => { - categories[categoryId].auditRefs.forEach((auditRef, index) => { - if (!auditRef.id) { - throw new Error(`missing an audit id at ${categoryId}[${index}]`); - } - const audit = auditsKeyedById.get(auditRef.id); - if (!audit) { - throw new Error(`could not find ${auditRef.id} audit for category ${categoryId}`); - } - const auditImpl = audit.implementation; - const isManual = auditImpl.meta.scoreDisplayMode === "manual"; - if (categoryId === "accessibility" && !auditRef.group && !isManual) { - throw new Error(`${auditRef.id} accessibility audit does not have a group`); - } - if (auditRef.weight > 0 && isManual) { - throw new Error(`${auditRef.id} is manual but has a positive weight`); - } - if (auditRef.group && (!groups || !groups[auditRef.group])) { - throw new Error(`${auditRef.id} references unknown group ${auditRef.group}`); - } - }); - }); -} -function assertValidSettings(settings) { - if (!settings.formFactor) { - throw new Error(`\`settings.formFactor\` must be defined as 'mobile' or 'desktop'. See https://github.com/GoogleChrome/lighthouse/blob/main/docs/emulation.md`); - } - if (!settings.screenEmulation.disabled) { - if (settings.screenEmulation.mobile !== (settings.formFactor === "mobile")) { - throw new Error(`Screen emulation mobile setting (${settings.screenEmulation.mobile}) does not match formFactor setting (${settings.formFactor}). See https://github.com/GoogleChrome/lighthouse/blob/main/docs/emulation.md`); - } - } - const skippedAndOnlyAuditId = settings.skipAudits?.find((auditId) => settings.onlyAudits?.includes(auditId)); - if (skippedAndOnlyAuditId) { - throw new Error(`${skippedAndOnlyAuditId} appears in both skipAudits and onlyAudits`); - } -} -function assertValidArtifacts(artifactDefns) { - const availableArtifacts = /* @__PURE__ */ new Set(); - for (const artifact of artifactDefns) { - assertValidArtifact(artifact); - if (availableArtifacts.has(artifact.id)) { - throw new Error(`Config defined multiple artifacts with id '${artifact.id}'`); - } - availableArtifacts.add(artifact.id); - if (!artifact.dependencies) continue; - for (const [dependencyKey, { id: dependencyId }] of Object.entries(artifact.dependencies)) { - if (availableArtifacts.has(dependencyId)) continue; - throwInvalidDependencyOrder(artifact.id, dependencyKey); - } - } -} -function assertValidConfig(resolvedConfig) { - assertValidArtifacts(resolvedConfig.artifacts || []); - for (const auditDefn of resolvedConfig.audits || []) { - assertValidAudit(auditDefn); - } - assertValidCategories(resolvedConfig.categories, resolvedConfig.audits, resolvedConfig.groups); - assertValidSettings(resolvedConfig.settings); -} -function throwInvalidDependencyOrder(artifactId, dependencyKey) { - throw new Error( - [ - `Failed to find dependency "${dependencyKey}" for "${artifactId}" artifact`, - `Check that...`, - ` 1. A gatherer exposes a matching Symbol that satisfies "${dependencyKey}".`, - ` 2. "${dependencyKey}" is configured to run before "${artifactId}"` - ].join("\n") - ); -} -function throwInvalidArtifactDependency(artifactId, dependencyKey) { - throw new Error( - [ - `Dependency "${dependencyKey}" for "${artifactId}" artifact is invalid.`, - `The dependency must be collected before the dependent.` - ].join("\n") - ); -} -var init_validation = __esm({ - "core/config/validation.js"() { - "use strict"; - init_process_global(); - init_audit(); - init_base_gatherer(); - init_i18n(); - /** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - __name(isValidArtifactDependency, "isValidArtifactDependency"); - __name(assertValidPluginName, "assertValidPluginName"); - __name(assertValidArtifact, "assertValidArtifact"); - __name(assertValidAudit, "assertValidAudit"); - __name(assertValidCategories, "assertValidCategories"); - __name(assertValidSettings, "assertValidSettings"); - __name(assertValidArtifacts, "assertValidArtifacts"); - __name(assertValidConfig, "assertValidConfig"); - __name(throwInvalidDependencyOrder, "throwInvalidDependencyOrder"); - __name(throwInvalidArtifactDependency, "throwInvalidArtifactDependency"); - } -}); - -// core/config/filters.js -function getAuditIdsInCategories(allCategories, onlyCategories) { - if (!allCategories) return /* @__PURE__ */ new Set(); - onlyCategories = onlyCategories || Object.keys(allCategories); - const categories = onlyCategories.map((categoryId) => allCategories[categoryId]); - const auditRefs = categories.flatMap((category) => category?.auditRefs || []); - return new Set(auditRefs.map((auditRef) => auditRef.id)); -} -function filterArtifactsByAvailableAudits(artifacts, audits) { - if (!artifacts) return null; - if (!audits) return artifacts; - const artifactsById = new Map(artifacts.map((artifact) => [artifact.id, artifact])); - const artifactIdsToKeep = /* @__PURE__ */ new Set([ - ...filterResistantArtifactIds, - ...audits.flatMap((audit) => audit.implementation.meta.requiredArtifacts) - ]); - let previousSize = 0; - while (previousSize !== artifactIdsToKeep.size) { - previousSize = artifactIdsToKeep.size; - for (const artifactId of artifactIdsToKeep) { - const artifact = artifactsById.get(artifactId); - if (!artifact) continue; - if (!artifact.dependencies) continue; - for (const dep of Object.values(artifact.dependencies)) { - artifactIdsToKeep.add(dep.id); - } - } - } - return artifacts.filter((artifact) => artifactIdsToKeep.has(artifact.id)); -} -function filterArtifactsByGatherMode(artifacts, mode) { - if (!artifacts) return null; - return artifacts.filter((artifact) => { - return artifact.gatherer.instance.meta.supportedModes.includes(mode); - }); -} -function filterAuditsByAvailableArtifacts(audits, availableArtifacts) { - if (!audits) return null; - const availableArtifactIds = new Set( - availableArtifacts.map((artifact) => artifact.id).concat(baseArtifactKeys) - ); - return audits.filter((audit) => { - const meta = audit.implementation.meta; - return meta.requiredArtifacts.every((id) => availableArtifactIds.has(id)); - }); -} -function filterAuditsByGatherMode(audits, mode) { - if (!audits) return null; - return audits.filter((audit) => { - const meta = audit.implementation.meta; - return !meta.supportedModes || meta.supportedModes.includes(mode); - }); -} -function filterCategoriesByGatherMode(categories, mode) { - if (!categories) return null; - const categoriesToKeep = Object.entries(categories).filter(([_, category]) => { - return !category.supportedModes || category.supportedModes.includes(mode); - }); - return Object.fromEntries(categoriesToKeep); -} -function filterCategoriesByExplicitFilters(categories, onlyCategories) { - if (!categories || !onlyCategories) return categories; - const categoriesToKeep = Object.entries(categories).filter(([categoryId]) => onlyCategories.includes(categoryId)); - return Object.fromEntries(categoriesToKeep); -} -function errorOnUnknownOnlyCategories(allCategories, onlyCategories) { - if (!onlyCategories) return; - const unknown = onlyCategories.filter((c) => !allCategories?.[c]); - if (unknown.length) { - throw new Error(`unrecognized category in 'onlyCategories': ${unknown.join(", ")}`); - } -} -function filterCategoriesByAvailableAudits(categories, availableAudits) { - if (!categories) return categories; - const availableAuditIdToMeta = new Map( - availableAudits.map((audit) => [audit.implementation.meta.id, audit.implementation.meta]) - ); - const categoryEntries = Object.entries(categories).map(([categoryId, category]) => { - const filteredCategory = { - ...category, - auditRefs: category.auditRefs.filter((ref) => availableAuditIdToMeta.has(ref.id)) - }; - const didFilter = filteredCategory.auditRefs.length < category.auditRefs.length; - const hasOnlyManualAudits = filteredCategory.auditRefs.every((ref) => { - const meta = availableAuditIdToMeta.get(ref.id); - if (!meta) return false; - return meta.scoreDisplayMode === Audit.SCORING_MODES.MANUAL; - }); - if (didFilter && hasOnlyManualAudits) filteredCategory.auditRefs = []; - return [categoryId, filteredCategory]; - }).filter((entry) => typeof entry[1] === "object" && entry[1].auditRefs.length); - return Object.fromEntries(categoryEntries); -} -function filterConfigByGatherMode(resolvedConfig, mode) { - const artifacts = filterArtifactsByGatherMode(resolvedConfig.artifacts, mode); - const supportedAudits = filterAuditsByGatherMode(resolvedConfig.audits, mode); - const audits = filterAuditsByAvailableArtifacts(supportedAudits, artifacts || []); - const supportedCategories = filterCategoriesByGatherMode(resolvedConfig.categories, mode); - const categories = filterCategoriesByAvailableAudits(supportedCategories, audits || []); - return { - ...resolvedConfig, - artifacts, - audits, - categories - }; -} -function filterConfigByExplicitFilters(resolvedConfig, filters) { - const { onlyAudits, onlyCategories, skipAudits } = filters; - if (onlyAudits && !onlyAudits.length) { - throw new Error(`onlyAudits cannot be an empty array.`); - } - if (onlyCategories && !onlyCategories.length) { - throw new Error(`onlyCategories cannot be an empty array.`); - } - errorOnUnknownOnlyCategories(resolvedConfig.categories, onlyCategories); - let baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, void 0); - if (onlyCategories) { - baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, onlyCategories); - } else if (onlyAudits) { - baseAuditIds = /* @__PURE__ */ new Set(); - } else if (!resolvedConfig.categories || !Object.keys(resolvedConfig.categories).length) { - baseAuditIds = new Set(resolvedConfig.audits?.map((audit) => audit.implementation.meta.id)); - } - const auditIdsToKeep = new Set( - [ - ...baseAuditIds, - // Start with our base audits. - ...onlyAudits || [], - // Additionally include the opt-in audits from `onlyAudits`. - ...filterResistantAuditIds - // Always include any filter-resistant audits. - ].filter((auditId) => !skipAudits || !skipAudits.includes(auditId)) - ); - const audits = auditIdsToKeep.size && resolvedConfig.audits ? resolvedConfig.audits.filter((audit) => auditIdsToKeep.has(audit.implementation.meta.id)) : resolvedConfig.audits; - const availableCategories = filterCategoriesByAvailableAudits(resolvedConfig.categories, audits || []); - const categories = filterCategoriesByExplicitFilters(availableCategories, onlyCategories); - let artifacts = filterArtifactsByAvailableAudits(resolvedConfig.artifacts, audits); - if (artifacts && resolvedConfig.settings.disableFullPageScreenshot) { - artifacts = artifacts.filter(({ id }) => id !== "FullPageScreenshot"); - } - return { - ...resolvedConfig, - artifacts, - audits, - categories - }; -} -var baseArtifactKeySource, baseArtifactKeys, filterResistantAuditIds, filterResistantArtifactIds; -var init_filters = __esm({ - "core/config/filters.js"() { - "use strict"; - init_process_global(); - init_audit(); - /** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - baseArtifactKeySource = { - fetchTime: "", - LighthouseRunWarnings: "", - BenchmarkIndex: "", - HostDPR: "", - settings: "", - Timing: "", - URL: "", - PageLoadError: "", - HostFormFactor: "", - HostUserAgent: "", - HostProduct: "", - GatherContext: "" - }; - baseArtifactKeys = Object.keys(baseArtifactKeySource); - filterResistantAuditIds = []; - filterResistantArtifactIds = ["Stacks", "NetworkUserAgent", "FullPageScreenshot"]; - __name(getAuditIdsInCategories, "getAuditIdsInCategories"); - __name(filterArtifactsByAvailableAudits, "filterArtifactsByAvailableAudits"); - __name(filterArtifactsByGatherMode, "filterArtifactsByGatherMode"); - __name(filterAuditsByAvailableArtifacts, "filterAuditsByAvailableArtifacts"); - __name(filterAuditsByGatherMode, "filterAuditsByGatherMode"); - __name(filterCategoriesByGatherMode, "filterCategoriesByGatherMode"); - __name(filterCategoriesByExplicitFilters, "filterCategoriesByExplicitFilters"); - __name(errorOnUnknownOnlyCategories, "errorOnUnknownOnlyCategories"); - __name(filterCategoriesByAvailableAudits, "filterCategoriesByAvailableAudits"); - __name(filterConfigByGatherMode, "filterConfigByGatherMode"); - __name(filterConfigByExplicitFilters, "filterConfigByExplicitFilters"); - } -}); - -// core/config/config-plugin.js -function isArrayOfUnknownObjects(arr) { - return Array.isArray(arr) && arr.every(isObjectOfUnknownProperties); -} -function isObjectOfUnknownProperties(val) { - return typeof val === "object" && val !== null && !Array.isArray(val); -} -function objectIsGatherMode(str) { - if (typeof str !== "string") return false; - return str === "navigation" || str === "timespan" || str === "snapshot"; -} -function isArrayOfGatherModes(arr) { - if (!Array.isArray(arr)) return false; - return arr.every(objectIsGatherMode); -} -function assertNoExcessProperties(obj, pluginName, objectName = "") { - if (objectName) { - objectName += " "; - } - const invalidKeys = Object.keys(obj); - if (invalidKeys.length > 0) { - const keys2 = invalidKeys.join(", "); - throw new Error(`${pluginName} has unrecognized ${objectName}properties: [${keys2}]`); - } -} -var ConfigPlugin, config_plugin_default; -var init_config_plugin = __esm({ - "core/config/config-plugin.js"() { - "use strict"; - init_process_global(); - init_i18n(); - /** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - __name(isArrayOfUnknownObjects, "isArrayOfUnknownObjects"); - __name(isObjectOfUnknownProperties, "isObjectOfUnknownProperties"); - __name(objectIsGatherMode, "objectIsGatherMode"); - __name(isArrayOfGatherModes, "isArrayOfGatherModes"); - __name(assertNoExcessProperties, "assertNoExcessProperties"); - ConfigPlugin = class _ConfigPlugin { - static { - __name(this, "ConfigPlugin"); - } - /** - * Extract and validate the list of AuditDefns added by the plugin (or undefined - * if no additional audits are being added by the plugin). - * @param {unknown} auditsJson - * @param {string} pluginName - * @return {Array<{path: string}>|undefined} - */ - static _parseAuditsList(auditsJson, pluginName) { - if (auditsJson === void 0) { - return void 0; - } else if (!isArrayOfUnknownObjects(auditsJson)) { - throw new Error(`${pluginName} has an invalid audits array.`); - } - return auditsJson.map((auditDefnJson) => { - const { path: path7, ...invalidRest } = auditDefnJson; - assertNoExcessProperties(invalidRest, pluginName, "audit"); - if (typeof path7 !== "string") { - throw new Error(`${pluginName} has a missing audit path.`); - } - return { - path: path7 - }; - }); - } - /** - * Extract and validate the list of category AuditRefs added by the plugin. - * @param {unknown} auditRefsJson - * @param {string} pluginName - * @return {Array} - */ - static _parseAuditRefsList(auditRefsJson, pluginName) { - if (!isArrayOfUnknownObjects(auditRefsJson)) { - throw new Error(`${pluginName} has no valid auditsRefs.`); - } - return auditRefsJson.map((auditRefJson) => { - const { id, weight, group, ...invalidRest } = auditRefJson; - assertNoExcessProperties(invalidRest, pluginName, "auditRef"); - if (typeof id !== "string") { - throw new Error(`${pluginName} has an invalid auditRef id.`); - } - if (typeof weight !== "number") { - throw new Error(`${pluginName} has an invalid auditRef weight.`); - } - if (typeof group !== "string" && typeof group !== "undefined") { - throw new Error(`${pluginName} has an invalid auditRef group.`); - } - const prependedGroup = group ? `${pluginName}-${group}` : group; - return { - id, - weight, - group: prependedGroup - }; - }); - } - /** - * Extract and validate the category added by the plugin. - * @param {unknown} categoryJson - * @param {string} pluginName - * @return {LH.Config.CategoryJson} - */ - static _parseCategory(categoryJson, pluginName) { - if (!isObjectOfUnknownProperties(categoryJson)) { - throw new Error(`${pluginName} has no valid category.`); - } - const { - title, - description, - manualDescription, - auditRefs: auditRefsJson, - supportedModes, - ...invalidRest - } = categoryJson; - assertNoExcessProperties(invalidRest, pluginName, "category"); - if (!isStringOrIcuMessage(title)) { - throw new Error(`${pluginName} has an invalid category tile.`); - } - if (!isStringOrIcuMessage(description) && description !== void 0) { - throw new Error(`${pluginName} has an invalid category description.`); - } - if (!isStringOrIcuMessage(manualDescription) && manualDescription !== void 0) { - throw new Error(`${pluginName} has an invalid category manualDescription.`); - } - if (!isArrayOfGatherModes(supportedModes) && supportedModes !== void 0) { - throw new Error( - `${pluginName} supportedModes must be an array, valid array values are "navigation", "timespan", and "snapshot".` - ); - } - const auditRefs = _ConfigPlugin._parseAuditRefsList(auditRefsJson, pluginName); - return { - title, - auditRefs, - description, - manualDescription, - supportedModes - }; - } - /** - * Extract and validate groups JSON added by the plugin. - * @param {unknown} groupsJson - * @param {string} pluginName - * @return {Record|undefined} - */ - static _parseGroups(groupsJson, pluginName) { - if (groupsJson === void 0) { - return void 0; - } - if (!isObjectOfUnknownProperties(groupsJson)) { - throw new Error(`${pluginName} groups json is not defined as an object.`); - } - const groups = Object.entries(groupsJson); - const parsedGroupsJson = {}; - groups.forEach(([groupId, groupJson]) => { - if (!isObjectOfUnknownProperties(groupJson)) { - throw new Error(`${pluginName} has a group not defined as an object.`); - } - const { title, description, ...invalidRest } = groupJson; - assertNoExcessProperties(invalidRest, pluginName, "group"); - if (!isStringOrIcuMessage(title)) { - throw new Error(`${pluginName} has an invalid group title.`); - } - if (!isStringOrIcuMessage(description) && description !== void 0) { - throw new Error(`${pluginName} has an invalid group description.`); - } - parsedGroupsJson[`${pluginName}-${groupId}`] = { - title, - description - }; - }); - return parsedGroupsJson; - } - /** - * Extracts and validates a config from the provided plugin input, throwing - * if it deviates from the expected object shape. - * @param {unknown} pluginJson - * @param {string} pluginName - * @return {LH.Config} - */ - static parsePlugin(pluginJson, pluginName) { - pluginJson = JSON.parse(JSON.stringify(pluginJson)); - if (!isObjectOfUnknownProperties(pluginJson)) { - throw new Error(`${pluginName} is not defined as an object.`); - } - const { - audits: pluginAuditsJson, - category: pluginCategoryJson, - groups: pluginGroupsJson, - ...invalidRest - } = pluginJson; - assertNoExcessProperties(invalidRest, pluginName); - return { - audits: _ConfigPlugin._parseAuditsList(pluginAuditsJson, pluginName), - categories: { - [pluginName]: _ConfigPlugin._parseCategory(pluginCategoryJson, pluginName) - }, - groups: _ConfigPlugin._parseGroups(pluginGroupsJson, pluginName) - }; - } - }; - config_plugin_default = ConfigPlugin; - } -}); - -// core/lib/axe.js -var require2, axeSource; -var init_axe = __esm({ - "core/lib/axe.js"() { - "use strict"; - init_process_global(); - init_module(); - /** - * @license - * Copyright 2020 Google LLC + * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ require2 = /* @__PURE__ */ createRequire({ url: "core/lib/axe.js" }.url); @@ -48291,196 +46468,6 @@ var init_trace_engine_result = __esm({ } }); -// node_modules/lighthouse-plugin-soft-navigation/plugin.js -var plugin_exports = {}; -__export(plugin_exports, { - default: () => plugin_default -}); -var plugin_default; -var init_plugin = __esm({ - "node_modules/lighthouse-plugin-soft-navigation/plugin.js"() { - init_process_global(); - plugin_default = { - audits: [ - { path: "lighthouse-plugin-soft-navigation/audits/soft-nav-fcp" }, - { path: "lighthouse-plugin-soft-navigation/audits/soft-nav-lcp" } - ], - groups: { - "metrics": { - title: "Metrics associated with a soft navigation" - } - }, - category: { - title: "Soft Navigation", - supportedModes: ["timespan"], - auditRefs: [ - { id: "soft-nav-fcp", weight: 1, group: "metrics" }, - { id: "soft-nav-lcp", weight: 1, group: "metrics" } - ] - } - }; - } -}); - -// node_modules/lighthouse-plugin-soft-navigation/lib/metric-timings.js -function computeMetricTimings(traceEvents) { - let softNavEvent; - let lastLcpCandidate; - let fcpEvent; - for (const event of traceEvents) { - switch (event.name) { - case "SoftNavigationHeuristics_SoftNavigationDetected": - if (softNavEvent) throw new Error("Multiple soft navigations detected"); - softNavEvent = event; - break; - case "largestContentfulPaint::Candidate": - if (softNavEvent) { - lastLcpCandidate = event; - } - break; - case "firstContentfulPaint": - if (softNavEvent) { - fcpEvent = event; - } - break; - } - } - if (!softNavEvent) return {}; - const timeOriginTs = softNavEvent.ts; - const getTiming = /* @__PURE__ */ __name((event) => { - if (!event) return void 0; - return (event.ts - timeOriginTs) / 1e3; - }, "getTiming"); - return { - lcpTiming: getTiming(lastLcpCandidate), - fcpTiming: getTiming(fcpEvent) - }; -} -var init_metric_timings = __esm({ - "node_modules/lighthouse-plugin-soft-navigation/lib/metric-timings.js"() { - init_process_global(); - __name(computeMetricTimings, "computeMetricTimings"); - } -}); - -// node_modules/lighthouse-plugin-soft-navigation/audits/soft-nav-fcp.js -var soft_nav_fcp_exports = {}; -__export(soft_nav_fcp_exports, { - default: () => soft_nav_fcp_default -}); -var SoftNavFCP, soft_nav_fcp_default; -var init_soft_nav_fcp = __esm({ - "node_modules/lighthouse-plugin-soft-navigation/audits/soft-nav-fcp.js"() { - init_process_global(); - init_core2(); - init_processed_trace(); - init_metric_timings(); - SoftNavFCP = class extends Audit { - static { - __name(this, "SoftNavFCP"); - } - /** - * @return {AuditMeta} - */ - static get meta() { - return { - id: "soft-nav-fcp", - title: "Soft Navigation First Contentful Paint", - description: "First Contentful Paint of a soft navigation.", - scoreDisplayMode: Audit.SCORING_MODES.NUMERIC, - supportedModes: ["timespan"], - requiredArtifacts: ["Trace"] - }; - } - /** - * @param {import('lighthouse').Artifacts} artifacts - * @param {AuditContext} context - * @return {Promise} - */ - static async audit(artifacts, context) { - const trace = artifacts.Trace; - const processedTrace = await ProcessedTraceComputed.request(trace, context); - const { fcpTiming } = computeMetricTimings(processedTrace.mainThreadEvents); - if (!fcpTiming) { - return { - notApplicable: true, - score: 1 - }; - } - return { - numericValue: fcpTiming, - numericUnit: "millisecond", - displayValue: `${fcpTiming} ms`, - score: Audit.computeLogNormalScore({ - p10: 1800, - median: 3e3 - }, fcpTiming) - }; - } - }; - soft_nav_fcp_default = SoftNavFCP; - } -}); - -// node_modules/lighthouse-plugin-soft-navigation/audits/soft-nav-lcp.js -var soft_nav_lcp_exports = {}; -__export(soft_nav_lcp_exports, { - default: () => soft_nav_lcp_default -}); -var SoftNavLCP, soft_nav_lcp_default; -var init_soft_nav_lcp = __esm({ - "node_modules/lighthouse-plugin-soft-navigation/audits/soft-nav-lcp.js"() { - init_process_global(); - init_core2(); - init_processed_trace(); - init_metric_timings(); - SoftNavLCP = class extends Audit { - static { - __name(this, "SoftNavLCP"); - } - /** - * @return {AuditMeta} - */ - static get meta() { - return { - id: "soft-nav-lcp", - title: "Soft Navigation Largest Contentful Paint", - description: "Largest Contentful Paint of a soft navigation.", - scoreDisplayMode: Audit.SCORING_MODES.NUMERIC, - supportedModes: ["timespan"], - requiredArtifacts: ["Trace"] - }; - } - /** - * @param {import('lighthouse').Artifacts} artifacts - * @param {AuditContext} context - * @return {Promise} - */ - static async audit(artifacts, context) { - const trace = artifacts.Trace; - const processedTrace = await ProcessedTraceComputed.request(trace, context); - const { lcpTiming } = computeMetricTimings(processedTrace.mainThreadEvents); - if (!lcpTiming) { - return { - notApplicable: true, - score: 1 - }; - } - return { - numericValue: lcpTiming, - numericUnit: "millisecond", - displayValue: `${lcpTiming} ms`, - score: Audit.computeLogNormalScore({ - p10: 2500, - median: 4e3 - }, lcpTiming) - }; - } - }; - soft_nav_lcp_default = SoftNavLCP; - } -}); - // lh-gatherer-shim:/Users/alexrudenko/src/lighthouse/core/gather/gatherers/bf-cache-failures.js var bf_cache_failures_exports = {}; __export(bf_cache_failures_exports, { @@ -50363,199 +48350,2215 @@ var init_user_timings = __esm({ } }); -// core/config/config-helpers.js -import path4 from "path"; -function isBundledEnvironment2() { - if (global.isDevtools || global.isLightrider) return true; - try { - require4.resolve("lighthouse-logger"); - return false; - } catch (err) { - return true; +// replace-modules:/Users/alexrudenko/src/lighthouse/node_modules/@sentry/node/build/cjs/index.js +var cjs_exports = {}; +__export(cjs_exports, { + default: () => cjs_default +}); +var cjs_default; +var init_cjs = __esm({ + "replace-modules:/Users/alexrudenko/src/lighthouse/node_modules/@sentry/node/build/cjs/index.js"() { + init_process_global(); + cjs_default = {}; } -} -function _mergeConfigFragment(base, extension, overwriteArrays = false) { - if (typeof base === "undefined" || base === null) { - return extension; - } else if (typeof extension === "undefined") { - return base; - } else if (Array.isArray(extension)) { - if (overwriteArrays) return extension; - if (!Array.isArray(base)) throw new TypeError(`Expected array but got ${typeof base}`); - const merged = base.slice(); - extension.forEach((item) => { - if (!merged.some((candidate) => isEqual_default(candidate, item))) merged.push(item); - }); - return merged; - } else if (typeof extension === "object") { - if (typeof base !== "object") throw new TypeError(`Expected object but got ${typeof base}`); - if (Array.isArray(base)) throw new TypeError("Expected object but got Array"); - Object.keys(extension).forEach((key) => { - const localOverwriteArrays = overwriteArrays || key === "settings" && typeof base[key] === "object"; - base[key] = _mergeConfigFragment(base[key], extension[key], localOverwriteArrays); - }); - return base; +}); + +// clients/devtools-mcp/devtools-mcp-entry.js +init_process_global(); + +// core/index.js +init_process_global(); +init_trace(); + +// core/runner.js +init_process_global(); +init_lighthouse_logger(); +init_lodash(); +import path6 from "path"; + +// core/scoring.js +init_process_global(); +init_audit(); +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var clampTo2Decimals2 = /* @__PURE__ */ __name((val) => Math.round(val * 100) / 100, "clampTo2Decimals"); +var ReportScoring = class _ReportScoring { + static { + __name(this, "ReportScoring"); + } + /** + * Computes the weighted-average of the score of the list of items. + * @param {Array<{score: number|null, weight: number}>} items + * @return {number|null} + */ + static arithmeticMean(items) { + items = items.filter((item) => item.weight > 0); + if (items.some((item) => item.score === null)) return null; + const results = items.reduce( + (result, item) => { + const score = item.score; + const weight = item.weight; + return { + weight: result.weight + weight, + sum: result.sum + /** @type {number} */ + score * weight + }; + }, + { weight: 0, sum: 0 } + ); + return clampTo2Decimals2(results.sum / results.weight || 0); + } + /** + * Returns the report JSON object with computed scores. + * @param {Object} configCategories + * @param {Object>} resultsByAuditId + * @return {Object>} + */ + static scoreAllCategories(configCategories, resultsByAuditId) { + const scoredCategories = {}; + for (const [categoryId, configCategory] of Object.entries(configCategories)) { + const auditRefs = configCategory.auditRefs.map((configMember) => { + const member = { ...configMember }; + const result = resultsByAuditId[member.id]; + if (result.scoreDisplayMode === Audit.SCORING_MODES.NOT_APPLICABLE || result.scoreDisplayMode === Audit.SCORING_MODES.INFORMATIVE || result.scoreDisplayMode === Audit.SCORING_MODES.MANUAL) { + member.weight = 0; + } + return member; + }); + const scores = auditRefs.map((auditRef) => ({ + score: resultsByAuditId[auditRef.id].score, + weight: auditRef.weight + })); + const score = _ReportScoring.arithmeticMean(scores); + scoredCategories[categoryId] = { + ...configCategory, + auditRefs, + id: categoryId, + score + }; + } + return scoredCategories; } - return extension; -} -function mergeConfigFragmentArrayByKey(baseArray, extensionArray, keyFn) { - const itemsByKey = /* @__PURE__ */ new Map(); - const mergedArray = baseArray || []; - for (let i = 0; i < mergedArray.length; i++) { - const item = mergedArray[i]; - itemsByKey.set(keyFn(item), { index: i, item }); +}; + +// core/runner.js +init_audit(); +init_format(); + +// core/lib/stack-packs.js +init_process_global(); +init_lighthouse_logger(); +var import_lighthouse_stack_packs = __toESM(require_lighthouse_stack_packs(), 1); +init_i18n(); +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var stackPacksToInclude = [ + { + packId: "gatsby", + requiredStacks: ["js:gatsby"] + }, + { + packId: "wordpress", + requiredStacks: ["js:wordpress"] + }, + { + packId: "wix", + requiredStacks: ["js:wix"] + }, + { + packId: "wp-rocket", + requiredStacks: ["js:wp-rocket"] + }, + { + packId: "ezoic", + requiredStacks: ["js:ezoic"] + }, + { + packId: "drupal", + requiredStacks: ["js:drupal"] + }, + { + packId: "nitropack", + requiredStacks: ["js:nitropack"] + }, + { + packId: "amp", + requiredStacks: ["js:amp"] + }, + { + packId: "magento", + requiredStacks: ["js:magento"] + }, + { + packId: "octobercms", + requiredStacks: ["js:octobercms"] + }, + { + packId: "joomla", + requiredStacks: ["js:joomla"] + }, + { + packId: "next.js", + requiredStacks: ["js:next"] + }, + { + packId: "nuxt", + requiredStacks: ["js:nuxt"] + }, + { + packId: "angular", + requiredStacks: ["js:angular"] + }, + { + packId: "react", + requiredStacks: ["js:react"] } - for (const item of extensionArray || []) { - const baseItemEntry = itemsByKey.get(keyFn(item)); - if (baseItemEntry) { - const baseItem = baseItemEntry.item; - const merged = typeof item === "object" && typeof baseItem === "object" ? mergeConfigFragment(baseItem, item, true) : item; - mergedArray[baseItemEntry.index] = merged; - } else { - mergedArray.push(item); +]; +function getStackPacks(pageStacks) { + if (!pageStacks) return []; + const packs = []; + for (const pageStack of pageStacks) { + const stackPackToIncl = stackPacksToInclude.find((stackPackToIncl2) => stackPackToIncl2.requiredStacks.includes(`${pageStack.detector}:${pageStack.id}`)); + if (!stackPackToIncl) { + continue; + } + const matchedPack = import_lighthouse_stack_packs.default.find((pack) => pack.id === stackPackToIncl.packId); + if (!matchedPack) { + lighthouse_logger_default.warn( + "StackPacks", + `'${stackPackToIncl.packId}' stack pack was matched but is not found in stack-packs lib` + ); + continue; + } + const str_105 = createIcuMessageFn( + `node_modules/lighthouse-stack-packs/packs/${matchedPack.id}.js`, + matchedPack.UIStrings + ); + const descriptions = {}; + const UIStrings125 = matchedPack.UIStrings; + for (const key in UIStrings125) { + if (UIStrings125[key]) { + descriptions[key] = str_105(UIStrings125[key]); + } } + packs.push({ + id: matchedPack.id, + title: matchedPack.title, + iconDataURL: matchedPack.icon, + descriptions + }); } - return mergedArray; + return packs.sort((a, b) => { + const aVal = stackPacksToInclude.findIndex((p) => p.packId === a.id); + const bVal = stackPacksToInclude.findIndex((p) => p.packId === b.id); + return aVal - bVal; + }); } -function expandGathererShorthand(gatherer) { - if (typeof gatherer === "string") { - return { path: gatherer }; - } else if ("implementation" in gatherer || "instance" in gatherer) { - return gatherer; - } else if ("path" in gatherer) { - if (typeof gatherer.path !== "string") { - throw new Error("Invalid Gatherer type " + JSON.stringify(gatherer)); +__name(getStackPacks, "getStackPacks"); + +// core/lib/asset-saver.js +init_process_global(); +init_url(); +init_lighthouse_logger(); +init_lantern2(); +import fs from "fs"; +import path3 from "path"; +import stream from "stream"; +import { createGzip, gunzipSync } from "zlib"; + +// core/lib/lantern-trace-saver.js +init_process_global(); +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +// core/lib/traces/metric-trace-events.js +init_process_global(); +init_lighthouse_logger(); +init_trace_processor(); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +// core/computed/network-analysis.js +init_process_global(); +init_lighthouse_logger(); +init_lantern2(); +init_computed_artifact(); +init_network_records(); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var NetworkAnalysis = class { + static { + __name(this, "NetworkAnalysis"); + } + /** + * @param {LH.DevtoolsLog} devtoolsLog + * @param {LH.Artifacts.ComputedContext} context + * @return {Promise} + */ + static async compute_(devtoolsLog, context) { + const records = await NetworkRecordsComputed.request(devtoolsLog, context); + const analysis = core_exports.NetworkAnalyzer.analyze(records); + if (!analysis) { + lighthouse_logger_default.error("NetworkAnalysis", "Network analysis failed due to lack of transfer data"); + return { + throughput: 0, + rtt: Number.POSITIVE_INFINITY, + additionalRttByOrigin: /* @__PURE__ */ new Map(), + serverResponseTimeByOrigin: /* @__PURE__ */ new Map() + }; } - return gatherer; - } else if (typeof gatherer === "function") { - return { implementation: gatherer }; - } else if (gatherer && typeof gatherer.getArtifact === "function") { - return { instance: gatherer }; - } else { - throw new Error("Invalid Gatherer type " + JSON.stringify(gatherer)); + return analysis; } -} -function expandAuditShorthand(audit) { - if (typeof audit === "string") { - return { path: audit, options: {} }; - } else if ("implementation" in audit && typeof audit.implementation.audit === "function") { - return audit; - } else if ("path" in audit && typeof audit.path === "string") { - return audit; - } else if ("audit" in audit && typeof audit.audit === "function") { - return { implementation: audit, options: {} }; +}; +var NetworkAnalysisComputed = makeComputedArtifact(NetworkAnalysis, null); + +// core/computed/load-simulator.js +init_process_global(); +init_computed_artifact(); +init_lantern2(); +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var LoadSimulator = class { + static { + __name(this, "LoadSimulator"); + } + /** + * @param {{devtoolsLog: LH.DevtoolsLog, settings: LH.Audit.Context['settings']}} data + * @param {LH.Artifacts.ComputedContext} context + * @return {Promise} + */ + static async compute_(data31, context) { + const networkAnalysis = await NetworkAnalysisComputed.request(data31.devtoolsLog, context); + return simulation_exports.Simulator.createSimulator({ ...data31.settings, networkAnalysis }); + } + /** + * @param {LH.Artifacts.NetworkAnalysis} networkAnalysis + * @return {LH.PrecomputedLanternData} + */ + static convertAnalysisToSaveableLanternData(networkAnalysis) { + const lanternData = { additionalRttByOrigin: {}, serverResponseTimeByOrigin: {} }; + for (const [origin, value] of networkAnalysis.additionalRttByOrigin.entries()) { + if (origin.startsWith("http")) lanternData.additionalRttByOrigin[origin] = value; + } + for (const [origin, value] of networkAnalysis.serverResponseTimeByOrigin.entries()) { + if (origin.startsWith("http")) lanternData.serverResponseTimeByOrigin[origin] = value; + } + return lanternData; + } +}; +var LoadSimulatorComputed = makeComputedArtifact(LoadSimulator, ["devtoolsLog", "settings"]); + +// core/lib/asset-saver.js +init_lh_error(); +init_root2(); +/** + * @license + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var artifactsFilename = "artifacts.json"; +var traceFilename = "trace.json"; +var devtoolsFilename = "devtoolslog.json"; +var errorPrefix = "pageLoadError."; +async function writeJson(contents, path7, gzip) { + const writeStream = fs.createWriteStream(gzip ? path7 + ".gz" : path7); + if (gzip) { + await stream.promises.pipeline(contents, createGzip(), writeStream); } else { - throw new Error("Invalid Audit type " + JSON.stringify(audit)); + await stream.promises.pipeline(contents, writeStream); } } -async function requireWrapper(requirePath) { - if (path4.isAbsolute(requirePath)) { - requirePath = url_default.pathToFileURL(requirePath).href; +__name(writeJson, "writeJson"); +function readJson(filename, reviver) { + if (fs.existsSync(filename + ".gz")) { + filename = filename + ".gz"; } - let module2; - if (bundledModules.has(requirePath)) { - module2 = await bundledModules.get(requirePath); - } else if (requirePath.match(/\.(js|mjs|cjs)$/)) { - module2 = await import(requirePath); - } else { - requirePath += ".js"; - module2 = await import(requirePath); + if (!filename.endsWith(".json.gz")) { + return JSON.parse(fs.readFileSync(filename, "utf8"), reviver); } - if (module2.default) return module2.default; - const methods = /* @__PURE__ */ new Set(["meta"]); - const possibleNamedExports = Object.keys(module2).filter((key) => { - if (!(module2[key] && module2[key] instanceof Object)) return false; - return Object.getOwnPropertyNames(module2[key]).some((method) => methods.has(method)); + const buffer = gunzipSync(fs.readFileSync(filename)); + return JSON.parse(buffer.toString("utf8"), reviver); +} +__name(readJson, "readJson"); +function endsWithSuffix(filename, suffix) { + return filename.endsWith(suffix) || filename.endsWith(suffix + ".gz"); +} +__name(endsWithSuffix, "endsWithSuffix"); +function loadArtifacts(basePath) { + lighthouse_logger_default.log("Reading artifacts from disk:", basePath); + if (!fs.existsSync(basePath)) { + throw new Error("No saved artifacts found at " + basePath); + } + const artifacts = readJson(path3.join(basePath, artifactsFilename), LighthouseError.parseReviver); + const filenames = fs.readdirSync(basePath); + filenames.filter((f) => endsWithSuffix(f, devtoolsFilename)).forEach((filename) => { + const devtoolsLog = readJson(path3.join(basePath, filename)); + if (filename.startsWith(devtoolsFilename)) { + artifacts.DevtoolsLog = devtoolsLog; + } else if (filename.startsWith(errorPrefix)) { + artifacts.DevtoolsLogError = devtoolsLog; + } }); - if (possibleNamedExports.length === 1) return possibleNamedExports[0]; - if (possibleNamedExports.length > 1) { - throw new Error(`module '${requirePath}' has too many possible exports`); + filenames.filter((f) => endsWithSuffix(f, traceFilename)).forEach((filename) => { + let trace = readJson(path3.join(basePath, filename)); + if (Array.isArray(trace)) { + trace = { traceEvents: trace }; + } + if (filename.startsWith(traceFilename)) { + artifacts.Trace = trace; + } else if (filename.startsWith(errorPrefix)) { + artifacts.TraceError = trace; + } + }); + if (Array.isArray(artifacts.Timing)) { + artifacts.Timing.forEach((entry) => entry.gather = true); } - throw new Error(`module '${requirePath}' missing default export`); + return artifacts; } -async function requireGatherer(gathererPath, coreGathererList, configDir) { - const coreGatherer = coreGathererList.find((a) => a === `${gathererPath}.js`); - let requirePath = `../gather/gatherers/${gathererPath}`; - if (!coreGatherer) { - requirePath = resolveModulePath(gathererPath, configDir, "gatherer"); +__name(loadArtifacts, "loadArtifacts"); +function stringifyReplacer(key, value) { + if (value instanceof Error) { + return LighthouseError.stringifyReplacer(value); } - const GathererClass = ( - /** @type {GathererConstructor} */ - await requireWrapper(requirePath) - ); - return { - instance: new GathererClass(), - implementation: GathererClass, - path: gathererPath - }; + return value; } -function requireAudit(auditPath, coreAuditList, configDir) { - const auditPathJs = `${auditPath}.js`; - const coreAudit = coreAuditList.find((a) => a === auditPathJs); - let requirePath = `../audits/${auditPath}`; - if (!coreAudit) { - if (isBundledEnvironment2()) { - requirePath = auditPath; - } else { - const absolutePath = resolveModulePath(auditPath, configDir, "audit"); - if (isBundledEnvironment2()) { - requirePath = path4.relative("", absolutePath); - } else { - requirePath = absolutePath; - } +__name(stringifyReplacer, "stringifyReplacer"); +async function saveArtifacts(artifacts, basePath, options = {}) { + const status = { msg: "Saving artifacts", id: "lh:assetSaver:saveArtifacts" }; + lighthouse_logger_default.time(status); + fs.mkdirSync(basePath, { recursive: true }); + const filenames = fs.readdirSync(basePath); + for (const filename of filenames) { + const isPreviousFile = filename.endsWith(traceFilename) || filename.endsWith(devtoolsFilename) || filename.endsWith(traceFilename + ".gz") || filename.endsWith(devtoolsFilename + ".gz") || filename === artifactsFilename || filename === artifactsFilename + ".gz"; + if (isPreviousFile) { + fs.unlinkSync(`${basePath}/${filename}`); } } - return requireWrapper(requirePath); + const { + DevtoolsLog: DevtoolsLog2, + Trace, + DevtoolsLogError, + TraceError, + ...restArtifacts + } = artifacts; + if (Trace) { + await saveTrace(Trace, `${basePath}/${traceFilename}`, options); + } + if (TraceError) { + await saveTrace(TraceError, `${basePath}/${errorPrefix}${traceFilename}`, options); + } + if (DevtoolsLog2) { + await saveDevtoolsLog( + DevtoolsLog2, + `${basePath}/${devtoolsFilename}`, + options + ); + } + if (DevtoolsLogError) { + await saveDevtoolsLog( + DevtoolsLogError, + `${basePath}/${errorPrefix}${devtoolsFilename}`, + options + ); + } + const restArtifactsString = JSON.stringify(restArtifacts, stringifyReplacer, 2); + await writeJson(function* () { + yield restArtifactsString; + yield "\n"; + }, `${basePath}/${artifactsFilename}`, !!options.gzip); + lighthouse_logger_default.log("Artifacts saved to disk in folder:", basePath); + lighthouse_logger_default.timeEnd(status); } -function cleanFlagsForSettings(flags = {}) { - const settings = {}; - for (const key of Object.keys(flags)) { - if (key in defaultSettings) { - settings[key] = flags[key]; +__name(saveArtifacts, "saveArtifacts"); +function saveLhr(lhr, basePath) { + fs.writeFileSync(`${basePath}/lhr.report.json`, JSON.stringify(lhr, null, 2)); +} +__name(saveLhr, "saveLhr"); +function* arrayOfObjectsJsonGenerator(arrayOfObjects) { + const ITEMS_PER_ITERATION = 500; + yield "[\n"; + if (arrayOfObjects.length > 0) { + const itemsIterator = arrayOfObjects[Symbol.iterator](); + const firstItem = itemsIterator.next().value; + yield ` ${JSON.stringify(firstItem)}`; + let itemsRemaining = ITEMS_PER_ITERATION; + let itemsJSON = ""; + for (const item of itemsIterator) { + itemsJSON += `, + ${JSON.stringify(item)}`; + itemsRemaining--; + if (itemsRemaining === 0) { + yield itemsJSON; + itemsRemaining = ITEMS_PER_ITERATION; + itemsJSON = ""; + } } + yield itemsJSON; } - return settings; + yield "\n]"; } -function resolveSettings(settingsJson = {}, overrides = void 0) { - const locale = lookupLocale(overrides?.locale || settingsJson.locale); - const { defaultSettings: defaultSettings2 } = constants_exports; - const settingWithDefaults = mergeConfigFragment(deepClone(defaultSettings2), settingsJson, true); - const settingsWithFlags = mergeConfigFragment( - settingWithDefaults, - cleanFlagsForSettings(overrides), - true - ); - settingsWithFlags.locale = locale; - if (settingsWithFlags.emulatedUserAgent === true) { - settingsWithFlags.emulatedUserAgent = userAgents[settingsWithFlags.formFactor]; +__name(arrayOfObjectsJsonGenerator, "arrayOfObjectsJsonGenerator"); +function* traceJsonGenerator(traceData) { + const { traceEvents, ...rest } = traceData; + yield "{\n"; + yield '"traceEvents": '; + yield* arrayOfObjectsJsonGenerator(traceEvents); + for (const [key, value] of Object.entries(rest)) { + yield `, +"${key}": ${JSON.stringify(value, null, 2)}`; } - assertValidSettings(settingsWithFlags); - return settingsWithFlags; + yield "}\n"; } -async function mergePlugins(config3, configDir, flags) { - const configPlugins = config3.plugins || []; - const flagPlugins = flags?.plugins || []; - const pluginNames = /* @__PURE__ */ new Set([...configPlugins, ...flagPlugins]); - for (const pluginName of pluginNames) { - assertValidPluginName(config3, pluginName); - const pluginPath = isBundledEnvironment2() ? pluginName : resolveModulePath(pluginName, configDir, "plugin"); - const rawPluginJson = await requireWrapper(pluginPath); - const pluginJson = config_plugin_default.parsePlugin(rawPluginJson, pluginName); - config3 = mergeConfigFragment(config3, pluginJson); - } - return config3; +__name(traceJsonGenerator, "traceJsonGenerator"); +function saveTrace(traceData, traceFilename2, options = {}) { + const traceIter = traceJsonGenerator(traceData); + return writeJson(traceIter, traceFilename2, !!options.gzip); } -async function resolveGathererToDefn(gathererJson, coreGathererList, configDir) { - const gathererDefn = expandGathererShorthand(gathererJson); - if (gathererDefn.instance) { - return { - instance: gathererDefn.instance, - implementation: gathererDefn.implementation, - path: gathererDefn.path - }; - } else if (gathererDefn.implementation) { - const GathererClass = gathererDefn.implementation; - return { +__name(saveTrace, "saveTrace"); +function saveDevtoolsLog(devtoolsLog, devtoolLogFilename, options = {}) { + return writeJson(function* () { + yield* arrayOfObjectsJsonGenerator(devtoolsLog); + yield "\n"; + }, devtoolLogFilename, !!options.gzip); +} +__name(saveDevtoolsLog, "saveDevtoolsLog"); + +// core/lib/sentry.js +init_process_global(); +init_lighthouse_logger(); + +// core/config/config.js +init_process_global(); +init_lighthouse_logger(); +import path5 from "path"; + +// core/config/default-config.js +init_process_global(); +init_lh(); + +// core/config/constants.js +var constants_exports = {}; +__export(constants_exports, { + defaultSettings: () => defaultSettings, + nonSimulatedSettingsOverrides: () => nonSimulatedSettingsOverrides, + screenEmulationMetrics: () => screenEmulationMetrics, + throttling: () => throttling2, + userAgents: () => userAgents +}); +init_process_global(); +init_lantern2(); +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var throttling2 = simulation_exports.Constants.throttling; +var MOTOGPOWER_EMULATION_METRICS = { + mobile: true, + width: 412, + height: 823, + // This value has some interesting ramifications for image-size-responsive, see: + // https://github.com/GoogleChrome/lighthouse/issues/10741#issuecomment-626903508 + deviceScaleFactor: 1.75, + disabled: false +}; +var DESKTOP_EMULATION_METRICS = { + mobile: false, + width: 1350, + height: 940, + deviceScaleFactor: 1, + disabled: false +}; +var screenEmulationMetrics = { + mobile: MOTOGPOWER_EMULATION_METRICS, + desktop: DESKTOP_EMULATION_METRICS +}; +var MOTOG4_USERAGENT = "Mozilla/5.0 (Linux; Android 11; moto g power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Mobile Safari/537.36"; +var DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"; +var userAgents = { + mobile: MOTOG4_USERAGENT, + desktop: DESKTOP_USERAGENT +}; +var defaultSettings = { + output: "json", + maxWaitForFcp: 30 * 1e3, + maxWaitForLoad: 45 * 1e3, + pauseAfterFcpMs: 1e3, + pauseAfterLoadMs: 1e3, + networkQuietThresholdMs: 1e3, + cpuQuietThresholdMs: 1e3, + formFactor: "mobile", + throttling: throttling2.mobileSlow4G, + throttlingMethod: "simulate", + screenEmulation: screenEmulationMetrics.mobile, + emulatedUserAgent: userAgents.mobile, + auditMode: false, + gatherMode: false, + clearStorageTypes: ["file_systems", "shader_cache", "service_workers", "cache_storage"], + disableStorageReset: false, + debugNavigation: false, + channel: "node", + usePassiveGathering: false, + disableFullPageScreenshot: false, + skipAboutBlank: false, + blankPage: "about:blank", + ignoreStatusCode: false, + // the following settings have no defaults but we still want ensure that `key in settings` + // in config will work in a typechecked way + locale: "en-US", + // actual default determined by Config using lib/i18n + blockedUrlPatterns: null, + additionalTraceCategories: null, + extraHeaders: null, + precomputedLanternData: null, + onlyAudits: null, + onlyCategories: null, + skipAudits: null +}; +var nonSimulatedSettingsOverrides = { + pauseAfterFcpMs: 5250, + pauseAfterLoadMs: 5250, + networkQuietThresholdMs: 5250, + cpuQuietThresholdMs: 5250 +}; + +// core/config/default-config.js +init_i18n(); +/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var UIStrings21 = { + /** Title of the Performance category of audits. Equivalent to 'Web performance', this term is inclusive of all web page speed and loading optimization topics. Also used as a label of a score gauge; try to limit to 20 characters. */ + performanceCategoryTitle: "Performance", + /** Title of the speed metrics section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. */ + metricGroupTitle: "Metrics", + /** Title of the insights section of the Performance category. Within this section are various insights to give developers tips on how to improve the performance of their page. */ + insightsGroupTitle: "Insights", + /** Description of the insights section of the Performance category. Within this section are various insights to give developers tips on how to improve the performance of their page. */ + insightsGroupDescription: "These insights are also available in the Chrome DevTools Performance Panel - [record a trace](https://developer.chrome.com/docs/devtools/performance/reference) to view more detailed information.", + /** Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage. */ + firstPaintImprovementsGroupTitle: "First Paint Improvements", + /** Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage. */ + firstPaintImprovementsGroupDescription: "The most critical aspect of performance is how quickly pixels are rendered onscreen. Key metrics: First Contentful Paint, First Meaningful Paint", + /** Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the overall loading performance of their web page. */ + overallImprovementsGroupTitle: "Overall Improvements", + /** Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the overall loading performance of their web page. */ + overallImprovementsGroupDescription: "Enhance the overall loading experience, so the page is responsive and ready to use as soon as possible. Key metrics: Time to Interactive, Speed Index", + /** Title of the diagnostics section of the Performance category. Within this section are audits with non-imperative titles that provide more detail on the page's page load performance characteristics. Whereas the 'Opportunities' suggest an action along with expected time savings, diagnostics do not. Within this section, the user may read the details and deduce additional actions they could take. */ + diagnosticsGroupTitle: "Diagnostics", + /** Description of the diagnostics section of the Performance category. Within this section are audits with non-imperative titles that provide more detail on a web page's load performance characteristics. Within this section, the user may read the details and deduce additional actions they could take to improve performance. */ + diagnosticsGroupDescription: "More information about the performance of your application. These numbers don't [directly affect](https://developer.chrome.com/docs/lighthouse/performance/performance-scoring/) the Performance score.", + /** Title of the Accessibility category of audits. This section contains audits focused on making web content accessible to all users. Also used as a label of a score gauge; try to limit to 20 characters. */ + a11yCategoryTitle: "Accessibility", + /** Description of the Accessibility category. This is displayed at the top of a list of audits focused on making web content accessible to all users. No character length limits. 'improve the accessibility of your web app' and 'manual testing' become link texts to additional documentation. */ + a11yCategoryDescription: "These checks highlight opportunities to [improve the accessibility of your web app](https://developer.chrome.com/docs/lighthouse/accessibility/). Automatic detection can only detect a subset of issues and does not guarantee the accessibility of your web app, so [manual testing](https://web.dev/articles/how-to-review) is also encouraged.", + /** Description of the Accessibility manual checks category. This description is displayed above a list of accessibility audits that currently have no automated test and so must be verified manually by the user. No character length limits. 'conducting an accessibility review' becomes link text to additional documentation. */ + a11yCategoryManualDescription: "These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://web.dev/articles/how-to-review).", + /** Title of the best practices section of the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices. */ + a11yBestPracticesGroupTitle: "Best practices", + /** Description of the best practices section within the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices. */ + a11yBestPracticesGroupDescription: "These items highlight common accessibility best practices.", + /** Title of the color contrast section within the Accessibility category. Within this section are audits with descriptive titles that highlight the color and vision aspects of the page's accessibility that are passing or failing. */ + a11yColorContrastGroupTitle: "Contrast", + /** Description of the color contrast section within the Accessibility category. Within this section are audits with descriptive titles that highlight the color and vision aspects of the page's accessibility that are passing or failing. */ + a11yColorContrastGroupDescription: "These are opportunities to improve the legibility of your content.", + /** Title of the HTML element naming section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the non-textual HTML elements on the page have names discernible by a screen reader. */ + a11yNamesLabelsGroupTitle: "Names and labels", + /** Description of the HTML element naming section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the non-textual HTML elements on the page have names discernible by a screen reader. */ + a11yNamesLabelsGroupDescription: "These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader.", + /** Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve keyboard navigation. */ + a11yNavigationGroupTitle: "Navigation", + /** Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve keyboard navigation. */ + a11yNavigationGroupDescription: "These are opportunities to improve keyboard navigation in your application.", + /** Title of the ARIA validity section within the Accessibility category. Within this section are audits with descriptive titles that highlight if whether all the aria-* HTML attributes have been used properly. */ + a11yAriaGroupTitle: "ARIA", + /** Description of the ARIA validity section within the Accessibility category. Within this section are audits with descriptive titles that highlight if whether all the aria-* HTML attributes have been used properly. */ + a11yAriaGroupDescription: "These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader.", + /** Title of the language section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the language has been annotated in the correct HTML attributes on the page. */ + a11yLanguageGroupTitle: "Internationalization and localization", + /** Description of the language section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the language has been annotated in the correct HTML attributes on the page. */ + a11yLanguageGroupDescription: "These are opportunities to improve the interpretation of your content by users in different locales.", + /** Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to provide alternative content for audio and video. */ + a11yAudioVideoGroupTitle: "Audio and video", + /** Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to provide alternative content for audio and video. */ + a11yAudioVideoGroupDescription: "These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments.", + /** Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve the experience of reading tabular or list data using assistive technology. */ + a11yTablesListsVideoGroupTitle: "Tables and lists", + /** Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve the experience of reading tabular or list data using assistive technology. */ + a11yTablesListsVideoGroupDescription: "These are opportunities to improve the experience of reading tabular or list data using assistive technology, like a screen reader.", + /** Title of the Search Engine Optimization (SEO) category of audits. This is displayed at the top of a list of audits focused on topics related to optimizing a website for indexing by search engines. Also used as a label of a score gauge; try to limit to 20 characters. */ + seoCategoryTitle: "SEO", + /** Description of the Search Engine Optimization (SEO) category. This is displayed at the top of a list of audits focused on optimizing a website for indexing by search engines. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */ + seoCategoryDescription: "These checks ensure that your page is following basic search engine optimization advice. There are many additional factors Lighthouse does not score here that may affect your search ranking, including performance on [Core Web Vitals](https://web.dev/explore/vitals). [Learn more about Google Search Essentials](https://support.google.com/webmasters/answer/35769).", + /** Description of the Search Engine Optimization (SEO) manual checks category, the additional validators must be run by hand in order to check all SEO best practices. This is displayed at the top of a list of manually run audits focused on optimizing a website for indexing by search engines. No character length limits. */ + seoCategoryManualDescription: "Run these additional validators on your site to check additional SEO best practices.", + /** Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight opportunities to make a page more usable on mobile devices. */ + seoMobileGroupTitle: "Mobile Friendly", + /** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight opportunities to make a page more usable on mobile devices. */ + seoMobileGroupDescription: "Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn how to make pages mobile-friendly](https://developers.google.com/search/mobile-sites/).", + /** Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website content more easily understood by search engine crawler bots. */ + seoContentGroupTitle: "Content Best Practices", + /** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website content more easily understood by search engine crawler bots. */ + seoContentGroupDescription: "Format your HTML in a way that enables crawlers to better understand your app’s content.", + /** Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers. */ + seoCrawlingGroupTitle: "Crawling and Indexing", + /** Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers. */ + seoCrawlingGroupDescription: "To appear in search results, crawlers need access to your app.", + /** Title of the Best Practices category of audits. This is displayed at the top of a list of audits focused on topics related to following web development best practices and accepted guidelines. Also used as a label of a score gauge; try to limit to 20 characters. */ + bestPracticesCategoryTitle: "Best Practices", + /** Title of the Trust & Safety group of audits. This is displayed at the top of a list of audits focused on maintaining user trust and protecting security in web development. */ + bestPracticesTrustSafetyGroupTitle: "Trust and Safety", + /** Title of the User Experience group of the Best Practices category. Within this section are the audits related to the end user's experience of the webpage. */ + bestPracticesUXGroupTitle: "User Experience", + /** Title of the Browser Compatibility group of the Best Practices category. Within this section are the audits related to whether the page is interpreted consistently by browsers. */ + bestPracticesBrowserCompatGroupTitle: "Browser Compatibility", + /** Title of the General group of the Best Practices category. Within this section are the audits that don't belong to a specific group but are of general interest. */ + bestPracticesGeneralGroupTitle: "General" +}; +var str_2 = createIcuMessageFn({ url: "core/config/default-config.js" }.url, UIStrings21); +var defaultConfig = { + settings: defaultSettings, + artifacts: [ + // Artifacts which can be depended on come first. + { id: "DevtoolsLog", gatherer: "devtools-log" }, + { id: "Trace", gatherer: "trace" }, + { id: "Accessibility", gatherer: "accessibility" }, + { id: "AnchorElements", gatherer: "anchor-elements" }, + { id: "ConsoleMessages", gatherer: "console-messages" }, + { id: "CSSUsage", gatherer: "css-usage" }, + { id: "Doctype", gatherer: "dobetterweb/doctype" }, + { id: "Inputs", gatherer: "inputs" }, + { id: "IFrameElements", gatherer: "iframe-elements" }, + { id: "ImageElements", gatherer: "image-elements" }, + { id: "InspectorIssues", gatherer: "inspector-issues" }, + { id: "JsUsage", gatherer: "js-usage" }, + { id: "LinkElements", gatherer: "link-elements" }, + { id: "MainDocumentContent", gatherer: "main-document-content" }, + { id: "MetaElements", gatherer: "meta-elements" }, + { id: "NetworkUserAgent", gatherer: "network-user-agent" }, + { id: "RobotsTxt", gatherer: "seo/robots-txt" }, + { id: "Scripts", gatherer: "scripts" }, + { id: "SourceMaps", gatherer: "source-maps" }, + { id: "Stacks", gatherer: "stacks" }, + { id: "Stylesheets", gatherer: "stylesheets" }, + { id: "TraceElements", gatherer: "trace-elements" }, + { id: "ViewportDimensions", gatherer: "viewport-dimensions" }, + // FullPageScreenshot comes at the end so all other node analysis is captured. + { id: "FullPageScreenshot", gatherer: "full-page-screenshot" }, + // BFCacheFailures comes at the very end because it can perform a page navigation. + { id: "BFCacheFailures", gatherer: "bf-cache-failures" } + ], + audits: [ + "is-on-https", + "redirects-http", + "metrics/first-contentful-paint", + "metrics/largest-contentful-paint", + "metrics/speed-index", + "screenshot-thumbnails", + "final-screenshot", + "metrics/total-blocking-time", + "metrics/max-potential-fid", + "metrics/cumulative-layout-shift", + "metrics/interaction-to-next-paint", + "errors-in-console", + "server-response-time", + "metrics/interactive", + "user-timings", + "redirects", + "image-aspect-ratio", + "image-size-responsive", + "deprecations", + "third-party-cookies", + "mainthread-work-breakdown", + "bootup-time", + "diagnostics", + "network-requests", + "network-rtt", + "network-server-latency", + "main-thread-tasks", + "metrics", + "resource-summary", + "layout-shifts", + "long-tasks", + "non-composited-animations", + "unsized-images", + "valid-source-maps", + "csp-xss", + "has-hsts", + "origin-isolation", + "clickjacking-mitigation", + "trusted-types-xss", + "script-treemap-data", + "accessibility/accesskeys", + "accessibility/aria-allowed-attr", + "accessibility/aria-allowed-role", + "accessibility/aria-command-name", + "accessibility/aria-conditional-attr", + "accessibility/aria-deprecated-role", + "accessibility/aria-dialog-name", + "accessibility/aria-hidden-body", + "accessibility/aria-hidden-focus", + "accessibility/aria-input-field-name", + "accessibility/aria-meter-name", + "accessibility/aria-progressbar-name", + "accessibility/aria-prohibited-attr", + "accessibility/aria-required-attr", + "accessibility/aria-required-children", + "accessibility/aria-required-parent", + "accessibility/aria-roles", + "accessibility/aria-text", + "accessibility/aria-toggle-field-name", + "accessibility/aria-tooltip-name", + "accessibility/aria-treeitem-name", + "accessibility/aria-valid-attr-value", + "accessibility/aria-valid-attr", + "accessibility/button-name", + "accessibility/bypass", + "accessibility/color-contrast", + "accessibility/definition-list", + "accessibility/dlitem", + "accessibility/document-title", + "accessibility/duplicate-id-aria", + "accessibility/empty-heading", + "accessibility/form-field-multiple-labels", + "accessibility/frame-title", + "accessibility/heading-order", + "accessibility/html-has-lang", + "accessibility/html-lang-valid", + "accessibility/html-xml-lang-mismatch", + "accessibility/identical-links-same-purpose", + "accessibility/image-alt", + "accessibility/image-redundant-alt", + "accessibility/input-button-name", + "accessibility/input-image-alt", + "accessibility/label-content-name-mismatch", + "accessibility/label", + "accessibility/landmark-one-main", + "accessibility/link-name", + "accessibility/link-in-text-block", + "accessibility/list", + "accessibility/listitem", + "accessibility/meta-refresh", + "accessibility/meta-viewport", + "accessibility/object-alt", + "accessibility/select-name", + "accessibility/skip-link", + "accessibility/tabindex", + "accessibility/table-duplicate-name", + "accessibility/table-fake-caption", + "accessibility/target-size", + "accessibility/td-has-header", + "accessibility/td-headers-attr", + "accessibility/th-has-data-cells", + "accessibility/valid-lang", + "accessibility/video-caption", + "accessibility/manual/custom-controls-labels", + "accessibility/manual/custom-controls-roles", + "accessibility/manual/focus-traps", + "accessibility/manual/focusable-controls", + "accessibility/manual/interactive-element-affordance", + "accessibility/manual/logical-tab-order", + "accessibility/manual/managed-focus", + "accessibility/manual/offscreen-content-hidden", + "accessibility/manual/use-landmarks", + "accessibility/manual/visual-order-follows-dom", + "byte-efficiency/total-byte-weight", + "byte-efficiency/unminified-css", + "byte-efficiency/unminified-javascript", + "byte-efficiency/unused-css-rules", + "byte-efficiency/unused-javascript", + "dobetterweb/doctype", + "dobetterweb/charset", + "dobetterweb/geolocation-on-start", + "dobetterweb/inspector-issues", + "dobetterweb/js-libraries", + "dobetterweb/notification-on-start", + "dobetterweb/paste-preventing-inputs", + "seo/meta-description", + "seo/http-status-code", + "seo/link-text", + "seo/crawlable-anchors", + "seo/is-crawlable", + "seo/robots-txt", + "seo/hreflang", + "seo/canonical", + "seo/manual/structured-data", + "bf-cache", + "insights/cache-insight", + "insights/cls-culprits-insight", + "insights/document-latency-insight", + "insights/dom-size-insight", + "insights/duplicated-javascript-insight", + "insights/font-display-insight", + "insights/forced-reflow-insight", + "insights/image-delivery-insight", + "insights/inp-breakdown-insight", + "insights/lcp-breakdown-insight", + "insights/lcp-discovery-insight", + "insights/legacy-javascript-insight", + "insights/modern-http-insight", + "insights/network-dependency-tree-insight", + "insights/render-blocking-insight", + "insights/third-parties-insight", + "insights/viewport-insight" + ], + groups: { + "metrics": { + title: str_2(UIStrings21.metricGroupTitle) + }, + "insights": { + title: str_2(UIStrings21.insightsGroupTitle), + description: str_2(UIStrings21.insightsGroupDescription) + }, + "diagnostics": { + title: str_2(UIStrings21.diagnosticsGroupTitle), + description: str_2(UIStrings21.diagnosticsGroupDescription) + }, + "a11y-best-practices": { + title: str_2(UIStrings21.a11yBestPracticesGroupTitle), + description: str_2(UIStrings21.a11yBestPracticesGroupDescription) + }, + "a11y-color-contrast": { + title: str_2(UIStrings21.a11yColorContrastGroupTitle), + description: str_2(UIStrings21.a11yColorContrastGroupDescription) + }, + "a11y-names-labels": { + title: str_2(UIStrings21.a11yNamesLabelsGroupTitle), + description: str_2(UIStrings21.a11yNamesLabelsGroupDescription) + }, + "a11y-navigation": { + title: str_2(UIStrings21.a11yNavigationGroupTitle), + description: str_2(UIStrings21.a11yNavigationGroupDescription) + }, + "a11y-aria": { + title: str_2(UIStrings21.a11yAriaGroupTitle), + description: str_2(UIStrings21.a11yAriaGroupDescription) + }, + "a11y-language": { + title: str_2(UIStrings21.a11yLanguageGroupTitle), + description: str_2(UIStrings21.a11yLanguageGroupDescription) + }, + "a11y-audio-video": { + title: str_2(UIStrings21.a11yAudioVideoGroupTitle), + description: str_2(UIStrings21.a11yAudioVideoGroupDescription) + }, + "a11y-tables-lists": { + title: str_2(UIStrings21.a11yTablesListsVideoGroupTitle), + description: str_2(UIStrings21.a11yTablesListsVideoGroupDescription) + }, + "seo-mobile": { + title: str_2(UIStrings21.seoMobileGroupTitle), + description: str_2(UIStrings21.seoMobileGroupDescription) + }, + "seo-content": { + title: str_2(UIStrings21.seoContentGroupTitle), + description: str_2(UIStrings21.seoContentGroupDescription) + }, + "seo-crawl": { + title: str_2(UIStrings21.seoCrawlingGroupTitle), + description: str_2(UIStrings21.seoCrawlingGroupDescription) + }, + "best-practices-trust-safety": { + title: str_2(UIStrings21.bestPracticesTrustSafetyGroupTitle) + }, + "best-practices-ux": { + title: str_2(UIStrings21.bestPracticesUXGroupTitle) + }, + "best-practices-browser-compat": { + title: str_2(UIStrings21.bestPracticesBrowserCompatGroupTitle) + }, + "best-practices-general": { + title: str_2(UIStrings21.bestPracticesGeneralGroupTitle) + }, + // Group for audits that should not be displayed. + "hidden": { title: "" } + }, + categories: { + "performance": { + title: str_2(UIStrings21.performanceCategoryTitle), + supportedModes: ["navigation", "timespan", "snapshot"], + auditRefs: [ + { id: "first-contentful-paint", weight: 10, group: "metrics", acronym: "FCP" }, + { id: "largest-contentful-paint", weight: 25, group: "metrics", acronym: "LCP" }, + { id: "total-blocking-time", weight: 30, group: "metrics", acronym: "TBT" }, + { id: "cumulative-layout-shift", weight: 25, group: "metrics", acronym: "CLS" }, + { id: "speed-index", weight: 10, group: "metrics", acronym: "SI" }, + { id: "interaction-to-next-paint", weight: 0, group: "metrics", acronym: "INP" }, + // Insight audits. + { id: "cache-insight", weight: 0, group: "insights" }, + { id: "cls-culprits-insight", weight: 0, group: "insights" }, + { id: "document-latency-insight", weight: 0, group: "insights" }, + { id: "dom-size-insight", weight: 0, group: "insights" }, + { id: "duplicated-javascript-insight", weight: 0, group: "insights" }, + { id: "font-display-insight", weight: 0, group: "insights" }, + { id: "forced-reflow-insight", weight: 0, group: "insights" }, + { id: "image-delivery-insight", weight: 0, group: "insights" }, + { id: "inp-breakdown-insight", weight: 0, group: "insights" }, + { id: "lcp-breakdown-insight", weight: 0, group: "insights" }, + { id: "lcp-discovery-insight", weight: 0, group: "insights" }, + { id: "legacy-javascript-insight", weight: 0, group: "insights" }, + { id: "modern-http-insight", weight: 0, group: "insights" }, + { id: "network-dependency-tree-insight", weight: 0, group: "insights" }, + { id: "render-blocking-insight", weight: 0, group: "insights" }, + { id: "third-parties-insight", weight: 0, group: "insights" }, + { id: "viewport-insight", weight: 0, group: "insights" }, + // These are our "invisible" metrics. Not displayed, but still in the LHR. + { id: "interactive", weight: 0, group: "hidden", acronym: "TTI" }, + { id: "max-potential-fid", weight: 0, group: "hidden" }, + { id: "unminified-css", weight: 0, group: "diagnostics" }, + { id: "unminified-javascript", weight: 0, group: "diagnostics" }, + { id: "unused-css-rules", weight: 0, group: "diagnostics" }, + { id: "unused-javascript", weight: 0, group: "diagnostics" }, + { id: "total-byte-weight", weight: 0, group: "diagnostics" }, + { id: "user-timings", weight: 0, group: "diagnostics" }, + { id: "bootup-time", weight: 0, group: "diagnostics" }, + { id: "mainthread-work-breakdown", weight: 0, group: "diagnostics" }, + { id: "long-tasks", weight: 0, group: "diagnostics" }, + { id: "non-composited-animations", weight: 0, group: "diagnostics" }, + { id: "unsized-images", weight: 0, group: "diagnostics" }, + { id: "bf-cache", weight: 0, group: "diagnostics" }, + // Audits past this point contain useful data but are not displayed with other audits. + { id: "network-requests", weight: 0, group: "hidden" }, + { id: "network-rtt", weight: 0, group: "hidden" }, + { id: "network-server-latency", weight: 0, group: "hidden" }, + { id: "main-thread-tasks", weight: 0, group: "hidden" }, + { id: "diagnostics", weight: 0, group: "hidden" }, + { id: "metrics", weight: 0, group: "hidden" }, + { id: "screenshot-thumbnails", weight: 0, group: "hidden" }, + { id: "final-screenshot", weight: 0, group: "hidden" }, + { id: "script-treemap-data", weight: 0, group: "hidden" }, + { id: "resource-summary", weight: 0, group: "hidden" }, + { id: "redirects", weight: 0, group: "hidden" }, + { id: "server-response-time", weight: 0, group: "hidden" }, + { id: "layout-shifts", weight: 0, group: "hidden" } + ] + }, + "accessibility": { + title: str_2(UIStrings21.a11yCategoryTitle), + description: str_2(UIStrings21.a11yCategoryDescription), + manualDescription: str_2(UIStrings21.a11yCategoryManualDescription), + supportedModes: ["navigation", "snapshot"], + // Audit weights weights are derived from the axe-core "Impact", + // with adjustments based on axe-core "Tags": + // + // ┌────────────┬───────────────────────────────────────────────┐ + // │ Impact │ Weight Based on Tags │ + // │ ├──────────────┬─────────────────┬──────────────┤ + // │ │ wcag A+AA │ best-practice │ experimental │ + // │ │ (ex: wcag2aa)│ (w/o wcag tag) │ │ + // ├────────────┼──────────────┼─────────────────┼──────────────┤ + // │ Minor │ 1 │ 0 │ 0 │ + // │ Moderate │ 3 │ 3 │ 0 │ + // │ Serious │ 7 │ 7 │ 0 │ + // │ Critical │ 10 │ 10 │ 0 │ + // └────────────┴──────────────┴─────────────────┴──────────────┘ + // + // Notes: + // • Experimental rules always have weight 0 + // • Best practice rules only affect scores when tagged with wcagA+AA + // and are moderate, serious, or critical. + // + // To find the latest axe-core Impact and Tag values: + // 1. Browse to https://dequeuniversity.com/rules/axe/html. + // 2. Click on the latest rule set (ex: https://dequeuniversity.com/rules/axe/html/4.10) + // 3. Review the tables + auditRefs: [ + { id: "accesskeys", weight: 7, group: "a11y-navigation" }, + // Serious, best-practice + { id: "aria-allowed-attr", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-command-name", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-conditional-attr", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-deprecated-role", weight: 1, group: "a11y-aria" }, + // Minor, wcag2a + { id: "aria-dialog-name", weight: 7, group: "a11y-aria" }, + // Serious, best-practice + { id: "aria-hidden-body", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-hidden-focus", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-input-field-name", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-meter-name", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-progressbar-name", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-prohibited-attr", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-required-attr", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-required-children", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-required-parent", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-roles", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-text", weight: 7, group: "a11y-aria" }, + // Serious, best-practice + { id: "aria-toggle-field-name", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-tooltip-name", weight: 7, group: "a11y-aria" }, + // Serious, wcag2a + { id: "aria-treeitem-name", weight: 7, group: "a11y-aria" }, + // Serious, best-practice + { id: "aria-valid-attr-value", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "aria-valid-attr", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "button-name", weight: 10, group: "a11y-names-labels" }, + // Critical, wcag2a + { id: "bypass", weight: 7, group: "a11y-navigation" }, + // Serious, wcag2a + { id: "color-contrast", weight: 7, group: "a11y-color-contrast" }, + // Serious, wcag2aa + { id: "definition-list", weight: 7, group: "a11y-tables-lists" }, + // Serious, wcag2a + { id: "dlitem", weight: 7, group: "a11y-tables-lists" }, + // Serious, wcag2a + { id: "document-title", weight: 7, group: "a11y-names-labels" }, + // Serious, wcag2a + { id: "duplicate-id-aria", weight: 10, group: "a11y-aria" }, + // Critical, wcag2a + { id: "form-field-multiple-labels", weight: 3, group: "a11y-names-labels" }, + // Moderate, wcag2a + { id: "frame-title", weight: 7, group: "a11y-names-labels" }, + // Serious, wcag2a + { id: "heading-order", weight: 3, group: "a11y-navigation" }, + // Moderate, best-practice + { id: "html-has-lang", weight: 7, group: "a11y-language" }, + // Serious, wcag2a + { id: "html-lang-valid", weight: 7, group: "a11y-language" }, + // Serious, wcag2a + { id: "html-xml-lang-mismatch", weight: 3, group: "a11y-language" }, + // Moderate, wcag2a + { id: "image-alt", weight: 10, group: "a11y-names-labels" }, + // Critical, wcag2a + { id: "input-button-name", weight: 10, group: "a11y-names-labels" }, + // Critical, wcag2a + { id: "input-image-alt", weight: 10, group: "a11y-names-labels" }, + // Critical, wcag2a + { id: "label", weight: 10, group: "a11y-names-labels" }, + // Critical, wcag2a + { id: "link-in-text-block", weight: 7, group: "a11y-color-contrast" }, + // Serious, wcag2a + { id: "link-name", weight: 7, group: "a11y-names-labels" }, + // Serious, wcag2a + { id: "list", weight: 7, group: "a11y-tables-lists" }, + // Serious, wcag2a + { id: "listitem", weight: 7, group: "a11y-tables-lists" }, + // Serious, wcag2a + { id: "meta-refresh", weight: 10, group: "a11y-best-practices" }, + // Critical, wcag2a + { id: "meta-viewport", weight: 10, group: "a11y-best-practices" }, + // Critical, wcag2aa + { id: "object-alt", weight: 7, group: "a11y-names-labels" }, + // Serious, wcag2a + { id: "select-name", weight: 10, group: "a11y-names-labels" }, + // Critical, wcag2a + { id: "skip-link", weight: 3, group: "a11y-names-labels" }, + // Moderate, best-practice + { id: "tabindex", weight: 7, group: "a11y-navigation" }, + // Serious, best-practice + { id: "target-size", weight: 7, group: "a11y-best-practices" }, + // Serious, wcag22aa + { id: "td-headers-attr", weight: 7, group: "a11y-tables-lists" }, + // Serious, wcag2a + { id: "th-has-data-cells", weight: 7, group: "a11y-tables-lists" }, + // Serious, wcag2a + { id: "valid-lang", weight: 7, group: "a11y-language" }, + // Serious, wcag2aa + { id: "video-caption", weight: 10, group: "a11y-audio-video" }, + // Critical, wcag2a + { id: "landmark-one-main", weight: 3, group: "a11y-best-practices" }, + // Moderate, best-practice + // Manual audits + { id: "focusable-controls", weight: 0 }, + { id: "interactive-element-affordance", weight: 0 }, + { id: "logical-tab-order", weight: 0 }, + { id: "visual-order-follows-dom", weight: 0 }, + { id: "focus-traps", weight: 0 }, + { id: "managed-focus", weight: 0 }, + { id: "use-landmarks", weight: 0 }, + { id: "offscreen-content-hidden", weight: 0 }, + { id: "custom-controls-labels", weight: 0 }, + { id: "custom-controls-roles", weight: 0 }, + // Low-impact best-practices + { id: "table-duplicate-name", weight: 0, group: "a11y-best-practices" }, + // Minor, best-practice + { id: "empty-heading", weight: 0, group: "a11y-best-practices" }, + // Minor, best-practice + { id: "aria-allowed-role", weight: 0, group: "a11y-best-practices" }, + // Minor, best-practice + { id: "image-redundant-alt", weight: 0, group: "a11y-names-labels" }, + // Minor, best-practice + // WCAG AAA + { id: "identical-links-same-purpose", weight: 0, group: "a11y-best-practices" }, + // Minor, wcag2aaa + // Hidden audits (ie. experimental) + { id: "label-content-name-mismatch", weight: 0, group: "hidden" }, + // Serious, experimental + { id: "table-fake-caption", weight: 0, group: "hidden" }, + // Serious, experimental + { id: "td-has-header", weight: 0, group: "hidden" } + // Critical, experimental + ] + }, + "best-practices": { + title: str_2(UIStrings21.bestPracticesCategoryTitle), + supportedModes: ["navigation", "timespan", "snapshot"], + auditRefs: [ + // Trust & Safety + { id: "is-on-https", weight: 5, group: "best-practices-trust-safety" }, + { id: "redirects-http", weight: 1, group: "best-practices-trust-safety" }, + { id: "geolocation-on-start", weight: 1, group: "best-practices-trust-safety" }, + { id: "notification-on-start", weight: 1, group: "best-practices-trust-safety" }, + { id: "csp-xss", weight: 0, group: "best-practices-trust-safety" }, + { id: "has-hsts", weight: 0, group: "best-practices-trust-safety" }, + { id: "origin-isolation", weight: 0, group: "best-practices-trust-safety" }, + { id: "clickjacking-mitigation", weight: 0, group: "best-practices-trust-safety" }, + { id: "trusted-types-xss", weight: 0, group: "best-practices-trust-safety" }, + // User Experience + { id: "paste-preventing-inputs", weight: 3, group: "best-practices-ux" }, + { id: "image-aspect-ratio", weight: 1, group: "best-practices-ux" }, + { id: "image-size-responsive", weight: 1, group: "best-practices-ux" }, + // Browser Compatibility + { id: "doctype", weight: 1, group: "best-practices-browser-compat" }, + { id: "charset", weight: 1, group: "best-practices-browser-compat" }, + // General Group + { id: "js-libraries", weight: 0, group: "best-practices-general" }, + { id: "deprecations", weight: 5, group: "best-practices-general" }, + { id: "third-party-cookies", weight: 5, group: "best-practices-general" }, + { id: "errors-in-console", weight: 1, group: "best-practices-general" }, + { id: "valid-source-maps", weight: 0, group: "best-practices-general" }, + { id: "inspector-issues", weight: 1, group: "best-practices-general" } + ] + }, + "seo": { + title: str_2(UIStrings21.seoCategoryTitle), + description: str_2(UIStrings21.seoCategoryDescription), + manualDescription: str_2(UIStrings21.seoCategoryManualDescription), + supportedModes: ["navigation", "snapshot"], + auditRefs: [ + // Should be at least 31% of the score, such that this audit failing + // results in the SEO category failing. + // Solve for w: + // w / (w + T) >= 0.31 + // where T is the sum of all the other weights. + { id: "is-crawlable", weight: 93 / 23, group: "seo-crawl" }, + { id: "document-title", weight: 1, group: "seo-content" }, + { id: "meta-description", weight: 1, group: "seo-content" }, + { id: "http-status-code", weight: 1, group: "seo-crawl" }, + { id: "link-text", weight: 1, group: "seo-content" }, + { id: "crawlable-anchors", weight: 1, group: "seo-crawl" }, + { id: "robots-txt", weight: 1, group: "seo-crawl" }, + { id: "image-alt", weight: 1, group: "seo-content" }, + { id: "hreflang", weight: 1, group: "seo-content" }, + { id: "canonical", weight: 1, group: "seo-content" }, + // Manual audits + { id: "structured-data", weight: 0 } + ] + } + } +}; +Object.defineProperty(defaultConfig, "UIStrings", { + enumerable: false, + get: /* @__PURE__ */ __name(() => UIStrings21, "get") +}); +var default_config_default = defaultConfig; + +// core/config/validation.js +init_process_global(); +init_audit(); +init_base_gatherer(); +init_i18n(); +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function isValidArtifactDependency(dependent, dependency) { + const levels = { timespan: 0, snapshot: 1, navigation: 2 }; + const dependentLevel = Math.min(...dependent.instance.meta.supportedModes.map((l) => levels[l])); + const dependencyLevel = Math.min(...dependency.instance.meta.supportedModes.map((l) => levels[l])); + if (dependentLevel === levels.timespan) return dependencyLevel === levels.timespan; + if (dependentLevel === levels.snapshot) return dependencyLevel === levels.snapshot; + return true; +} +__name(isValidArtifactDependency, "isValidArtifactDependency"); +function assertValidPluginName(config3, pluginName) { + const parts = pluginName.split("/"); + if (parts.length === 2) { + pluginName = parts[1]; + } + if (!pluginName.startsWith("lighthouse-plugin-")) { + throw new Error(`plugin name '${pluginName}' does not start with 'lighthouse-plugin-'`); + } + if (config3.categories?.[pluginName]) { + throw new Error(`plugin name '${pluginName}' not allowed because it is the id of a category already found in config`); + } +} +__name(assertValidPluginName, "assertValidPluginName"); +function assertValidArtifact(artifactDefn) { + const gatherer = artifactDefn.gatherer.instance; + if (typeof gatherer.meta !== "object") { + throw new Error(`Gatherer for ${artifactDefn.id} did not provide a meta object.`); + } + if (gatherer.meta.supportedModes.length === 0) { + throw new Error(`Gatherer for ${artifactDefn.id} did not support any gather modes.`); + } + if (typeof gatherer.getArtifact !== "function" || gatherer.getArtifact === base_gatherer_default.prototype.getArtifact) { + throw new Error(`Gatherer for ${artifactDefn.id} did not define a "getArtifact" method.`); + } +} +__name(assertValidArtifact, "assertValidArtifact"); +function assertValidAudit(auditDefinition) { + const { implementation, path: auditPath } = auditDefinition; + const auditName = auditPath || implementation?.meta?.id || "Unknown audit"; + if (typeof implementation.audit !== "function" || implementation.audit === Audit.audit) { + throw new Error(`${auditName} has no audit() method.`); + } + if (typeof implementation.meta.id !== "string") { + throw new Error(`${auditName} has no meta.id property, or the property is not a string.`); + } + if (!isStringOrIcuMessage(implementation.meta.title)) { + throw new Error(`${auditName} has no meta.title property, or the property is not a string.`); + } + const scoreDisplayMode = implementation.meta.scoreDisplayMode || Audit.SCORING_MODES.BINARY; + if (!isStringOrIcuMessage(implementation.meta.failureTitle) && scoreDisplayMode === Audit.SCORING_MODES.BINARY) { + throw new Error(`${auditName} has no meta.failureTitle and should.`); + } + if (!isStringOrIcuMessage(implementation.meta.description)) { + throw new Error( + `${auditName} has no meta.description property, or the property is not a string.` + ); + } else if (implementation.meta.description === "") { + throw new Error( + `${auditName} has an empty meta.description string. Please add a description for the UI.` + ); + } + if (!Array.isArray(implementation.meta.requiredArtifacts)) { + throw new Error( + `${auditName} has no meta.requiredArtifacts property, or the property is not an array.` + ); + } +} +__name(assertValidAudit, "assertValidAudit"); +function assertValidCategories(categories, audits, groups) { + if (!categories) { + return; + } + const auditsKeyedById = new Map((audits || []).map((audit) => { + return [audit.implementation.meta.id, audit]; + })); + Object.keys(categories).forEach((categoryId) => { + categories[categoryId].auditRefs.forEach((auditRef, index) => { + if (!auditRef.id) { + throw new Error(`missing an audit id at ${categoryId}[${index}]`); + } + const audit = auditsKeyedById.get(auditRef.id); + if (!audit) { + throw new Error(`could not find ${auditRef.id} audit for category ${categoryId}`); + } + const auditImpl = audit.implementation; + const isManual = auditImpl.meta.scoreDisplayMode === "manual"; + if (categoryId === "accessibility" && !auditRef.group && !isManual) { + throw new Error(`${auditRef.id} accessibility audit does not have a group`); + } + if (auditRef.weight > 0 && isManual) { + throw new Error(`${auditRef.id} is manual but has a positive weight`); + } + if (auditRef.group && (!groups || !groups[auditRef.group])) { + throw new Error(`${auditRef.id} references unknown group ${auditRef.group}`); + } + }); + }); +} +__name(assertValidCategories, "assertValidCategories"); +function assertValidSettings(settings) { + if (!settings.formFactor) { + throw new Error(`\`settings.formFactor\` must be defined as 'mobile' or 'desktop'. See https://github.com/GoogleChrome/lighthouse/blob/main/docs/emulation.md`); + } + if (!settings.screenEmulation.disabled) { + if (settings.screenEmulation.mobile !== (settings.formFactor === "mobile")) { + throw new Error(`Screen emulation mobile setting (${settings.screenEmulation.mobile}) does not match formFactor setting (${settings.formFactor}). See https://github.com/GoogleChrome/lighthouse/blob/main/docs/emulation.md`); + } + } + const skippedAndOnlyAuditId = settings.skipAudits?.find((auditId) => settings.onlyAudits?.includes(auditId)); + if (skippedAndOnlyAuditId) { + throw new Error(`${skippedAndOnlyAuditId} appears in both skipAudits and onlyAudits`); + } +} +__name(assertValidSettings, "assertValidSettings"); +function assertValidArtifacts(artifactDefns) { + const availableArtifacts = /* @__PURE__ */ new Set(); + for (const artifact of artifactDefns) { + assertValidArtifact(artifact); + if (availableArtifacts.has(artifact.id)) { + throw new Error(`Config defined multiple artifacts with id '${artifact.id}'`); + } + availableArtifacts.add(artifact.id); + if (!artifact.dependencies) continue; + for (const [dependencyKey, { id: dependencyId }] of Object.entries(artifact.dependencies)) { + if (availableArtifacts.has(dependencyId)) continue; + throwInvalidDependencyOrder(artifact.id, dependencyKey); + } + } +} +__name(assertValidArtifacts, "assertValidArtifacts"); +function assertValidConfig(resolvedConfig) { + assertValidArtifacts(resolvedConfig.artifacts || []); + for (const auditDefn of resolvedConfig.audits || []) { + assertValidAudit(auditDefn); + } + assertValidCategories(resolvedConfig.categories, resolvedConfig.audits, resolvedConfig.groups); + assertValidSettings(resolvedConfig.settings); +} +__name(assertValidConfig, "assertValidConfig"); +function throwInvalidDependencyOrder(artifactId, dependencyKey) { + throw new Error( + [ + `Failed to find dependency "${dependencyKey}" for "${artifactId}" artifact`, + `Check that...`, + ` 1. A gatherer exposes a matching Symbol that satisfies "${dependencyKey}".`, + ` 2. "${dependencyKey}" is configured to run before "${artifactId}"` + ].join("\n") + ); +} +__name(throwInvalidDependencyOrder, "throwInvalidDependencyOrder"); +function throwInvalidArtifactDependency(artifactId, dependencyKey) { + throw new Error( + [ + `Dependency "${dependencyKey}" for "${artifactId}" artifact is invalid.`, + `The dependency must be collected before the dependent.` + ].join("\n") + ); +} +__name(throwInvalidArtifactDependency, "throwInvalidArtifactDependency"); + +// core/config/filters.js +init_process_global(); +init_audit(); +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var baseArtifactKeySource = { + fetchTime: "", + LighthouseRunWarnings: "", + BenchmarkIndex: "", + HostDPR: "", + settings: "", + Timing: "", + URL: "", + PageLoadError: "", + HostFormFactor: "", + HostUserAgent: "", + HostProduct: "", + GatherContext: "" +}; +var baseArtifactKeys = Object.keys(baseArtifactKeySource); +var filterResistantAuditIds = []; +var filterResistantArtifactIds = ["Stacks", "NetworkUserAgent", "FullPageScreenshot"]; +function getAuditIdsInCategories(allCategories, onlyCategories) { + if (!allCategories) return /* @__PURE__ */ new Set(); + onlyCategories = onlyCategories || Object.keys(allCategories); + const categories = onlyCategories.map((categoryId) => allCategories[categoryId]); + const auditRefs = categories.flatMap((category) => category?.auditRefs || []); + return new Set(auditRefs.map((auditRef) => auditRef.id)); +} +__name(getAuditIdsInCategories, "getAuditIdsInCategories"); +function filterArtifactsByAvailableAudits(artifacts, audits) { + if (!artifacts) return null; + if (!audits) return artifacts; + const artifactsById = new Map(artifacts.map((artifact) => [artifact.id, artifact])); + const artifactIdsToKeep = /* @__PURE__ */ new Set([ + ...filterResistantArtifactIds, + ...audits.flatMap((audit) => audit.implementation.meta.requiredArtifacts) + ]); + let previousSize = 0; + while (previousSize !== artifactIdsToKeep.size) { + previousSize = artifactIdsToKeep.size; + for (const artifactId of artifactIdsToKeep) { + const artifact = artifactsById.get(artifactId); + if (!artifact) continue; + if (!artifact.dependencies) continue; + for (const dep of Object.values(artifact.dependencies)) { + artifactIdsToKeep.add(dep.id); + } + } + } + return artifacts.filter((artifact) => artifactIdsToKeep.has(artifact.id)); +} +__name(filterArtifactsByAvailableAudits, "filterArtifactsByAvailableAudits"); +function filterArtifactsByGatherMode(artifacts, mode) { + if (!artifacts) return null; + return artifacts.filter((artifact) => { + return artifact.gatherer.instance.meta.supportedModes.includes(mode); + }); +} +__name(filterArtifactsByGatherMode, "filterArtifactsByGatherMode"); +function filterAuditsByAvailableArtifacts(audits, availableArtifacts) { + if (!audits) return null; + const availableArtifactIds = new Set( + availableArtifacts.map((artifact) => artifact.id).concat(baseArtifactKeys) + ); + return audits.filter((audit) => { + const meta = audit.implementation.meta; + return meta.requiredArtifacts.every((id) => availableArtifactIds.has(id)); + }); +} +__name(filterAuditsByAvailableArtifacts, "filterAuditsByAvailableArtifacts"); +function filterAuditsByGatherMode(audits, mode) { + if (!audits) return null; + return audits.filter((audit) => { + const meta = audit.implementation.meta; + return !meta.supportedModes || meta.supportedModes.includes(mode); + }); +} +__name(filterAuditsByGatherMode, "filterAuditsByGatherMode"); +function filterCategoriesByGatherMode(categories, mode) { + if (!categories) return null; + const categoriesToKeep = Object.entries(categories).filter(([_, category]) => { + return !category.supportedModes || category.supportedModes.includes(mode); + }); + return Object.fromEntries(categoriesToKeep); +} +__name(filterCategoriesByGatherMode, "filterCategoriesByGatherMode"); +function filterCategoriesByExplicitFilters(categories, onlyCategories) { + if (!categories || !onlyCategories) return categories; + const categoriesToKeep = Object.entries(categories).filter(([categoryId]) => onlyCategories.includes(categoryId)); + return Object.fromEntries(categoriesToKeep); +} +__name(filterCategoriesByExplicitFilters, "filterCategoriesByExplicitFilters"); +function errorOnUnknownOnlyCategories(allCategories, onlyCategories) { + if (!onlyCategories) return; + const unknown = onlyCategories.filter((c) => !allCategories?.[c]); + if (unknown.length) { + throw new Error(`unrecognized category in 'onlyCategories': ${unknown.join(", ")}`); + } +} +__name(errorOnUnknownOnlyCategories, "errorOnUnknownOnlyCategories"); +function filterCategoriesByAvailableAudits(categories, availableAudits) { + if (!categories) return categories; + const availableAuditIdToMeta = new Map( + availableAudits.map((audit) => [audit.implementation.meta.id, audit.implementation.meta]) + ); + const categoryEntries = Object.entries(categories).map(([categoryId, category]) => { + const filteredCategory = { + ...category, + auditRefs: category.auditRefs.filter((ref) => availableAuditIdToMeta.has(ref.id)) + }; + const didFilter = filteredCategory.auditRefs.length < category.auditRefs.length; + const hasOnlyManualAudits = filteredCategory.auditRefs.every((ref) => { + const meta = availableAuditIdToMeta.get(ref.id); + if (!meta) return false; + return meta.scoreDisplayMode === Audit.SCORING_MODES.MANUAL; + }); + if (didFilter && hasOnlyManualAudits) filteredCategory.auditRefs = []; + return [categoryId, filteredCategory]; + }).filter((entry) => typeof entry[1] === "object" && entry[1].auditRefs.length); + return Object.fromEntries(categoryEntries); +} +__name(filterCategoriesByAvailableAudits, "filterCategoriesByAvailableAudits"); +function filterConfigByGatherMode(resolvedConfig, mode) { + const artifacts = filterArtifactsByGatherMode(resolvedConfig.artifacts, mode); + const supportedAudits = filterAuditsByGatherMode(resolvedConfig.audits, mode); + const audits = filterAuditsByAvailableArtifacts(supportedAudits, artifacts || []); + const supportedCategories = filterCategoriesByGatherMode(resolvedConfig.categories, mode); + const categories = filterCategoriesByAvailableAudits(supportedCategories, audits || []); + return { + ...resolvedConfig, + artifacts, + audits, + categories + }; +} +__name(filterConfigByGatherMode, "filterConfigByGatherMode"); +function filterConfigByExplicitFilters(resolvedConfig, filters) { + const { onlyAudits, onlyCategories, skipAudits } = filters; + if (onlyAudits && !onlyAudits.length) { + throw new Error(`onlyAudits cannot be an empty array.`); + } + if (onlyCategories && !onlyCategories.length) { + throw new Error(`onlyCategories cannot be an empty array.`); + } + errorOnUnknownOnlyCategories(resolvedConfig.categories, onlyCategories); + let baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, void 0); + if (onlyCategories) { + baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, onlyCategories); + } else if (onlyAudits) { + baseAuditIds = /* @__PURE__ */ new Set(); + } else if (!resolvedConfig.categories || !Object.keys(resolvedConfig.categories).length) { + baseAuditIds = new Set(resolvedConfig.audits?.map((audit) => audit.implementation.meta.id)); + } + const auditIdsToKeep = new Set( + [ + ...baseAuditIds, + // Start with our base audits. + ...onlyAudits || [], + // Additionally include the opt-in audits from `onlyAudits`. + ...filterResistantAuditIds + // Always include any filter-resistant audits. + ].filter((auditId) => !skipAudits || !skipAudits.includes(auditId)) + ); + const audits = auditIdsToKeep.size && resolvedConfig.audits ? resolvedConfig.audits.filter((audit) => auditIdsToKeep.has(audit.implementation.meta.id)) : resolvedConfig.audits; + const availableCategories = filterCategoriesByAvailableAudits(resolvedConfig.categories, audits || []); + const categories = filterCategoriesByExplicitFilters(availableCategories, onlyCategories); + let artifacts = filterArtifactsByAvailableAudits(resolvedConfig.artifacts, audits); + if (artifacts && resolvedConfig.settings.disableFullPageScreenshot) { + artifacts = artifacts.filter(({ id }) => id !== "FullPageScreenshot"); + } + return { + ...resolvedConfig, + artifacts, + audits, + categories + }; +} +__name(filterConfigByExplicitFilters, "filterConfigByExplicitFilters"); + +// core/config/config-helpers.js +init_process_global(); +init_module(); +init_url(); +init_lodash(); +import path4 from "path"; + +// core/config/config-plugin.js +init_process_global(); +init_i18n(); +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +function isArrayOfUnknownObjects(arr) { + return Array.isArray(arr) && arr.every(isObjectOfUnknownProperties); +} +__name(isArrayOfUnknownObjects, "isArrayOfUnknownObjects"); +function isObjectOfUnknownProperties(val) { + return typeof val === "object" && val !== null && !Array.isArray(val); +} +__name(isObjectOfUnknownProperties, "isObjectOfUnknownProperties"); +function objectIsGatherMode(str) { + if (typeof str !== "string") return false; + return str === "navigation" || str === "timespan" || str === "snapshot"; +} +__name(objectIsGatherMode, "objectIsGatherMode"); +function isArrayOfGatherModes(arr) { + if (!Array.isArray(arr)) return false; + return arr.every(objectIsGatherMode); +} +__name(isArrayOfGatherModes, "isArrayOfGatherModes"); +function assertNoExcessProperties(obj, pluginName, objectName = "") { + if (objectName) { + objectName += " "; + } + const invalidKeys = Object.keys(obj); + if (invalidKeys.length > 0) { + const keys2 = invalidKeys.join(", "); + throw new Error(`${pluginName} has unrecognized ${objectName}properties: [${keys2}]`); + } +} +__name(assertNoExcessProperties, "assertNoExcessProperties"); +var ConfigPlugin = class _ConfigPlugin { + static { + __name(this, "ConfigPlugin"); + } + /** + * Extract and validate the list of AuditDefns added by the plugin (or undefined + * if no additional audits are being added by the plugin). + * @param {unknown} auditsJson + * @param {string} pluginName + * @return {Array<{path: string}>|undefined} + */ + static _parseAuditsList(auditsJson, pluginName) { + if (auditsJson === void 0) { + return void 0; + } else if (!isArrayOfUnknownObjects(auditsJson)) { + throw new Error(`${pluginName} has an invalid audits array.`); + } + return auditsJson.map((auditDefnJson) => { + const { path: path7, ...invalidRest } = auditDefnJson; + assertNoExcessProperties(invalidRest, pluginName, "audit"); + if (typeof path7 !== "string") { + throw new Error(`${pluginName} has a missing audit path.`); + } + return { + path: path7 + }; + }); + } + /** + * Extract and validate the list of category AuditRefs added by the plugin. + * @param {unknown} auditRefsJson + * @param {string} pluginName + * @return {Array} + */ + static _parseAuditRefsList(auditRefsJson, pluginName) { + if (!isArrayOfUnknownObjects(auditRefsJson)) { + throw new Error(`${pluginName} has no valid auditsRefs.`); + } + return auditRefsJson.map((auditRefJson) => { + const { id, weight, group, ...invalidRest } = auditRefJson; + assertNoExcessProperties(invalidRest, pluginName, "auditRef"); + if (typeof id !== "string") { + throw new Error(`${pluginName} has an invalid auditRef id.`); + } + if (typeof weight !== "number") { + throw new Error(`${pluginName} has an invalid auditRef weight.`); + } + if (typeof group !== "string" && typeof group !== "undefined") { + throw new Error(`${pluginName} has an invalid auditRef group.`); + } + const prependedGroup = group ? `${pluginName}-${group}` : group; + return { + id, + weight, + group: prependedGroup + }; + }); + } + /** + * Extract and validate the category added by the plugin. + * @param {unknown} categoryJson + * @param {string} pluginName + * @return {LH.Config.CategoryJson} + */ + static _parseCategory(categoryJson, pluginName) { + if (!isObjectOfUnknownProperties(categoryJson)) { + throw new Error(`${pluginName} has no valid category.`); + } + const { + title, + description, + manualDescription, + auditRefs: auditRefsJson, + supportedModes, + ...invalidRest + } = categoryJson; + assertNoExcessProperties(invalidRest, pluginName, "category"); + if (!isStringOrIcuMessage(title)) { + throw new Error(`${pluginName} has an invalid category tile.`); + } + if (!isStringOrIcuMessage(description) && description !== void 0) { + throw new Error(`${pluginName} has an invalid category description.`); + } + if (!isStringOrIcuMessage(manualDescription) && manualDescription !== void 0) { + throw new Error(`${pluginName} has an invalid category manualDescription.`); + } + if (!isArrayOfGatherModes(supportedModes) && supportedModes !== void 0) { + throw new Error( + `${pluginName} supportedModes must be an array, valid array values are "navigation", "timespan", and "snapshot".` + ); + } + const auditRefs = _ConfigPlugin._parseAuditRefsList(auditRefsJson, pluginName); + return { + title, + auditRefs, + description, + manualDescription, + supportedModes + }; + } + /** + * Extract and validate groups JSON added by the plugin. + * @param {unknown} groupsJson + * @param {string} pluginName + * @return {Record|undefined} + */ + static _parseGroups(groupsJson, pluginName) { + if (groupsJson === void 0) { + return void 0; + } + if (!isObjectOfUnknownProperties(groupsJson)) { + throw new Error(`${pluginName} groups json is not defined as an object.`); + } + const groups = Object.entries(groupsJson); + const parsedGroupsJson = {}; + groups.forEach(([groupId, groupJson]) => { + if (!isObjectOfUnknownProperties(groupJson)) { + throw new Error(`${pluginName} has a group not defined as an object.`); + } + const { title, description, ...invalidRest } = groupJson; + assertNoExcessProperties(invalidRest, pluginName, "group"); + if (!isStringOrIcuMessage(title)) { + throw new Error(`${pluginName} has an invalid group title.`); + } + if (!isStringOrIcuMessage(description) && description !== void 0) { + throw new Error(`${pluginName} has an invalid group description.`); + } + parsedGroupsJson[`${pluginName}-${groupId}`] = { + title, + description + }; + }); + return parsedGroupsJson; + } + /** + * Extracts and validates a config from the provided plugin input, throwing + * if it deviates from the expected object shape. + * @param {unknown} pluginJson + * @param {string} pluginName + * @return {LH.Config} + */ + static parsePlugin(pluginJson, pluginName) { + pluginJson = JSON.parse(JSON.stringify(pluginJson)); + if (!isObjectOfUnknownProperties(pluginJson)) { + throw new Error(`${pluginName} is not defined as an object.`); + } + const { + audits: pluginAuditsJson, + category: pluginCategoryJson, + groups: pluginGroupsJson, + ...invalidRest + } = pluginJson; + assertNoExcessProperties(invalidRest, pluginName); + return { + audits: _ConfigPlugin._parseAuditsList(pluginAuditsJson, pluginName), + categories: { + [pluginName]: _ConfigPlugin._parseCategory(pluginCategoryJson, pluginName) + }, + groups: _ConfigPlugin._parseGroups(pluginGroupsJson, pluginName) + }; + } +}; +var config_plugin_default = ConfigPlugin; + +// core/config/config-helpers.js +init_i18n(); +init_esm_utils(); +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var require4 = createRequire({ url: "core/config/config-helpers.js" }.url); +function isBundledEnvironment2() { + if (global.isDevtools || global.isLightrider) return true; + try { + require4.resolve("lighthouse-logger"); + return false; + } catch (err) { + return true; + } +} +__name(isBundledEnvironment2, "isBundledEnvironment"); +var mergeOptionsOfItems = /* @__PURE__ */ __name(function(items) { + const mergedItems = []; + for (const item of items) { + const existingItem = item.path && mergedItems.find((candidate) => candidate.path === item.path); + if (!existingItem) { + mergedItems.push(item); + continue; + } + existingItem.options = Object.assign({}, existingItem.options, item.options); + } + return mergedItems; +}, "mergeOptionsOfItems"); +function _mergeConfigFragment(base, extension, overwriteArrays = false) { + if (typeof base === "undefined" || base === null) { + return extension; + } else if (typeof extension === "undefined") { + return base; + } else if (Array.isArray(extension)) { + if (overwriteArrays) return extension; + if (!Array.isArray(base)) throw new TypeError(`Expected array but got ${typeof base}`); + const merged = base.slice(); + extension.forEach((item) => { + if (!merged.some((candidate) => isEqual_default(candidate, item))) merged.push(item); + }); + return merged; + } else if (typeof extension === "object") { + if (typeof base !== "object") throw new TypeError(`Expected object but got ${typeof base}`); + if (Array.isArray(base)) throw new TypeError("Expected object but got Array"); + Object.keys(extension).forEach((key) => { + const localOverwriteArrays = overwriteArrays || key === "settings" && typeof base[key] === "object"; + base[key] = _mergeConfigFragment(base[key], extension[key], localOverwriteArrays); + }); + return base; + } + return extension; +} +__name(_mergeConfigFragment, "_mergeConfigFragment"); +var mergeConfigFragment = _mergeConfigFragment; +function mergeConfigFragmentArrayByKey(baseArray, extensionArray, keyFn) { + const itemsByKey = /* @__PURE__ */ new Map(); + const mergedArray = baseArray || []; + for (let i = 0; i < mergedArray.length; i++) { + const item = mergedArray[i]; + itemsByKey.set(keyFn(item), { index: i, item }); + } + for (const item of extensionArray || []) { + const baseItemEntry = itemsByKey.get(keyFn(item)); + if (baseItemEntry) { + const baseItem = baseItemEntry.item; + const merged = typeof item === "object" && typeof baseItem === "object" ? mergeConfigFragment(baseItem, item, true) : item; + mergedArray[baseItemEntry.index] = merged; + } else { + mergedArray.push(item); + } + } + return mergedArray; +} +__name(mergeConfigFragmentArrayByKey, "mergeConfigFragmentArrayByKey"); +function expandGathererShorthand(gatherer) { + if (typeof gatherer === "string") { + return { path: gatherer }; + } else if ("implementation" in gatherer || "instance" in gatherer) { + return gatherer; + } else if ("path" in gatherer) { + if (typeof gatherer.path !== "string") { + throw new Error("Invalid Gatherer type " + JSON.stringify(gatherer)); + } + return gatherer; + } else if (typeof gatherer === "function") { + return { implementation: gatherer }; + } else if (gatherer && typeof gatherer.getArtifact === "function") { + return { instance: gatherer }; + } else { + throw new Error("Invalid Gatherer type " + JSON.stringify(gatherer)); + } +} +__name(expandGathererShorthand, "expandGathererShorthand"); +function expandAuditShorthand(audit) { + if (typeof audit === "string") { + return { path: audit, options: {} }; + } else if ("implementation" in audit && typeof audit.implementation.audit === "function") { + return audit; + } else if ("path" in audit && typeof audit.path === "string") { + return audit; + } else if ("audit" in audit && typeof audit.audit === "function") { + return { implementation: audit, options: {} }; + } else { + throw new Error("Invalid Audit type " + JSON.stringify(audit)); + } +} +__name(expandAuditShorthand, "expandAuditShorthand"); +var bundledModules = /* @__PURE__ */ new Map([ + ["../gather/gatherers/accessibility", Promise.resolve().then(() => (init_accessibility(), accessibility_exports))], + ["../gather/gatherers/anchor-elements", Promise.resolve().then(() => (init_anchor_elements(), anchor_elements_exports))], + ["../gather/gatherers/console-messages", Promise.resolve().then(() => (init_console_messages(), console_messages_exports))], + ["../gather/gatherers/devtools-log", Promise.resolve().then(() => (init_devtools_log(), devtools_log_exports))], + ["../gather/gatherers/dobetterweb/doctype", Promise.resolve().then(() => (init_doctype(), doctype_exports))], + ["../gather/gatherers/image-elements", Promise.resolve().then(() => (init_image_elements(), image_elements_exports))], + ["../gather/gatherers/inputs", Promise.resolve().then(() => (init_inputs(), inputs_exports))], + ["../gather/gatherers/inspector-issues", Promise.resolve().then(() => (init_inspector_issues(), inspector_issues_exports))], + ["../gather/gatherers/link-elements", Promise.resolve().then(() => (init_link_elements(), link_elements_exports))], + ["../gather/gatherers/main-document-content", Promise.resolve().then(() => (init_main_document_content(), main_document_content_exports))], + ["../gather/gatherers/meta-elements", Promise.resolve().then(() => (init_meta_elements(), meta_elements_exports))], + ["../gather/gatherers/scripts", Promise.resolve().then(() => (init_scripts(), scripts_exports))], + ["../gather/gatherers/seo/robots-txt", Promise.resolve().then(() => (init_robots_txt(), robots_txt_exports))], + ["../gather/gatherers/source-maps", Promise.resolve().then(() => (init_source_maps(), source_maps_exports))], + ["../gather/gatherers/stacks", Promise.resolve().then(() => (init_stacks(), stacks_exports))], + ["../gather/gatherers/viewport-dimensions", Promise.resolve().then(() => (init_viewport_dimensions(), viewport_dimensions_exports))], + ["../audits/accessibility/accesskeys", Promise.resolve().then(() => (init_accesskeys(), accesskeys_exports))], + ["../audits/accessibility/aria-allowed-attr", Promise.resolve().then(() => (init_aria_allowed_attr(), aria_allowed_attr_exports))], + ["../audits/accessibility/aria-allowed-role", Promise.resolve().then(() => (init_aria_allowed_role(), aria_allowed_role_exports))], + ["../audits/accessibility/aria-command-name", Promise.resolve().then(() => (init_aria_command_name(), aria_command_name_exports))], + ["../audits/accessibility/aria-conditional-attr", Promise.resolve().then(() => (init_aria_conditional_attr(), aria_conditional_attr_exports))], + ["../audits/accessibility/aria-deprecated-role", Promise.resolve().then(() => (init_aria_deprecated_role(), aria_deprecated_role_exports))], + ["../audits/accessibility/aria-dialog-name", Promise.resolve().then(() => (init_aria_dialog_name(), aria_dialog_name_exports))], + ["../audits/accessibility/aria-hidden-body", Promise.resolve().then(() => (init_aria_hidden_body(), aria_hidden_body_exports))], + ["../audits/accessibility/aria-hidden-focus", Promise.resolve().then(() => (init_aria_hidden_focus(), aria_hidden_focus_exports))], + ["../audits/accessibility/aria-input-field-name", Promise.resolve().then(() => (init_aria_input_field_name(), aria_input_field_name_exports))], + ["../audits/accessibility/aria-meter-name", Promise.resolve().then(() => (init_aria_meter_name(), aria_meter_name_exports))], + ["../audits/accessibility/aria-progressbar-name", Promise.resolve().then(() => (init_aria_progressbar_name(), aria_progressbar_name_exports))], + ["../audits/accessibility/aria-prohibited-attr", Promise.resolve().then(() => (init_aria_prohibited_attr(), aria_prohibited_attr_exports))], + ["../audits/accessibility/aria-required-attr", Promise.resolve().then(() => (init_aria_required_attr(), aria_required_attr_exports))], + ["../audits/accessibility/aria-required-children", Promise.resolve().then(() => (init_aria_required_children(), aria_required_children_exports))], + ["../audits/accessibility/aria-required-parent", Promise.resolve().then(() => (init_aria_required_parent(), aria_required_parent_exports))], + ["../audits/accessibility/aria-roles", Promise.resolve().then(() => (init_aria_roles(), aria_roles_exports))], + ["../audits/accessibility/aria-text", Promise.resolve().then(() => (init_aria_text(), aria_text_exports))], + ["../audits/accessibility/aria-toggle-field-name", Promise.resolve().then(() => (init_aria_toggle_field_name(), aria_toggle_field_name_exports))], + ["../audits/accessibility/aria-tooltip-name", Promise.resolve().then(() => (init_aria_tooltip_name(), aria_tooltip_name_exports))], + ["../audits/accessibility/aria-treeitem-name", Promise.resolve().then(() => (init_aria_treeitem_name(), aria_treeitem_name_exports))], + ["../audits/accessibility/aria-valid-attr-value", Promise.resolve().then(() => (init_aria_valid_attr_value(), aria_valid_attr_value_exports))], + ["../audits/accessibility/aria-valid-attr", Promise.resolve().then(() => (init_aria_valid_attr(), aria_valid_attr_exports))], + ["../audits/accessibility/button-name", Promise.resolve().then(() => (init_button_name(), button_name_exports))], + ["../audits/accessibility/bypass", Promise.resolve().then(() => (init_bypass(), bypass_exports))], + ["../audits/accessibility/color-contrast", Promise.resolve().then(() => (init_color_contrast(), color_contrast_exports))], + ["../audits/accessibility/definition-list", Promise.resolve().then(() => (init_definition_list(), definition_list_exports))], + ["../audits/accessibility/dlitem", Promise.resolve().then(() => (init_dlitem(), dlitem_exports))], + ["../audits/accessibility/document-title", Promise.resolve().then(() => (init_document_title(), document_title_exports))], + ["../audits/accessibility/duplicate-id-aria", Promise.resolve().then(() => (init_duplicate_id_aria(), duplicate_id_aria_exports))], + ["../audits/accessibility/empty-heading", Promise.resolve().then(() => (init_empty_heading(), empty_heading_exports))], + ["../audits/accessibility/form-field-multiple-labels", Promise.resolve().then(() => (init_form_field_multiple_labels(), form_field_multiple_labels_exports))], + ["../audits/accessibility/frame-title", Promise.resolve().then(() => (init_frame_title(), frame_title_exports))], + ["../audits/accessibility/heading-order", Promise.resolve().then(() => (init_heading_order(), heading_order_exports))], + ["../audits/accessibility/html-has-lang", Promise.resolve().then(() => (init_html_has_lang(), html_has_lang_exports))], + ["../audits/accessibility/html-lang-valid", Promise.resolve().then(() => (init_html_lang_valid(), html_lang_valid_exports))], + ["../audits/accessibility/html-xml-lang-mismatch", Promise.resolve().then(() => (init_html_xml_lang_mismatch(), html_xml_lang_mismatch_exports))], + ["../audits/accessibility/identical-links-same-purpose", Promise.resolve().then(() => (init_identical_links_same_purpose(), identical_links_same_purpose_exports))], + ["../audits/accessibility/image-alt", Promise.resolve().then(() => (init_image_alt(), image_alt_exports))], + ["../audits/accessibility/image-redundant-alt", Promise.resolve().then(() => (init_image_redundant_alt(), image_redundant_alt_exports))], + ["../audits/accessibility/input-button-name", Promise.resolve().then(() => (init_input_button_name(), input_button_name_exports))], + ["../audits/accessibility/input-image-alt", Promise.resolve().then(() => (init_input_image_alt(), input_image_alt_exports))], + ["../audits/accessibility/label-content-name-mismatch", Promise.resolve().then(() => (init_label_content_name_mismatch(), label_content_name_mismatch_exports))], + ["../audits/accessibility/label", Promise.resolve().then(() => (init_label(), label_exports))], + ["../audits/accessibility/landmark-one-main", Promise.resolve().then(() => (init_landmark_one_main(), landmark_one_main_exports))], + ["../audits/accessibility/link-in-text-block", Promise.resolve().then(() => (init_link_in_text_block(), link_in_text_block_exports))], + ["../audits/accessibility/link-name", Promise.resolve().then(() => (init_link_name(), link_name_exports))], + ["../audits/accessibility/list", Promise.resolve().then(() => (init_list(), list_exports))], + ["../audits/accessibility/listitem", Promise.resolve().then(() => (init_listitem(), listitem_exports))], + ["../audits/accessibility/manual/custom-controls-labels", Promise.resolve().then(() => (init_custom_controls_labels(), custom_controls_labels_exports))], + ["../audits/accessibility/manual/custom-controls-roles", Promise.resolve().then(() => (init_custom_controls_roles(), custom_controls_roles_exports))], + ["../audits/accessibility/manual/focus-traps", Promise.resolve().then(() => (init_focus_traps(), focus_traps_exports))], + ["../audits/accessibility/manual/focusable-controls", Promise.resolve().then(() => (init_focusable_controls(), focusable_controls_exports))], + ["../audits/accessibility/manual/interactive-element-affordance", Promise.resolve().then(() => (init_interactive_element_affordance(), interactive_element_affordance_exports))], + ["../audits/accessibility/manual/logical-tab-order", Promise.resolve().then(() => (init_logical_tab_order(), logical_tab_order_exports))], + ["../audits/accessibility/manual/managed-focus", Promise.resolve().then(() => (init_managed_focus(), managed_focus_exports))], + ["../audits/accessibility/manual/offscreen-content-hidden", Promise.resolve().then(() => (init_offscreen_content_hidden(), offscreen_content_hidden_exports))], + ["../audits/accessibility/manual/use-landmarks", Promise.resolve().then(() => (init_use_landmarks(), use_landmarks_exports))], + ["../audits/accessibility/manual/visual-order-follows-dom", Promise.resolve().then(() => (init_visual_order_follows_dom(), visual_order_follows_dom_exports))], + ["../audits/accessibility/meta-refresh", Promise.resolve().then(() => (init_meta_refresh(), meta_refresh_exports))], + ["../audits/accessibility/meta-viewport", Promise.resolve().then(() => (init_meta_viewport(), meta_viewport_exports))], + ["../audits/accessibility/object-alt", Promise.resolve().then(() => (init_object_alt(), object_alt_exports))], + ["../audits/accessibility/select-name", Promise.resolve().then(() => (init_select_name(), select_name_exports))], + ["../audits/accessibility/skip-link", Promise.resolve().then(() => (init_skip_link(), skip_link_exports))], + ["../audits/accessibility/tabindex", Promise.resolve().then(() => (init_tabindex(), tabindex_exports))], + ["../audits/accessibility/table-duplicate-name", Promise.resolve().then(() => (init_table_duplicate_name(), table_duplicate_name_exports))], + ["../audits/accessibility/table-fake-caption", Promise.resolve().then(() => (init_table_fake_caption(), table_fake_caption_exports))], + ["../audits/accessibility/target-size", Promise.resolve().then(() => (init_target_size(), target_size_exports))], + ["../audits/accessibility/td-has-header", Promise.resolve().then(() => (init_td_has_header(), td_has_header_exports))], + ["../audits/accessibility/td-headers-attr", Promise.resolve().then(() => (init_td_headers_attr(), td_headers_attr_exports))], + ["../audits/accessibility/th-has-data-cells", Promise.resolve().then(() => (init_th_has_data_cells(), th_has_data_cells_exports))], + ["../audits/accessibility/valid-lang", Promise.resolve().then(() => (init_valid_lang(), valid_lang_exports))], + ["../audits/accessibility/video-caption", Promise.resolve().then(() => (init_video_caption(), video_caption_exports))], + ["../audits/clickjacking-mitigation", Promise.resolve().then(() => (init_clickjacking_mitigation(), clickjacking_mitigation_exports))], + ["../audits/csp-xss", Promise.resolve().then(() => (init_csp_xss(), csp_xss_exports))], + ["../audits/deprecations", Promise.resolve().then(() => (init_deprecations(), deprecations_exports))], + ["../audits/dobetterweb/charset", Promise.resolve().then(() => (init_charset(), charset_exports))], + ["../audits/dobetterweb/doctype", Promise.resolve().then(() => (init_doctype2(), doctype_exports2))], + ["../audits/dobetterweb/geolocation-on-start", Promise.resolve().then(() => (init_geolocation_on_start(), geolocation_on_start_exports))], + ["../audits/dobetterweb/inspector-issues", Promise.resolve().then(() => (init_inspector_issues2(), inspector_issues_exports2))], + ["../audits/dobetterweb/js-libraries", Promise.resolve().then(() => (init_js_libraries(), js_libraries_exports))], + ["../audits/dobetterweb/notification-on-start", Promise.resolve().then(() => (init_notification_on_start(), notification_on_start_exports))], + ["../audits/dobetterweb/paste-preventing-inputs", Promise.resolve().then(() => (init_paste_preventing_inputs(), paste_preventing_inputs_exports))], + ["../audits/errors-in-console", Promise.resolve().then(() => (init_errors_in_console(), errors_in_console_exports))], + ["../audits/has-hsts", Promise.resolve().then(() => (init_has_hsts(), has_hsts_exports))], + ["../audits/image-aspect-ratio", Promise.resolve().then(() => (init_image_aspect_ratio(), image_aspect_ratio_exports))], + ["../audits/image-size-responsive", Promise.resolve().then(() => (init_image_size_responsive(), image_size_responsive_exports))], + ["../audits/is-on-https", Promise.resolve().then(() => (init_is_on_https(), is_on_https_exports))], + ["../audits/origin-isolation", Promise.resolve().then(() => (init_origin_isolation(), origin_isolation_exports))], + ["../audits/redirects-http", Promise.resolve().then(() => (init_redirects_http(), redirects_http_exports))], + ["../audits/seo/canonical", Promise.resolve().then(() => (init_canonical(), canonical_exports))], + ["../audits/seo/crawlable-anchors", Promise.resolve().then(() => (init_crawlable_anchors(), crawlable_anchors_exports))], + ["../audits/seo/hreflang", Promise.resolve().then(() => (init_hreflang(), hreflang_exports))], + ["../audits/seo/http-status-code", Promise.resolve().then(() => (init_http_status_code(), http_status_code_exports))], + ["../audits/seo/is-crawlable", Promise.resolve().then(() => (init_is_crawlable(), is_crawlable_exports))], + ["../audits/seo/link-text", Promise.resolve().then(() => (init_link_text(), link_text_exports))], + ["../audits/seo/manual/structured-data", Promise.resolve().then(() => (init_structured_data(), structured_data_exports))], + ["../audits/seo/meta-description", Promise.resolve().then(() => (init_meta_description(), meta_description_exports))], + ["../audits/seo/robots-txt", Promise.resolve().then(() => (init_robots_txt2(), robots_txt_exports2))], + ["../audits/third-party-cookies", Promise.resolve().then(() => (init_third_party_cookies(), third_party_cookies_exports))], + ["../audits/trusted-types-xss", Promise.resolve().then(() => (init_trusted_types_xss(), trusted_types_xss_exports))], + ["../audits/valid-source-maps", Promise.resolve().then(() => (init_valid_source_maps(), valid_source_maps_exports))], + ["../computed/speedline", Promise.resolve().then(() => (init_speedline(), speedline_exports))], + ["../computed/metrics/timing-summary", Promise.resolve().then(() => (init_timing_summary(), timing_summary_exports))], + ["../computed/entity-classification", Promise.resolve().then(() => (init_entity_classification(), entity_classification_exports))], + ["../computed/trace-engine-result", Promise.resolve().then(() => (init_trace_engine_result(), trace_engine_result_exports))], + ["../gather/gatherers/bf-cache-failures", Promise.resolve().then(() => (init_bf_cache_failures(), bf_cache_failures_exports))], + ["../gather/gatherers/css-usage", Promise.resolve().then(() => (init_css_usage(), css_usage_exports))], + ["../gather/gatherers/full-page-screenshot", Promise.resolve().then(() => (init_full_page_screenshot(), full_page_screenshot_exports))], + ["../gather/gatherers/iframe-elements", Promise.resolve().then(() => (init_iframe_elements(), iframe_elements_exports))], + ["../gather/gatherers/js-usage", Promise.resolve().then(() => (init_js_usage(), js_usage_exports))], + ["../gather/gatherers/network-user-agent", Promise.resolve().then(() => (init_network_user_agent(), network_user_agent_exports))], + ["../gather/gatherers/stylesheets", Promise.resolve().then(() => (init_stylesheets(), stylesheets_exports))], + ["../gather/gatherers/trace-elements", Promise.resolve().then(() => (init_trace_elements(), trace_elements_exports))], + ["../gather/gatherers/trace", Promise.resolve().then(() => (init_trace(), trace_exports))], + ["../audits/autocomplete", Promise.resolve().then(() => (init_autocomplete(), autocomplete_exports))], + ["../audits/bf-cache", Promise.resolve().then(() => (init_bf_cache(), bf_cache_exports))], + ["../audits/bootup-time", Promise.resolve().then(() => (init_bootup_time(), bootup_time_exports))], + ["../audits/byte-efficiency/total-byte-weight", Promise.resolve().then(() => (init_total_byte_weight(), total_byte_weight_exports))], + ["../audits/byte-efficiency/unminified-css", Promise.resolve().then(() => (init_unminified_css(), unminified_css_exports))], + ["../audits/byte-efficiency/unminified-javascript", Promise.resolve().then(() => (init_unminified_javascript(), unminified_javascript_exports))], + ["../audits/byte-efficiency/unused-css-rules", Promise.resolve().then(() => (init_unused_css_rules(), unused_css_rules_exports))], + ["../audits/byte-efficiency/unused-javascript", Promise.resolve().then(() => (init_unused_javascript(), unused_javascript_exports))], + ["../audits/diagnostics", Promise.resolve().then(() => (init_diagnostics(), diagnostics_exports))], + ["../audits/final-screenshot", Promise.resolve().then(() => (init_final_screenshot(), final_screenshot_exports))], + ["../audits/insights/cache-insight", Promise.resolve().then(() => (init_cache_insight(), cache_insight_exports))], + ["../audits/insights/cls-culprits-insight", Promise.resolve().then(() => (init_cls_culprits_insight(), cls_culprits_insight_exports))], + ["../audits/insights/document-latency-insight", Promise.resolve().then(() => (init_document_latency_insight(), document_latency_insight_exports))], + ["../audits/insights/dom-size-insight", Promise.resolve().then(() => (init_dom_size_insight(), dom_size_insight_exports))], + ["../audits/insights/duplicated-javascript-insight", Promise.resolve().then(() => (init_duplicated_javascript_insight(), duplicated_javascript_insight_exports))], + ["../audits/insights/font-display-insight", Promise.resolve().then(() => (init_font_display_insight(), font_display_insight_exports))], + ["../audits/insights/forced-reflow-insight", Promise.resolve().then(() => (init_forced_reflow_insight(), forced_reflow_insight_exports))], + ["../audits/insights/image-delivery-insight", Promise.resolve().then(() => (init_image_delivery_insight(), image_delivery_insight_exports))], + ["../audits/insights/inp-breakdown-insight", Promise.resolve().then(() => (init_inp_breakdown_insight(), inp_breakdown_insight_exports))], + ["../audits/insights/lcp-breakdown-insight", Promise.resolve().then(() => (init_lcp_breakdown_insight(), lcp_breakdown_insight_exports))], + ["../audits/insights/lcp-discovery-insight", Promise.resolve().then(() => (init_lcp_discovery_insight(), lcp_discovery_insight_exports))], + ["../audits/insights/legacy-javascript-insight", Promise.resolve().then(() => (init_legacy_javascript_insight(), legacy_javascript_insight_exports))], + ["../audits/insights/modern-http-insight", Promise.resolve().then(() => (init_modern_http_insight(), modern_http_insight_exports))], + ["../audits/insights/network-dependency-tree-insight", Promise.resolve().then(() => (init_network_dependency_tree_insight(), network_dependency_tree_insight_exports))], + ["../audits/insights/render-blocking-insight", Promise.resolve().then(() => (init_render_blocking_insight(), render_blocking_insight_exports))], + ["../audits/insights/slow-css-selector-insight", Promise.resolve().then(() => (init_slow_css_selector_insight(), slow_css_selector_insight_exports))], + ["../audits/insights/third-parties-insight", Promise.resolve().then(() => (init_third_parties_insight(), third_parties_insight_exports))], + ["../audits/insights/viewport-insight", Promise.resolve().then(() => (init_viewport_insight(), viewport_insight_exports))], + ["../audits/layout-shifts", Promise.resolve().then(() => (init_layout_shifts(), layout_shifts_exports))], + ["../audits/long-tasks", Promise.resolve().then(() => (init_long_tasks(), long_tasks_exports))], + ["../audits/main-thread-tasks", Promise.resolve().then(() => (init_main_thread_tasks(), main_thread_tasks_exports))], + ["../audits/mainthread-work-breakdown", Promise.resolve().then(() => (init_mainthread_work_breakdown(), mainthread_work_breakdown_exports))], + ["../audits/metrics", Promise.resolve().then(() => (init_metrics2(), metrics_exports2))], + ["../audits/metrics/cumulative-layout-shift", Promise.resolve().then(() => (init_cumulative_layout_shift(), cumulative_layout_shift_exports))], + ["../audits/metrics/first-contentful-paint", Promise.resolve().then(() => (init_first_contentful_paint(), first_contentful_paint_exports))], + ["../audits/metrics/interaction-to-next-paint", Promise.resolve().then(() => (init_interaction_to_next_paint(), interaction_to_next_paint_exports))], + ["../audits/metrics/interactive", Promise.resolve().then(() => (init_interactive(), interactive_exports))], + ["../audits/metrics/largest-contentful-paint", Promise.resolve().then(() => (init_largest_contentful_paint(), largest_contentful_paint_exports))], + ["../audits/metrics/max-potential-fid", Promise.resolve().then(() => (init_max_potential_fid(), max_potential_fid_exports))], + ["../audits/metrics/speed-index", Promise.resolve().then(() => (init_speed_index(), speed_index_exports))], + ["../audits/metrics/total-blocking-time", Promise.resolve().then(() => (init_total_blocking_time(), total_blocking_time_exports))], + ["../audits/network-requests", Promise.resolve().then(() => (init_network_requests(), network_requests_exports))], + ["../audits/network-rtt", Promise.resolve().then(() => (init_network_rtt(), network_rtt_exports))], + ["../audits/network-server-latency", Promise.resolve().then(() => (init_network_server_latency(), network_server_latency_exports))], + ["../audits/non-composited-animations", Promise.resolve().then(() => (init_non_composited_animations(), non_composited_animations_exports))], + ["../audits/oopif-iframe-test-audit", Promise.resolve().then(() => (init_oopif_iframe_test_audit(), oopif_iframe_test_audit_exports))], + ["../audits/predictive-perf", Promise.resolve().then(() => (init_predictive_perf(), predictive_perf_exports))], + ["../audits/redirects", Promise.resolve().then(() => (init_redirects(), redirects_exports))], + ["../audits/resource-summary", Promise.resolve().then(() => (init_resource_summary(), resource_summary_exports))], + ["../audits/screenshot-thumbnails", Promise.resolve().then(() => (init_screenshot_thumbnails(), screenshot_thumbnails_exports))], + ["../audits/script-treemap-data", Promise.resolve().then(() => (init_script_treemap_data(), script_treemap_data_exports))], + ["../audits/server-response-time", Promise.resolve().then(() => (init_server_response_time(), server_response_time_exports))], + ["../audits/unsized-images", Promise.resolve().then(() => (init_unsized_images(), unsized_images_exports))], + ["../audits/user-timings", Promise.resolve().then(() => (init_user_timings(), user_timings_exports))] +]); +async function requireWrapper(requirePath) { + if (path4.isAbsolute(requirePath)) { + requirePath = url_default.pathToFileURL(requirePath).href; + } + let module2; + if (bundledModules.has(requirePath)) { + module2 = await bundledModules.get(requirePath); + } else if (requirePath.match(/\.(js|mjs|cjs)$/)) { + module2 = await import(requirePath); + } else { + requirePath += ".js"; + module2 = await import(requirePath); + } + if (module2.default) return module2.default; + const methods = /* @__PURE__ */ new Set(["meta"]); + const possibleNamedExports = Object.keys(module2).filter((key) => { + if (!(module2[key] && module2[key] instanceof Object)) return false; + return Object.getOwnPropertyNames(module2[key]).some((method) => methods.has(method)); + }); + if (possibleNamedExports.length === 1) return possibleNamedExports[0]; + if (possibleNamedExports.length > 1) { + throw new Error(`module '${requirePath}' has too many possible exports`); + } + throw new Error(`module '${requirePath}' missing default export`); +} +__name(requireWrapper, "requireWrapper"); +async function requireGatherer(gathererPath, coreGathererList, configDir) { + const coreGatherer = coreGathererList.find((a) => a === `${gathererPath}.js`); + let requirePath = `../gather/gatherers/${gathererPath}`; + if (!coreGatherer) { + requirePath = resolveModulePath(gathererPath, configDir, "gatherer"); + } + const GathererClass = ( + /** @type {GathererConstructor} */ + await requireWrapper(requirePath) + ); + return { + instance: new GathererClass(), + implementation: GathererClass, + path: gathererPath + }; +} +__name(requireGatherer, "requireGatherer"); +function requireAudit(auditPath, coreAuditList, configDir) { + const auditPathJs = `${auditPath}.js`; + const coreAudit = coreAuditList.find((a) => a === auditPathJs); + let requirePath = `../audits/${auditPath}`; + if (!coreAudit) { + if (isBundledEnvironment2()) { + requirePath = auditPath; + } else { + const absolutePath = resolveModulePath(auditPath, configDir, "audit"); + if (isBundledEnvironment2()) { + requirePath = path4.relative("", absolutePath); + } else { + requirePath = absolutePath; + } + } + } + return requireWrapper(requirePath); +} +__name(requireAudit, "requireAudit"); +function cleanFlagsForSettings(flags = {}) { + const settings = {}; + for (const key of Object.keys(flags)) { + if (key in defaultSettings) { + settings[key] = flags[key]; + } + } + return settings; +} +__name(cleanFlagsForSettings, "cleanFlagsForSettings"); +function resolveSettings(settingsJson = {}, overrides = void 0) { + const locale = lookupLocale(overrides?.locale || settingsJson.locale); + const { defaultSettings: defaultSettings2 } = constants_exports; + const settingWithDefaults = mergeConfigFragment(deepClone(defaultSettings2), settingsJson, true); + const settingsWithFlags = mergeConfigFragment( + settingWithDefaults, + cleanFlagsForSettings(overrides), + true + ); + settingsWithFlags.locale = locale; + if (settingsWithFlags.emulatedUserAgent === true) { + settingsWithFlags.emulatedUserAgent = userAgents[settingsWithFlags.formFactor]; + } + assertValidSettings(settingsWithFlags); + return settingsWithFlags; +} +__name(resolveSettings, "resolveSettings"); +async function mergePlugins(config3, configDir, flags) { + const configPlugins = config3.plugins || []; + const flagPlugins = flags?.plugins || []; + const pluginNames = /* @__PURE__ */ new Set([...configPlugins, ...flagPlugins]); + for (const pluginName of pluginNames) { + assertValidPluginName(config3, pluginName); + const pluginPath = isBundledEnvironment2() ? pluginName : resolveModulePath(pluginName, configDir, "plugin"); + const rawPluginJson = await requireWrapper(pluginPath); + const pluginJson = config_plugin_default.parsePlugin(rawPluginJson, pluginName); + config3 = mergeConfigFragment(config3, pluginJson); + } + return config3; +} +__name(mergePlugins, "mergePlugins"); +async function resolveGathererToDefn(gathererJson, coreGathererList, configDir) { + const gathererDefn = expandGathererShorthand(gathererJson); + if (gathererDefn.instance) { + return { + instance: gathererDefn.instance, + implementation: gathererDefn.implementation, + path: gathererDefn.path + }; + } else if (gathererDefn.implementation) { + const GathererClass = gathererDefn.implementation; + return { instance: new GathererClass(), implementation: gathererDefn.implementation, path: gathererDefn.path @@ -50567,6 +50570,7 @@ async function resolveGathererToDefn(gathererJson, coreGathererList, configDir) throw new Error("Invalid expanded Gatherer: " + JSON.stringify(gathererDefn)); } } +__name(resolveGathererToDefn, "resolveGathererToDefn"); async function resolveAuditsToDefns(audits, configDir) { if (!audits) { return null; @@ -50591,6 +50595,7 @@ async function resolveAuditsToDefns(audits, configDir) { mergedAuditDefns.forEach((audit) => assertValidAudit(audit)); return mergedAuditDefns; } +__name(resolveAuditsToDefns, "resolveAuditsToDefns"); function resolveModulePath(moduleIdentifier, configDir, category) { try { return require4.resolve(moduleIdentifier); @@ -50624,6 +50629,7 @@ function resolveModulePath(moduleIdentifier, configDir, category) { throw new Error(errorString + ` ${relativePath}`); } +__name(resolveModulePath, "resolveModulePath"); function shallowClone(item) { if (typeof item === "object") { return Object.assign( @@ -50635,9 +50641,11 @@ function shallowClone(item) { } return item; } +__name(shallowClone, "shallowClone"); function deepClone(json) { return JSON.parse(JSON.stringify(json)); } +__name(deepClone, "deepClone"); function deepCloneConfigJson(json) { const cloned = deepClone(json); if (Array.isArray(json.audits)) { @@ -50651,251 +50659,24 @@ function deepCloneConfigJson(json) { } return cloned; } -var require4, mergeOptionsOfItems, mergeConfigFragment, bundledModules; -var init_config_helpers = __esm({ - "core/config/config-helpers.js"() { - "use strict"; - init_process_global(); - init_module(); - init_url(); - init_lodash(); - init_constants(); - init_config_plugin(); - init_runner(); - init_i18n(); - init_validation(); - init_esm_utils(); - /** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - require4 = createRequire({ url: "core/config/config-helpers.js" }.url); - __name(isBundledEnvironment2, "isBundledEnvironment"); - mergeOptionsOfItems = /* @__PURE__ */ __name(function(items) { - const mergedItems = []; - for (const item of items) { - const existingItem = item.path && mergedItems.find((candidate) => candidate.path === item.path); - if (!existingItem) { - mergedItems.push(item); - continue; - } - existingItem.options = Object.assign({}, existingItem.options, item.options); - } - return mergedItems; - }, "mergeOptionsOfItems"); - __name(_mergeConfigFragment, "_mergeConfigFragment"); - mergeConfigFragment = _mergeConfigFragment; - __name(mergeConfigFragmentArrayByKey, "mergeConfigFragmentArrayByKey"); - __name(expandGathererShorthand, "expandGathererShorthand"); - __name(expandAuditShorthand, "expandAuditShorthand"); - bundledModules = /* @__PURE__ */ new Map([ - ["../gather/gatherers/accessibility", Promise.resolve().then(() => (init_accessibility(), accessibility_exports))], - ["../gather/gatherers/anchor-elements", Promise.resolve().then(() => (init_anchor_elements(), anchor_elements_exports))], - ["../gather/gatherers/console-messages", Promise.resolve().then(() => (init_console_messages(), console_messages_exports))], - ["../gather/gatherers/devtools-log", Promise.resolve().then(() => (init_devtools_log(), devtools_log_exports))], - ["../gather/gatherers/dobetterweb/doctype", Promise.resolve().then(() => (init_doctype(), doctype_exports))], - ["../gather/gatherers/image-elements", Promise.resolve().then(() => (init_image_elements(), image_elements_exports))], - ["../gather/gatherers/inputs", Promise.resolve().then(() => (init_inputs(), inputs_exports))], - ["../gather/gatherers/inspector-issues", Promise.resolve().then(() => (init_inspector_issues(), inspector_issues_exports))], - ["../gather/gatherers/link-elements", Promise.resolve().then(() => (init_link_elements(), link_elements_exports))], - ["../gather/gatherers/main-document-content", Promise.resolve().then(() => (init_main_document_content(), main_document_content_exports))], - ["../gather/gatherers/meta-elements", Promise.resolve().then(() => (init_meta_elements(), meta_elements_exports))], - ["../gather/gatherers/scripts", Promise.resolve().then(() => (init_scripts(), scripts_exports))], - ["../gather/gatherers/seo/robots-txt", Promise.resolve().then(() => (init_robots_txt(), robots_txt_exports))], - ["../gather/gatherers/source-maps", Promise.resolve().then(() => (init_source_maps(), source_maps_exports))], - ["../gather/gatherers/stacks", Promise.resolve().then(() => (init_stacks(), stacks_exports))], - ["../gather/gatherers/viewport-dimensions", Promise.resolve().then(() => (init_viewport_dimensions(), viewport_dimensions_exports))], - ["../audits/accessibility/accesskeys", Promise.resolve().then(() => (init_accesskeys(), accesskeys_exports))], - ["../audits/accessibility/aria-allowed-attr", Promise.resolve().then(() => (init_aria_allowed_attr(), aria_allowed_attr_exports))], - ["../audits/accessibility/aria-allowed-role", Promise.resolve().then(() => (init_aria_allowed_role(), aria_allowed_role_exports))], - ["../audits/accessibility/aria-command-name", Promise.resolve().then(() => (init_aria_command_name(), aria_command_name_exports))], - ["../audits/accessibility/aria-conditional-attr", Promise.resolve().then(() => (init_aria_conditional_attr(), aria_conditional_attr_exports))], - ["../audits/accessibility/aria-deprecated-role", Promise.resolve().then(() => (init_aria_deprecated_role(), aria_deprecated_role_exports))], - ["../audits/accessibility/aria-dialog-name", Promise.resolve().then(() => (init_aria_dialog_name(), aria_dialog_name_exports))], - ["../audits/accessibility/aria-hidden-body", Promise.resolve().then(() => (init_aria_hidden_body(), aria_hidden_body_exports))], - ["../audits/accessibility/aria-hidden-focus", Promise.resolve().then(() => (init_aria_hidden_focus(), aria_hidden_focus_exports))], - ["../audits/accessibility/aria-input-field-name", Promise.resolve().then(() => (init_aria_input_field_name(), aria_input_field_name_exports))], - ["../audits/accessibility/aria-meter-name", Promise.resolve().then(() => (init_aria_meter_name(), aria_meter_name_exports))], - ["../audits/accessibility/aria-progressbar-name", Promise.resolve().then(() => (init_aria_progressbar_name(), aria_progressbar_name_exports))], - ["../audits/accessibility/aria-prohibited-attr", Promise.resolve().then(() => (init_aria_prohibited_attr(), aria_prohibited_attr_exports))], - ["../audits/accessibility/aria-required-attr", Promise.resolve().then(() => (init_aria_required_attr(), aria_required_attr_exports))], - ["../audits/accessibility/aria-required-children", Promise.resolve().then(() => (init_aria_required_children(), aria_required_children_exports))], - ["../audits/accessibility/aria-required-parent", Promise.resolve().then(() => (init_aria_required_parent(), aria_required_parent_exports))], - ["../audits/accessibility/aria-roles", Promise.resolve().then(() => (init_aria_roles(), aria_roles_exports))], - ["../audits/accessibility/aria-text", Promise.resolve().then(() => (init_aria_text(), aria_text_exports))], - ["../audits/accessibility/aria-toggle-field-name", Promise.resolve().then(() => (init_aria_toggle_field_name(), aria_toggle_field_name_exports))], - ["../audits/accessibility/aria-tooltip-name", Promise.resolve().then(() => (init_aria_tooltip_name(), aria_tooltip_name_exports))], - ["../audits/accessibility/aria-treeitem-name", Promise.resolve().then(() => (init_aria_treeitem_name(), aria_treeitem_name_exports))], - ["../audits/accessibility/aria-valid-attr-value", Promise.resolve().then(() => (init_aria_valid_attr_value(), aria_valid_attr_value_exports))], - ["../audits/accessibility/aria-valid-attr", Promise.resolve().then(() => (init_aria_valid_attr(), aria_valid_attr_exports))], - ["../audits/accessibility/button-name", Promise.resolve().then(() => (init_button_name(), button_name_exports))], - ["../audits/accessibility/bypass", Promise.resolve().then(() => (init_bypass(), bypass_exports))], - ["../audits/accessibility/color-contrast", Promise.resolve().then(() => (init_color_contrast(), color_contrast_exports))], - ["../audits/accessibility/definition-list", Promise.resolve().then(() => (init_definition_list(), definition_list_exports))], - ["../audits/accessibility/dlitem", Promise.resolve().then(() => (init_dlitem(), dlitem_exports))], - ["../audits/accessibility/document-title", Promise.resolve().then(() => (init_document_title(), document_title_exports))], - ["../audits/accessibility/duplicate-id-aria", Promise.resolve().then(() => (init_duplicate_id_aria(), duplicate_id_aria_exports))], - ["../audits/accessibility/empty-heading", Promise.resolve().then(() => (init_empty_heading(), empty_heading_exports))], - ["../audits/accessibility/form-field-multiple-labels", Promise.resolve().then(() => (init_form_field_multiple_labels(), form_field_multiple_labels_exports))], - ["../audits/accessibility/frame-title", Promise.resolve().then(() => (init_frame_title(), frame_title_exports))], - ["../audits/accessibility/heading-order", Promise.resolve().then(() => (init_heading_order(), heading_order_exports))], - ["../audits/accessibility/html-has-lang", Promise.resolve().then(() => (init_html_has_lang(), html_has_lang_exports))], - ["../audits/accessibility/html-lang-valid", Promise.resolve().then(() => (init_html_lang_valid(), html_lang_valid_exports))], - ["../audits/accessibility/html-xml-lang-mismatch", Promise.resolve().then(() => (init_html_xml_lang_mismatch(), html_xml_lang_mismatch_exports))], - ["../audits/accessibility/identical-links-same-purpose", Promise.resolve().then(() => (init_identical_links_same_purpose(), identical_links_same_purpose_exports))], - ["../audits/accessibility/image-alt", Promise.resolve().then(() => (init_image_alt(), image_alt_exports))], - ["../audits/accessibility/image-redundant-alt", Promise.resolve().then(() => (init_image_redundant_alt(), image_redundant_alt_exports))], - ["../audits/accessibility/input-button-name", Promise.resolve().then(() => (init_input_button_name(), input_button_name_exports))], - ["../audits/accessibility/input-image-alt", Promise.resolve().then(() => (init_input_image_alt(), input_image_alt_exports))], - ["../audits/accessibility/label-content-name-mismatch", Promise.resolve().then(() => (init_label_content_name_mismatch(), label_content_name_mismatch_exports))], - ["../audits/accessibility/label", Promise.resolve().then(() => (init_label(), label_exports))], - ["../audits/accessibility/landmark-one-main", Promise.resolve().then(() => (init_landmark_one_main(), landmark_one_main_exports))], - ["../audits/accessibility/link-in-text-block", Promise.resolve().then(() => (init_link_in_text_block(), link_in_text_block_exports))], - ["../audits/accessibility/link-name", Promise.resolve().then(() => (init_link_name(), link_name_exports))], - ["../audits/accessibility/list", Promise.resolve().then(() => (init_list(), list_exports))], - ["../audits/accessibility/listitem", Promise.resolve().then(() => (init_listitem(), listitem_exports))], - ["../audits/accessibility/manual/custom-controls-labels", Promise.resolve().then(() => (init_custom_controls_labels(), custom_controls_labels_exports))], - ["../audits/accessibility/manual/custom-controls-roles", Promise.resolve().then(() => (init_custom_controls_roles(), custom_controls_roles_exports))], - ["../audits/accessibility/manual/focus-traps", Promise.resolve().then(() => (init_focus_traps(), focus_traps_exports))], - ["../audits/accessibility/manual/focusable-controls", Promise.resolve().then(() => (init_focusable_controls(), focusable_controls_exports))], - ["../audits/accessibility/manual/interactive-element-affordance", Promise.resolve().then(() => (init_interactive_element_affordance(), interactive_element_affordance_exports))], - ["../audits/accessibility/manual/logical-tab-order", Promise.resolve().then(() => (init_logical_tab_order(), logical_tab_order_exports))], - ["../audits/accessibility/manual/managed-focus", Promise.resolve().then(() => (init_managed_focus(), managed_focus_exports))], - ["../audits/accessibility/manual/offscreen-content-hidden", Promise.resolve().then(() => (init_offscreen_content_hidden(), offscreen_content_hidden_exports))], - ["../audits/accessibility/manual/use-landmarks", Promise.resolve().then(() => (init_use_landmarks(), use_landmarks_exports))], - ["../audits/accessibility/manual/visual-order-follows-dom", Promise.resolve().then(() => (init_visual_order_follows_dom(), visual_order_follows_dom_exports))], - ["../audits/accessibility/meta-refresh", Promise.resolve().then(() => (init_meta_refresh(), meta_refresh_exports))], - ["../audits/accessibility/meta-viewport", Promise.resolve().then(() => (init_meta_viewport(), meta_viewport_exports))], - ["../audits/accessibility/object-alt", Promise.resolve().then(() => (init_object_alt(), object_alt_exports))], - ["../audits/accessibility/select-name", Promise.resolve().then(() => (init_select_name(), select_name_exports))], - ["../audits/accessibility/skip-link", Promise.resolve().then(() => (init_skip_link(), skip_link_exports))], - ["../audits/accessibility/tabindex", Promise.resolve().then(() => (init_tabindex(), tabindex_exports))], - ["../audits/accessibility/table-duplicate-name", Promise.resolve().then(() => (init_table_duplicate_name(), table_duplicate_name_exports))], - ["../audits/accessibility/table-fake-caption", Promise.resolve().then(() => (init_table_fake_caption(), table_fake_caption_exports))], - ["../audits/accessibility/target-size", Promise.resolve().then(() => (init_target_size(), target_size_exports))], - ["../audits/accessibility/td-has-header", Promise.resolve().then(() => (init_td_has_header(), td_has_header_exports))], - ["../audits/accessibility/td-headers-attr", Promise.resolve().then(() => (init_td_headers_attr(), td_headers_attr_exports))], - ["../audits/accessibility/th-has-data-cells", Promise.resolve().then(() => (init_th_has_data_cells(), th_has_data_cells_exports))], - ["../audits/accessibility/valid-lang", Promise.resolve().then(() => (init_valid_lang(), valid_lang_exports))], - ["../audits/accessibility/video-caption", Promise.resolve().then(() => (init_video_caption(), video_caption_exports))], - ["../audits/clickjacking-mitigation", Promise.resolve().then(() => (init_clickjacking_mitigation(), clickjacking_mitigation_exports))], - ["../audits/csp-xss", Promise.resolve().then(() => (init_csp_xss(), csp_xss_exports))], - ["../audits/deprecations", Promise.resolve().then(() => (init_deprecations(), deprecations_exports))], - ["../audits/dobetterweb/charset", Promise.resolve().then(() => (init_charset(), charset_exports))], - ["../audits/dobetterweb/doctype", Promise.resolve().then(() => (init_doctype2(), doctype_exports2))], - ["../audits/dobetterweb/geolocation-on-start", Promise.resolve().then(() => (init_geolocation_on_start(), geolocation_on_start_exports))], - ["../audits/dobetterweb/inspector-issues", Promise.resolve().then(() => (init_inspector_issues2(), inspector_issues_exports2))], - ["../audits/dobetterweb/js-libraries", Promise.resolve().then(() => (init_js_libraries(), js_libraries_exports))], - ["../audits/dobetterweb/notification-on-start", Promise.resolve().then(() => (init_notification_on_start(), notification_on_start_exports))], - ["../audits/dobetterweb/paste-preventing-inputs", Promise.resolve().then(() => (init_paste_preventing_inputs(), paste_preventing_inputs_exports))], - ["../audits/errors-in-console", Promise.resolve().then(() => (init_errors_in_console(), errors_in_console_exports))], - ["../audits/has-hsts", Promise.resolve().then(() => (init_has_hsts(), has_hsts_exports))], - ["../audits/image-aspect-ratio", Promise.resolve().then(() => (init_image_aspect_ratio(), image_aspect_ratio_exports))], - ["../audits/image-size-responsive", Promise.resolve().then(() => (init_image_size_responsive(), image_size_responsive_exports))], - ["../audits/is-on-https", Promise.resolve().then(() => (init_is_on_https(), is_on_https_exports))], - ["../audits/origin-isolation", Promise.resolve().then(() => (init_origin_isolation(), origin_isolation_exports))], - ["../audits/redirects-http", Promise.resolve().then(() => (init_redirects_http(), redirects_http_exports))], - ["../audits/seo/canonical", Promise.resolve().then(() => (init_canonical(), canonical_exports))], - ["../audits/seo/crawlable-anchors", Promise.resolve().then(() => (init_crawlable_anchors(), crawlable_anchors_exports))], - ["../audits/seo/hreflang", Promise.resolve().then(() => (init_hreflang(), hreflang_exports))], - ["../audits/seo/http-status-code", Promise.resolve().then(() => (init_http_status_code(), http_status_code_exports))], - ["../audits/seo/is-crawlable", Promise.resolve().then(() => (init_is_crawlable(), is_crawlable_exports))], - ["../audits/seo/link-text", Promise.resolve().then(() => (init_link_text(), link_text_exports))], - ["../audits/seo/manual/structured-data", Promise.resolve().then(() => (init_structured_data(), structured_data_exports))], - ["../audits/seo/meta-description", Promise.resolve().then(() => (init_meta_description(), meta_description_exports))], - ["../audits/seo/robots-txt", Promise.resolve().then(() => (init_robots_txt2(), robots_txt_exports2))], - ["../audits/third-party-cookies", Promise.resolve().then(() => (init_third_party_cookies(), third_party_cookies_exports))], - ["../audits/trusted-types-xss", Promise.resolve().then(() => (init_trusted_types_xss(), trusted_types_xss_exports))], - ["../audits/valid-source-maps", Promise.resolve().then(() => (init_valid_source_maps(), valid_source_maps_exports))], - ["../computed/speedline", Promise.resolve().then(() => (init_speedline(), speedline_exports))], - ["../computed/metrics/timing-summary", Promise.resolve().then(() => (init_timing_summary(), timing_summary_exports))], - ["../computed/entity-classification", Promise.resolve().then(() => (init_entity_classification(), entity_classification_exports))], - ["../computed/trace-engine-result", Promise.resolve().then(() => (init_trace_engine_result(), trace_engine_result_exports))], - ["lighthouse-plugin-soft-navigation", Promise.resolve().then(() => (init_plugin(), plugin_exports))], - ["lighthouse-plugin-soft-navigation/audits/soft-nav-fcp", Promise.resolve().then(() => (init_soft_nav_fcp(), soft_nav_fcp_exports))], - ["lighthouse-plugin-soft-navigation/audits/soft-nav-lcp", Promise.resolve().then(() => (init_soft_nav_lcp(), soft_nav_lcp_exports))], - ["../gather/gatherers/bf-cache-failures", Promise.resolve().then(() => (init_bf_cache_failures(), bf_cache_failures_exports))], - ["../gather/gatherers/css-usage", Promise.resolve().then(() => (init_css_usage(), css_usage_exports))], - ["../gather/gatherers/full-page-screenshot", Promise.resolve().then(() => (init_full_page_screenshot(), full_page_screenshot_exports))], - ["../gather/gatherers/iframe-elements", Promise.resolve().then(() => (init_iframe_elements(), iframe_elements_exports))], - ["../gather/gatherers/js-usage", Promise.resolve().then(() => (init_js_usage(), js_usage_exports))], - ["../gather/gatherers/network-user-agent", Promise.resolve().then(() => (init_network_user_agent(), network_user_agent_exports))], - ["../gather/gatherers/stylesheets", Promise.resolve().then(() => (init_stylesheets(), stylesheets_exports))], - ["../gather/gatherers/trace-elements", Promise.resolve().then(() => (init_trace_elements(), trace_elements_exports))], - ["../gather/gatherers/trace", Promise.resolve().then(() => (init_trace(), trace_exports))], - ["../audits/autocomplete", Promise.resolve().then(() => (init_autocomplete(), autocomplete_exports))], - ["../audits/bf-cache", Promise.resolve().then(() => (init_bf_cache(), bf_cache_exports))], - ["../audits/bootup-time", Promise.resolve().then(() => (init_bootup_time(), bootup_time_exports))], - ["../audits/byte-efficiency/total-byte-weight", Promise.resolve().then(() => (init_total_byte_weight(), total_byte_weight_exports))], - ["../audits/byte-efficiency/unminified-css", Promise.resolve().then(() => (init_unminified_css(), unminified_css_exports))], - ["../audits/byte-efficiency/unminified-javascript", Promise.resolve().then(() => (init_unminified_javascript(), unminified_javascript_exports))], - ["../audits/byte-efficiency/unused-css-rules", Promise.resolve().then(() => (init_unused_css_rules(), unused_css_rules_exports))], - ["../audits/byte-efficiency/unused-javascript", Promise.resolve().then(() => (init_unused_javascript(), unused_javascript_exports))], - ["../audits/diagnostics", Promise.resolve().then(() => (init_diagnostics(), diagnostics_exports))], - ["../audits/final-screenshot", Promise.resolve().then(() => (init_final_screenshot(), final_screenshot_exports))], - ["../audits/insights/cache-insight", Promise.resolve().then(() => (init_cache_insight(), cache_insight_exports))], - ["../audits/insights/cls-culprits-insight", Promise.resolve().then(() => (init_cls_culprits_insight(), cls_culprits_insight_exports))], - ["../audits/insights/document-latency-insight", Promise.resolve().then(() => (init_document_latency_insight(), document_latency_insight_exports))], - ["../audits/insights/dom-size-insight", Promise.resolve().then(() => (init_dom_size_insight(), dom_size_insight_exports))], - ["../audits/insights/duplicated-javascript-insight", Promise.resolve().then(() => (init_duplicated_javascript_insight(), duplicated_javascript_insight_exports))], - ["../audits/insights/font-display-insight", Promise.resolve().then(() => (init_font_display_insight(), font_display_insight_exports))], - ["../audits/insights/forced-reflow-insight", Promise.resolve().then(() => (init_forced_reflow_insight(), forced_reflow_insight_exports))], - ["../audits/insights/image-delivery-insight", Promise.resolve().then(() => (init_image_delivery_insight(), image_delivery_insight_exports))], - ["../audits/insights/inp-breakdown-insight", Promise.resolve().then(() => (init_inp_breakdown_insight(), inp_breakdown_insight_exports))], - ["../audits/insights/lcp-breakdown-insight", Promise.resolve().then(() => (init_lcp_breakdown_insight(), lcp_breakdown_insight_exports))], - ["../audits/insights/lcp-discovery-insight", Promise.resolve().then(() => (init_lcp_discovery_insight(), lcp_discovery_insight_exports))], - ["../audits/insights/legacy-javascript-insight", Promise.resolve().then(() => (init_legacy_javascript_insight(), legacy_javascript_insight_exports))], - ["../audits/insights/modern-http-insight", Promise.resolve().then(() => (init_modern_http_insight(), modern_http_insight_exports))], - ["../audits/insights/network-dependency-tree-insight", Promise.resolve().then(() => (init_network_dependency_tree_insight(), network_dependency_tree_insight_exports))], - ["../audits/insights/render-blocking-insight", Promise.resolve().then(() => (init_render_blocking_insight(), render_blocking_insight_exports))], - ["../audits/insights/slow-css-selector-insight", Promise.resolve().then(() => (init_slow_css_selector_insight(), slow_css_selector_insight_exports))], - ["../audits/insights/third-parties-insight", Promise.resolve().then(() => (init_third_parties_insight(), third_parties_insight_exports))], - ["../audits/insights/viewport-insight", Promise.resolve().then(() => (init_viewport_insight(), viewport_insight_exports))], - ["../audits/layout-shifts", Promise.resolve().then(() => (init_layout_shifts(), layout_shifts_exports))], - ["../audits/long-tasks", Promise.resolve().then(() => (init_long_tasks(), long_tasks_exports))], - ["../audits/main-thread-tasks", Promise.resolve().then(() => (init_main_thread_tasks(), main_thread_tasks_exports))], - ["../audits/mainthread-work-breakdown", Promise.resolve().then(() => (init_mainthread_work_breakdown(), mainthread_work_breakdown_exports))], - ["../audits/metrics", Promise.resolve().then(() => (init_metrics2(), metrics_exports2))], - ["../audits/metrics/cumulative-layout-shift", Promise.resolve().then(() => (init_cumulative_layout_shift(), cumulative_layout_shift_exports))], - ["../audits/metrics/first-contentful-paint", Promise.resolve().then(() => (init_first_contentful_paint(), first_contentful_paint_exports))], - ["../audits/metrics/interaction-to-next-paint", Promise.resolve().then(() => (init_interaction_to_next_paint(), interaction_to_next_paint_exports))], - ["../audits/metrics/interactive", Promise.resolve().then(() => (init_interactive(), interactive_exports))], - ["../audits/metrics/largest-contentful-paint", Promise.resolve().then(() => (init_largest_contentful_paint(), largest_contentful_paint_exports))], - ["../audits/metrics/max-potential-fid", Promise.resolve().then(() => (init_max_potential_fid(), max_potential_fid_exports))], - ["../audits/metrics/speed-index", Promise.resolve().then(() => (init_speed_index(), speed_index_exports))], - ["../audits/metrics/total-blocking-time", Promise.resolve().then(() => (init_total_blocking_time(), total_blocking_time_exports))], - ["../audits/network-requests", Promise.resolve().then(() => (init_network_requests(), network_requests_exports))], - ["../audits/network-rtt", Promise.resolve().then(() => (init_network_rtt(), network_rtt_exports))], - ["../audits/network-server-latency", Promise.resolve().then(() => (init_network_server_latency(), network_server_latency_exports))], - ["../audits/non-composited-animations", Promise.resolve().then(() => (init_non_composited_animations(), non_composited_animations_exports))], - ["../audits/oopif-iframe-test-audit", Promise.resolve().then(() => (init_oopif_iframe_test_audit(), oopif_iframe_test_audit_exports))], - ["../audits/predictive-perf", Promise.resolve().then(() => (init_predictive_perf(), predictive_perf_exports))], - ["../audits/redirects", Promise.resolve().then(() => (init_redirects(), redirects_exports))], - ["../audits/resource-summary", Promise.resolve().then(() => (init_resource_summary(), resource_summary_exports))], - ["../audits/screenshot-thumbnails", Promise.resolve().then(() => (init_screenshot_thumbnails(), screenshot_thumbnails_exports))], - ["../audits/script-treemap-data", Promise.resolve().then(() => (init_script_treemap_data(), script_treemap_data_exports))], - ["../audits/server-response-time", Promise.resolve().then(() => (init_server_response_time(), server_response_time_exports))], - ["../audits/unsized-images", Promise.resolve().then(() => (init_unsized_images(), unsized_images_exports))], - ["../audits/user-timings", Promise.resolve().then(() => (init_user_timings(), user_timings_exports))] - ]); - __name(requireWrapper, "requireWrapper"); - __name(requireGatherer, "requireGatherer"); - __name(requireAudit, "requireAudit"); - __name(cleanFlagsForSettings, "cleanFlagsForSettings"); - __name(resolveSettings, "resolveSettings"); - __name(mergePlugins, "mergePlugins"); - __name(resolveGathererToDefn, "resolveGathererToDefn"); - __name(resolveAuditsToDefns, "resolveAuditsToDefns"); - __name(resolveModulePath, "resolveModulePath"); - __name(shallowClone, "shallowClone"); - __name(deepClone, "deepClone"); - __name(deepCloneConfigJson, "deepCloneConfigJson"); - } -}); +__name(deepCloneConfigJson, "deepCloneConfigJson"); // core/config/config.js -import path5 from "path"; +init_esm_utils(); +init_format(); +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var defaultConfigPath = path5.join( + "", + "../../config/default-config.js" +); +var internalArtifactPriorities = { + FullPageScreenshot: 1, + BFCacheFailures: 1 +}; function resolveWorkingCopy(config3, context) { let { configPath } = context; if (configPath && !path5.isAbsolute(configPath)) { @@ -50912,6 +50693,7 @@ function resolveWorkingCopy(config3, context) { configDir }; } +__name(resolveWorkingCopy, "resolveWorkingCopy"); function resolveExtensions(config3) { if (!config3.extends) return config3; if (config3.extends !== "lighthouse:default") { @@ -50927,6 +50709,7 @@ function resolveExtensions(config3) { ); return mergedConfig; } +__name(resolveExtensions, "resolveExtensions"); function resolveArtifactDependencies(artifact, gatherer, artifactDefnsBySymbol) { if (!("dependencies" in gatherer.instance.meta)) return void 0; const dependencies = Object.entries(gatherer.instance.meta.dependencies).map( @@ -50940,6 +50723,7 @@ function resolveArtifactDependencies(artifact, gatherer, artifactDefnsBySymbol) ); return Object.fromEntries(dependencies); } +__name(resolveArtifactDependencies, "resolveArtifactDependencies"); async function resolveArtifactsToDefns(artifacts, configDir) { if (!artifacts) return null; const status = { msg: "Resolve artifact definitions", id: "lh:config:resolveArtifactsToDefns" }; @@ -50968,6 +50752,7 @@ async function resolveArtifactsToDefns(artifacts, configDir) { lighthouse_logger_default.timeEnd(status); return artifactDefns; } +__name(resolveArtifactsToDefns, "resolveArtifactsToDefns"); function overrideSettingsForGatherMode(settings, gatherMode) { if (gatherMode === "timespan") { if (settings.throttlingMethod === "simulate") { @@ -50975,6 +50760,7 @@ function overrideSettingsForGatherMode(settings, gatherMode) { } } } +__name(overrideSettingsForGatherMode, "overrideSettingsForGatherMode"); function overrideThrottlingWindows(settings) { if (settings.throttlingMethod === "simulate") return; settings.cpuQuietThresholdMs = Math.max( @@ -50994,6 +50780,7 @@ function overrideThrottlingWindows(settings) { nonSimulatedSettingsOverrides.pauseAfterLoadMs ); } +__name(overrideThrottlingWindows, "overrideThrottlingWindows"); async function initializeConfig(gatherMode, config3, flags = {}) { const status = { msg: "Initialize config", id: "lh:config" }; lighthouse_logger_default.time(status, "verbose"); @@ -51017,57 +50804,33 @@ async function initializeConfig(gatherMode, config3, flags = {}) { lighthouse_logger_default.timeEnd(status); return { resolvedConfig }; } -var defaultConfigPath, internalArtifactPriorities; -var init_config = __esm({ - "core/config/config.js"() { - "use strict"; - init_process_global(); - init_lighthouse_logger(); - init_runner(); - init_default_config(); - init_constants(); - init_validation(); - init_filters(); - init_config_helpers(); - init_esm_utils(); - init_format(); - /** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - defaultConfigPath = path5.join( - "", - "../../config/default-config.js" - ); - internalArtifactPriorities = { - FullPageScreenshot: 1, - BFCacheFailures: 1 - }; - __name(resolveWorkingCopy, "resolveWorkingCopy"); - __name(resolveExtensions, "resolveExtensions"); - __name(resolveArtifactDependencies, "resolveArtifactDependencies"); - __name(resolveArtifactsToDefns, "resolveArtifactsToDefns"); - __name(overrideSettingsForGatherMode, "overrideSettingsForGatherMode"); - __name(overrideThrottlingWindows, "overrideThrottlingWindows"); - __name(initializeConfig, "initializeConfig"); - } -}); - -// replace-modules:/Users/alexrudenko/src/lighthouse/node_modules/@sentry/node/build/cjs/index.js -var cjs_exports = {}; -__export(cjs_exports, { - default: () => cjs_default -}); -var cjs_default; -var init_cjs = __esm({ - "replace-modules:/Users/alexrudenko/src/lighthouse/node_modules/@sentry/node/build/cjs/index.js"() { - init_process_global(); - cjs_default = {}; - } -}); +__name(initializeConfig, "initializeConfig"); // core/lib/sentry.js +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +var SENTRY_URL = "https://a6bb0da87ee048cc9ae2a345fc09ab2e:63a7029f46f74265981b7e005e0f69f8@sentry.io/174697"; +var SAMPLE_RATE = 0.01; +var noop = /* @__PURE__ */ __name(() => { +}, "noop"); +var sentryDelegate = { + init, + /** @type {(message: string, level?: SeverityLevel) => void} */ + captureMessage: noop, + /** @type {(breadcrumb: Breadcrumb) => void} */ + captureBreadcrumb: noop, + /** @type {() => any} */ + getContext: noop, + /** @type {(error: Error, options: {level?: string, tags?: {[key: string]: any}, extra?: {[key: string]: any}}) => Promise} */ + captureException: /* @__PURE__ */ __name(async () => { + }, "captureException"), + _shouldSample() { + return SAMPLE_RATE >= Math.random(); + } +}; async function init(opts) { if (!opts.flags.enableErrorReporting) { return; @@ -51144,49 +50907,16 @@ async function init(opts) { ); } } -var SENTRY_URL, SAMPLE_RATE, noop, sentryDelegate, Sentry; -var init_sentry = __esm({ - "core/lib/sentry.js"() { - "use strict"; - init_process_global(); - init_lighthouse_logger(); - init_config(); - /** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - SENTRY_URL = "https://a6bb0da87ee048cc9ae2a345fc09ab2e:63a7029f46f74265981b7e005e0f69f8@sentry.io/174697"; - SAMPLE_RATE = 0.01; - noop = /* @__PURE__ */ __name(() => { - }, "noop"); - sentryDelegate = { - init, - /** @type {(message: string, level?: SeverityLevel) => void} */ - captureMessage: noop, - /** @type {(breadcrumb: Breadcrumb) => void} */ - captureBreadcrumb: noop, - /** @type {() => any} */ - getContext: noop, - /** @type {(error: Error, options: {level?: string, tags?: {[key: string]: any}, extra?: {[key: string]: any}}) => Promise} */ - captureException: /* @__PURE__ */ __name(async () => { - }, "captureException"), - _shouldSample() { - return SAMPLE_RATE >= Math.random(); - } - }; - __name(init, "init"); - Sentry = sentryDelegate; - } -}); +__name(init, "init"); +var Sentry = sentryDelegate; + +// report/generator/report-generator.js +init_process_global(); // replace-modules:/Users/alexrudenko/src/lighthouse/report/generator/report-assets.js -var reportAssets; -var init_report_assets = __esm({ - "replace-modules:/Users/alexrudenko/src/lighthouse/report/generator/report-assets.js"() { - init_process_global(); - reportAssets = { - REPORT_TEMPLATE: `